예제 #1
0
def on_lookup_wadoku_expression():
    init_nachschlagen()
    try:
        # No argument means expression
        mw.nachschlagen.wadoku()
    except ValueError as ve:
        showInfo(str(ve))
예제 #2
0
파일: main.py 프로젝트: dae/anki
 def __init__(self, app, profileManager, opts, args):
     QMainWindow.__init__(self)
     self.state = "startup"
     self.opts = opts
     aqt.mw = self
     self.app = app
     self.pm = profileManager
     # init rest of app
     self.safeMode = self.app.queryKeyboardModifiers() & Qt.ShiftModifier
     try:
         self.setupUI()
         self.setupAddons()
     except:
         showInfo(_("Error during startup:\n%s") % traceback.format_exc())
         sys.exit(1)
     # must call this after ui set up
     if self.safeMode:
         tooltip(_("Shift key was held down. Skipping automatic "
                 "syncing and add-on loading."))
     # were we given a file to import?
     if args and args[0]:
         self.onAppMsg(args[0])
     # Load profile in a timer so we can let the window finish init and not
     # close on profile load error.
     if isWin:
         fn = self.setupProfileAfterWebviewsLoaded
     else:
         fn = self.setupProfile
     self.progress.timer(10, fn, False, requiresCollection=False)
예제 #3
0
def onSmartAnswer():
    card = mw.reviewer.card
    if not card:
        showInfo('Not in review now!')
        return
    easebutton = mw.col.sched.answerButtons(card)
    mw.reviewer._answerCard(easebutton)
예제 #4
0
파일: main.py 프로젝트: mstange/anki
    def loadProfile(self):
        # show main window
        if self.pm.profile['mainWindowState']:
            restoreGeom(self, "mainWindow")
            restoreState(self, "mainWindow")
        else:
            self.resize(500, 400)
        # toolbar needs to be retranslated
        self.toolbar.draw()
        # show and raise window for osx
        self.show()
        self.activateWindow()
        self.raise_()
        # maybe sync (will load DB)
        self.onSync(auto=True)
        # import pending?
        if self.pendingImport:
            if self.pm.profile['key']:
                showInfo(_("""\
To import into a password protected profile, please open the profile before attempting to import."""))
            else:
                import aqt.importing
                aqt.importing.importFile(self, self.pendingImport)
            self.pendingImport = None
        runHook("profileLoaded")
예제 #5
0
파일: addons.py 프로젝트: ChYi/ankiqt
    def disableObsoletePlugins(self):
        dir = self.pluginsFolder()
        native = _(
            "The %s plugin has been disabled, as Anki supports "+
            "this natively now.")
        plugins = [
            ("Custom Media Directory.py",
             (native % "custom media folder") + _(""" \
Please visit Settings>Preferences.""")),
            ("Regenerate Reading Field.py", _("""\
The regenerate reading field plugin has been disabled, as the Japanese \
support plugin supports this now. Please download the latest version.""")),
            ("Sync LaTeX with iPhone client.py",
             native % "sync LaTeX"),
            ("Incremental Reading.py",
             _("""The incremental reading plugin has been disabled because \
it needs updates.""")),
            ("Learn Mode.py", _("""\
The learn mode plugin has been disabled because it needs to be rewritten \
to work with this version of Anki."""))
            ]
        for p in plugins:
            path = os.path.join(dir, p[0])
            if os.path.exists(path):
                new = path.replace(".py", ".disabled")
                if os.path.exists(new):
                    os.unlink(new)
                os.rename(path, new)
                showInfo(p[1])
예제 #6
0
    def __init__(self):

        if USE_APPLESCRIPT is False:

            if not mw.col.conf.get(SETTING_TOKEN, False):
                # First run of the Plugin we did not save the access key yet
                client = EvernoteClient(
                    consumer_key='scriptkiddi-2682',
                    consumer_secret='965f1873e4df583c',
                    sandbox=False
                )
                request_token = client.get_request_token('https://fap-studios.de/anknotes/index.html')
                url = client.get_authorize_url(request_token)
                showInfo("We will open a Evernote Tab in your browser so you can allow access to your account")
                openLink(url)
                oauth_verifier = getText(prompt="Please copy the code that showed up, after allowing access, in here")[0]
                auth_token = client.get_access_token(
                    request_token.get('oauth_token'),
                    request_token.get('oauth_token_secret'),
                    oauth_verifier)
                mw.col.conf[SETTING_TOKEN] = auth_token
            else:
                auth_token = mw.col.conf.get(SETTING_TOKEN, False)

            self.token = auth_token
            self.client = EvernoteClient(token=auth_token, sandbox=False)
            self.noteStore = self.client.get_note_store()
예제 #7
0
    def _linkHandler(self, url):
        if ":" in url:
            (cmd, arg) = url.split(":")
        else:
            cmd = url
        if cmd == "open":
            self._selDeck(arg)
        elif cmd == "opts":
            self._showOptions(arg)
        elif cmd == "shared":
            self._onShared()
        elif cmd == "import":
            self.mw.onImport()
        elif cmd == "cram":
            self.mw.onCram()
        elif cmd == "create":
            showInfo(_("""\
To create a new deck, simply enter its name into any place that ask for \
a deck name, such as when adding notes, changing a card's deck while browsing, \
or importing text files."""))
        elif cmd == "drag":
            draggedDeckDid, ontoDeckDid = arg.split(',')
            self._dragDeckOnto(draggedDeckDid, ontoDeckDid)
        elif cmd == "collapse":
            self._collapse(arg)
예제 #8
0
 def check_command(command, command_type, options):
     if command_type in command:
         value = command[command_type]
         if value not in options:
             showInfo(error_message.format(command_type, value, command))
             return False
     return True
예제 #9
0
    def updateCollection(self):
        f = self.form
        d = self.mw.col

        if not isMac:
            wasAccel = self.mw.pm.glMode() != "software"
            wantAccel = f.hwAccel.isChecked()
            if wasAccel != wantAccel:
                if wantAccel:
                    self.mw.pm.setGlMode("auto")
                else:
                    self.mw.pm.setGlMode("software")
                showInfo(_("Changes will take effect when you restart Anki."))

        qc = d.conf
        qc['dueCounts'] = f.showProgress.isChecked()
        qc['estTimes'] = f.showEstimates.isChecked()
        qc['newSpread'] = f.newSpread.currentIndex()
        qc['nightMode'] = f.nightMode.isChecked()
        qc['timeLim'] = f.timeLimit.value()*60
        qc['collapseTime'] = f.lrnCutoff.value()*60
        qc['addToCur'] = not f.useCurrent.currentIndex()
        qc['dayLearnFirst'] = f.dayLearnFirst.isChecked()
        self._updateDayCutoff()
        self._updateSchedVer(f.newSched.isChecked())
        d.setMod()
예제 #10
0
def getVerse(self):
    ''' Lookup verse from ESV web-service and set results in current note.
    self should be set to Editor
    '''
    #open ESV api connection and run query against reference
    esv = EsvSession()
    if not esv.query(self.note[REF_FIELD]):
        #query did not return successfully
        showInfo("No such passage: %s" % (self.note[REF_FIELD]))
        return

    #Retrive audio into a temporary folder
    path = namedtmp(os.path.basename(esv.esvMp3Link), True)
    urllib.urlretrieve(esv.esvMp3Link, path)

    #set note fields
    self.note[AUDIO_FIELD] = self._addMedia(path)
    self.note[TEXT_FIELD] = esv.esvText
    self.note[REF_FIELD] = esv.esvRef
    self.note[HINT_FIELD] = ",".join(esv.esvText.split()[:5]).replace(",", " ")

    #set 'y' for any additional card types that need to be generated
    for cardName in ADDTL_CARDS:
        self.note[cardName] = 'y'

    #reload note, makes things show up
    self.loadNote()
def fill_sounds(collection, view_key):
    if view_key == "deckBrowser":
        return showInfo(u"First select one of your decks")

    query_str = "deck:current"
    d_scanned = 0
    d_success = 0
    d_failed = 0
    d_full = 0
    notes = Finder(collection).findNotes(query_str)
    mw.progress.start(immediate=True)
    for noteId in notes:
        d_scanned = d_scanned+1
        note = collection.getNote(noteId)
        note_dict = dict(note)      # edit_function routines require a dict
        if has_field(Sound_fields, note_dict):
            if get_any(Sound_fields, note_dict)=="":
                s = sound(note_dict["Hanzi"])
                if  "" == s:
                    d_failed = d_failed+1
                else:
                    set_all(Sound_fields, note_dict, to = s)
                    d_success = d_success+1
                # write back to note from dict and flush
                for f in Sound_fields:
                    if note_dict.has_key(f) and note_dict[f] <> note[f]:
                        note[f] = note_dict[f]
                        note.flush()
            else:
                d_full = d_full+1
    mw.progress.finish()
    msg_string = "%(empty)d/%(total)d empty Chinese notes in current deck<br>%(filled)d/%(empty)d notes were filled successfully<br>%(failed)d/%(empty)d notes fill failed."% {"empty":d_scanned-d_full, "total":d_scanned, "filled":d_success, "failed":d_failed}
    if d_failed>0:
        msg_string = msg_string+"<br><br>Please check your network connexion, or retry later."
    showInfo(msg_string)
예제 #12
0
def markdownconverter(arg = None):

    if arg is None:
        col = mw.col
    else:
        col = arg

    changed = 0
    # Iterate over the cards
    ids = col.findCards("tag:Markdown")
    for id in ids:
        card = col.getCard(id)
        note = card.note()
        for (name, value) in note.items():
            converted = ''
            converted = remade(value)
            #showInfo("%s:\n%s" % (name, converted) )
            note[name] = converted
        note.delTag("Markdown")
        ++changed
        note.flush()
    #   mw.reset()

    if arg is None:
        showInfo("Done: %d db" % changed)

    if changed > 0:
        return changed
예제 #13
0
  def getSubscribeDecks(self, subs):
  
    for sub in subs:
      try:
        jsonResponse = self.server.getDeck(sub)

        # Uncomment this line to see data in retrieved deck
        #showInfo('Success! Result is ' + str(jsonResponse[0]))
        if len(jsonResponse) > 0:
          deck = jsonResponse[0]
          cards = deck['cards']
          toFile = ''
          for card in cards:
            toFile += '%s; %s;\n' % (card['notes']['Front'], card['notes']['Back'])
          directory = os.path.dirname(__file__)
          filename = directory + '\import.txt'
          file = open(filename, 'w')
          file.write(toFile)
          file.close()
          self.importDeckFromCSV(filename, deck['name'])
          #self.deckCol.append(deck)    # Adds retrieved deck to internal AnkiHub Deck Collection
      except HTTPError, e:
        showInfo(str('Subscription Download Error: %d - %s' % (e.code, str(json.loads(e.read())))))
      except URLError, e:
        showInfo(str(e.args))
예제 #14
0
  def connect(self, endpoint):
    def connectAction():
      self.createLoadingScreen()

      self.username = mw.login.username.text()
      password = mw.login.password.text()

      try:
        jsonResponse = None
        if 'Login' in endpoint:
            jsonResponse = self.server.login(self.username, password)
        else:
            jsonResponse = self.server.signup(self.username, password)
        mw.login.close()
        self.username = jsonResponse['user']['username']
        self.sessionToken = jsonResponse['user']['sessionToken']
        showInfo('Success! Logged in as ' + jsonResponse['user']['username'])
        self.getSubscribeDecks(jsonResponse['user']['subscriptions'])
        self.processDecks()
        mw.loading.close()
        self.createSettings()
      except HTTPError, e:
        showInfo(str('%s Error: %d - %s' % (endpoint, e.code, json.loads(e.read()))))
      except URLError, e:
        showInfo(str(e.args))
예제 #15
0
def on_lookup_wadoku_selection():
    init_nachschlagen()
    try:
        # Empty list (or possibly 'None')  means selection
        mw.nachschlagen.wadoku([])
    except ValueError as ve:
        showInfo(str(ve))
예제 #16
0
 def clean(pl):
     if pl.poll() is not None:
         pl.wait()
         return False
     else:
         showInfo("Clean")
         return True
예제 #17
0
 def setup_client(self):
     auth_token = SETTINGS.EVERNOTE.AUTH_TOKEN.fetch()
     if not auth_token:
         # First run of the Plugin we did not save the access key yet
         secrets = {'holycrepe': '36f46ea5dec83d4a', 'scriptkiddi-2682': '965f1873e4df583c'}
         client = EvernoteClient(
             consumer_key=EVERNOTE.API.CONSUMER_KEY,
             consumer_secret=secrets[EVERNOTE.API.CONSUMER_KEY],
             sandbox=EVERNOTE.API.IS_SANDBOXED
         )
         request_token = client.get_request_token('https://fap-studios.de/anknotes/index.html')
         url = client.get_authorize_url(request_token)
         showInfo("We will open a Evernote Tab in your browser so you can allow access to your account")
         openLink(url)
         oauth_verifier = getText(prompt="Please copy the code that showed up, after allowing access, in here")[0]
         auth_token = client.get_access_token(
             request_token.get('oauth_token'),
             request_token.get('oauth_token_secret'),
             oauth_verifier)
         SETTINGS.EVERNOTE.AUTH_TOKEN.save(auth_token)
     else:
         client = EvernoteClient(token=auth_token, sandbox=EVERNOTE.API.IS_SANDBOXED)
     self.token = auth_token
     self.client = client
     log("Set up Evernote Client", 'client')
예제 #18
0
def my_keyHandler(self, evt):
    #global messageBuff
    global audio_speed, audio_replay
    
    key = unicode(evt.text())

    if key == "0":
        audio_speed = 1.0
    elif key == "[":
        audio_speed = max(0.1, audio_speed - 0.1)
    elif key == "]":
        audio_speed = min(4.0, audio_speed + 0.1)
    
    if key in "0[]":    
        if audio_replay:
            play(audio_file)
        elif anki.sound.mplayerManager is not None:
            if anki.sound.mplayerManager.mplayer is not None: 
                anki.sound.mplayerManager.mplayer.stdin.write("af_add scaletempo=stride=10:overlap=0.8\n")
                anki.sound.mplayerManager.mplayer.stdin.write(("speed_set %f \n" % audio_speed))
    
    if key == "p":
        anki.sound.mplayerManager.mplayer.stdin.write("pause\n")
    elif key == "l":
        audio_replay = not audio_replay
        if audio_replay:
            showInfo("Auto Replay ON")
        else:
            showInfo("Auto Replay OFF")
    
    if key == "r":
        anki.sound.mplayerClear = True
예제 #19
0
 def add_deck(self, pos):
     #TODO handle this case better
     if len(get_decks()) == len(self.app_settings.get('DeckEdit')):
         showInfo('exhausted all possible decks')
         return
     deck_edit_window = DeckEdit(self.app_settings, self)
     self._show_deck_edit(deck_edit_window)
예제 #20
0
파일: __main__.py 프로젝트: brumar/anknotes
 def __init__(self):
     if not mw.col.conf.get(SETTING_TOKEN, False):
         # First run of the Plugin we did not save the access key yet
         client = EvernoteClient(
             consumer_key='scriptkiddi-2682',
             consumer_secret='965f1873e4df583c',
             sandbox=False
         )
         request_token = client.get_request_token('http://brunomart.in/anknotes/index.html')
         url = client.get_authorize_url(request_token)
         showInfo("We will open a Evernote Tab in your browser so you can allow access to your account")
         openLink(url)
         oauth_verifier = getText(prompt="Please copy the code that showed up, after allowing access, in here")[0]
         secret_key = getText(prompt="protect your value with a password, it will be asked each time you import your notes")[0]
         auth_token = client.get_access_token(
             request_token.get('oauth_token'),
             request_token.get('oauth_token_secret'),
             oauth_verifier)
         mw.col.conf[SETTING_TOKEN] = encode(secret_key, auth_token)
     else:
         secret_key = getText(prompt="password")[0]
         auth_token_encoded = mw.col.conf.get(SETTING_TOKEN, False)
         auth_token = decode(secret_key, auth_token_encoded)
     self.token = auth_token
     self.client = EvernoteClient(token=auth_token, sandbox=False)
     self.noteStore = self.client.get_note_store()
예제 #21
0
def bulkReplace(self):
	""" Performs search-and-replace on selected notes """
	nids = self.selectedNotes()
	if not nids:
		return
	# Allow undo
	self.mw.checkpoint(_("Fix word wrap on selected cards (remove non-breaking space)"))
	self.mw.progress.start()
	# Not sure if beginReset is required
	self.model.beginReset()
	changed = self.col.findReplace(nids, # Selected note IDs
		'&nbsp;', # from
		' ',  # to whitespace
		True, # treat as regular expression
		None, # all note fields
		True) # case insensitivity
	self.model.endReset()
	self.mw.progress.finish()
	# Display a progress meter
	showInfo(ngettext(
            "%(a)d of %(b)d note updated",
            "%(a)d of %(b)d notes updated", len(nids)) % {
                'a': changed,
                'b': len(nids),
            })
예제 #22
0
파일: editor.py 프로젝트: WangHanbin/anki
    def onCloze(self):
        # check that the model is set up for cloze deletion
        if not re.search("{{(.*:)*cloze:", self.note.model()["tmpls"][0]["qfmt"]):
            if self.addMode:
                tooltip(_("Warning, cloze deletions will not work until " "you switch the type at the top to Cloze."))
            else:
                showInfo(
                    _(
                        """\
To make a cloze deletion on an existing note, you need to change it \
to a cloze type first, via Edit>Change Note Type."""
                    )
                )
                return
        # find the highest existing cloze
        highest = 0
        for name, val in self.note.items():
            m = re.findall("\{\{c(\d+)::", val)
            if m:
                highest = max(highest, sorted([int(x) for x in m])[-1])
        # reuse last?
        if not self.mw.app.keyboardModifiers() & Qt.AltModifier:
            highest += 1
        # must start at 1
        highest = max(1, highest)
        self.web.eval("wrap('{{c%d::', '}}');" % highest)
예제 #23
0
파일: main.py 프로젝트: mstange/anki
 def __init__(self, app, profileManager, args):
     QMainWindow.__init__(self)
     self.state = "startup"
     aqt.mw = self
     self.app = app
     if isWin:
         self._xpstyle = QStyleFactory.create("WindowsXP")
         self.app.setStyle(self._xpstyle)
     self.pm = profileManager
     # running 2.0 for the first time?
     if self.pm.meta['firstRun']:
         # load the new deck user profile
         self.pm.load(self.pm.profiles()[0])
         # upgrade if necessary
         from aqt.upgrade import Upgrader
         u = Upgrader(self)
         u.maybeUpgrade()
         self.pm.meta['firstRun'] = False
         self.pm.save()
     # init rest of app
     try:
         self.setupUI()
         self.setupAddons()
     except:
         showInfo(_("Error during startup:\n%s") % traceback.format_exc())
         sys.exit(1)
     # were we given a file to import?
     if args and args[0]:
         self.onAppMsg(unicode(args[0], "utf8", "ignore"))
     # Load profile in a timer so we can let the window finish init and not
     # close on profile load error.
     self.progress.timer(10, self.setupProfile, False)
예제 #24
0
 def remGroup(self):
     if self.conf['id'] == 1:
         showInfo(_("The default configuration can't be removed."), self)
     else:
         self.mw.col.decks.remConf(self.conf['id'])
         self.deck['conf'] = 1
         self.loadConfs()
예제 #25
0
파일: gimg.py 프로젝트: visual000/misc
    def loadImages(self):
        query = getTextFromHTML(self.parent.editor.note["Front"])
        query = "".join(x for x in query if x.isalnum())

        # NOTE: Google returns a different table-based page structure when using urllib with the above user agent.
        # 		Keep this in mind when editing the scraper.
        opener = urllib2.build_opener()
        opener.addheaders = [("Accept Language", "en-GB,en-US;q=0.8,en;q=0.6"), ("User-agent", "Mozilla/5.0")]

        try:
            page = opener.open("http://www.google.com/search?tbm=isch&q=" + query)
        except:
            # TODO print error msg
            self.close()
            showInfo("Error downloading images")
            return

        imageContainer = BeautifulSoup(page.read()).find("table", {"class": "images_table"})
        images = imageContainer.findAll("img", limit=15)

        for image in images:
            imgFile = tempfile.NamedTemporaryFile(prefix=queryClean, suffix=".jpg")
            imgFile.seek(0)
            imgFile.write(urllib2.urlopen(image["src"]).read())
            imgFile.flush()

            imgWidget = ClickableImage(imgFile)
            # self.destroyed.connect(imgWidget.close) # XXX: not working
            # mw.connect(self, SIGNAL("close"), imgWidget.close)
            mw.connect(imgWidget, SIGNAL("clicked"), self.selectImage)
            self.layout.addWidget(imgWidget)
            imgWidget.show()
예제 #26
0
파일: main.py 프로젝트: terrisage/Anki
 def __init__(self, app, profileManager, args):
     QMainWindow.__init__(self)
     self.state = "startup"
     aqt.mw = self
     self.app = app
     self.pm = profileManager
     # running 2.0 for the first time?
     if self.pm.meta['firstRun']:
         # load the new deck user profile
         self.pm.load(self.pm.profiles()[0])
         self.pm.meta['firstRun'] = False
         self.pm.save()
     # init rest of app
     self.safeMode = self.app.queryKeyboardModifiers() & Qt.ShiftModifier
     try:
         self.setupUI()
         self.setupAddons()
     except:
         showInfo(_("Error during startup:\n%s") % traceback.format_exc())
         sys.exit(1)
     # must call this after ui set up
     if self.safeMode:
         tooltip(_("Shift key was held down. Skipping automatic "
                 "syncing and add-on loading."))
     # were we given a file to import?
     if args and args[0]:
         self.onAppMsg(args[0])
     # Load profile in a timer so we can let the window finish init and not
     # close on profile load error.
     self.progress.timer(10, self.setupProfile, False)
예제 #27
0
def checkCollection(col=None, force=False):
    """Check for unreported cards and send them to beeminder."""
    col = col or mw.col
    if col is None:
        return

    # reviews
    if REP_GOAL:
        reps           = col.db.first("select count() from revlog")[0]
        last_timestamp = col.conf.get("beeminderRepTimestamp", 0)
        timestamp      = col.db.first("select id/1000 from revlog order by id desc limit 1")
        if timestamp is not None:
            timestamp = timestamp[0]
        reportCards(col, reps, timestamp, "beeminderRepTotal", REP_GOAL, REP_OFFSET)

        if (force or timestamp != last_timestamp) and SEND_DATA:
            col.conf["beeminderRepTimestamp"] = timestamp
            col.setMod()

    # new cards
    if NEW_GOAL:
        new_cards      = col.db.first("select count(distinct(cid)) from revlog where type = 0")[0]
        last_timestamp = col.conf.get("beeminderNewTimestamp", 0)
        timestamp      = col.db.first("select id/1000 from revlog where type = 0 order by id desc limit 1")
        if timestamp is not None:
            timestamp = timestamp[0]
        reportCards(col, new_cards, timestamp, "beeminderNewTotal", NEW_GOAL, NEW_OFFSET)

        if (force or timestamp != last_timestamp) and SEND_DATA:
            col.conf["beeminderNewTimestamp"] = timestamp
            col.setMod()

    if force and (REP_GOAL or NEW_GOAL):
        showInfo("Synced with Beeminder.")
예제 #28
0
파일: main.py 프로젝트: terrisage/Anki
    def loadProfile(self):
        # show main window
        if self.pm.profile['mainWindowState']:
            restoreGeom(self, "mainWindow")
            restoreState(self, "mainWindow")
        # toolbar needs to be retranslated
        self.toolbar.draw()
        # titlebar
        self.setWindowTitle("Anki - " + self.pm.name)
        # show and raise window for osx
        self.show()
        self.activateWindow()
        self.raise_()
        # maybe sync (will load DB)
        if self.pendingImport and os.path.basename(
                self.pendingImport).startswith("backup-"):
            # skip sync when importing a backup
            self.loadCollection()
        else:
            self.onSync(auto=True)
        # import pending?
        if self.pendingImport:
            if self.pm.profile['key']:
                showInfo(_("""\
To import into a password protected profile, please open the profile before attempting to import."""))
            else:
                self.handleImport(self.pendingImport)

            self.pendingImport = None
        runHook("profileLoaded")
예제 #29
0
  def getTransactions(self, gid):
    try:
      jsonResponse = self.server.getTransactions(gid)
      return jsonResponse

    except HTTPError, e:
      showInfo(str('Transaction Download Error: %d - %s' % (e.code, str(json.loads(e.read())))))
예제 #30
0
파일: main.py 프로젝트: terrisage/Anki
    def onAppMsg(self, buf):
        if self.state == "startup":
            # try again in a second
            return self.progress.timer(1000, lambda: self.onAppMsg(buf), False)
        elif self.state == "profileManager":
            # can't raise window while in profile manager
            if buf == "raise":
                return
            self.pendingImport = buf
            return tooltip(_("Deck will be imported when a profile is opened."))
        if not self.interactiveState() or self.progress.busy():
            # we can't raise the main window while in profile dialog, syncing, etc
            if buf != "raise":
                showInfo(_("""\
Please ensure a profile is open and Anki is not busy, then try again."""),
                     parent=None)
            return
        # raise window
        if isWin:
            # on windows we can raise the window by minimizing and restoring
            self.showMinimized()
            self.setWindowState(Qt.WindowActive)
            self.showNormal()
        else:
            # on osx we can raise the window. on unity the icon in the tray will just flash.
            self.activateWindow()
            self.raise_()
        if buf == "raise":
            return
        # import
        self.handleImport(buf)
예제 #31
0
파일: main.py 프로젝트: fossabot/anki
    def handleImport(self, path):
        import aqt.importing
        if not os.path.exists(path):
            return showInfo(_("Please use File>Import to import this file."))

        aqt.importing.importFile(self, path)
예제 #32
0
def testFunction():
    # get the number of cards in the current collection, which is stored in
    # the main window
    cardCount = mw.col.cardCount()
    # show a message box
    showInfo("Card count: %d" % cardCount)
예제 #33
0
파일: customstudy.py 프로젝트: zjulyx/anki
 def accept(self):
     f = self.form
     i = self.radioIdx
     spin = f.spin.value()
     if i == RADIO_NEW:
         self.deck["extendNew"] = spin
         self.mw.col.decks.save(self.deck)
         self.mw.col.sched.extendLimits(spin, 0)
         self.mw.reset()
         return QDialog.accept(self)
     elif i == RADIO_REV:
         self.deck["extendRev"] = spin
         self.mw.col.decks.save(self.deck)
         self.mw.col.sched.extendLimits(0, spin)
         self.mw.reset()
         return QDialog.accept(self)
     elif i == RADIO_CRAM:
         tags = self._getTags()
     # the rest create a filtered deck
     cur = self.mw.col.decks.byName(tr(
         TR.CUSTOM_STUDY_CUSTOM_STUDY_SESSION))
     if cur:
         if not cur["dyn"]:
             showInfo(tr(TR.CUSTOM_STUDY_MUST_RENAME_DECK))
             return QDialog.accept(self)
         else:
             # safe to empty
             self.mw.col.sched.empty_filtered_deck(cur["id"])
             # reuse; don't delete as it may have children
             dyn = cur
             self.mw.col.decks.select(cur["id"])
     else:
         did = self.mw.col.decks.new_filtered(
             tr(TR.CUSTOM_STUDY_CUSTOM_STUDY_SESSION))
         dyn = self.mw.col.decks.get(did)
     # and then set various options
     if i == RADIO_FORGOT:
         dyn["terms"][0] = ["rated:%d:1" % spin, DYN_MAX_SIZE, DYN_RANDOM]
         dyn["resched"] = False
     elif i == RADIO_AHEAD:
         dyn["terms"][0] = ["prop:due<=%d" % spin, DYN_MAX_SIZE, DYN_DUE]
         dyn["resched"] = True
     elif i == RADIO_PREVIEW:
         dyn["terms"][0] = [
             "is:new added:%s" % spin, DYN_MAX_SIZE, DYN_OLDEST
         ]
         dyn["resched"] = False
     elif i == RADIO_CRAM:
         type = f.cardType.currentRow()
         if type == TYPE_NEW:
             terms = "is:new "
             ord = DYN_ADDED
             dyn["resched"] = True
         elif type == TYPE_DUE:
             terms = "is:due "
             ord = DYN_DUE
             dyn["resched"] = True
         elif type == TYPE_REVIEW:
             terms = "-is:new "
             ord = DYN_RANDOM
             dyn["resched"] = True
         else:
             terms = ""
             ord = DYN_RANDOM
             dyn["resched"] = False
         dyn["terms"][0] = [(terms + tags).strip(), spin, ord]
     # add deck limit
     dyn["terms"][0][0] = 'deck:"%s" %s ' % (self.deck["name"],
                                             dyn["terms"][0][0])
     self.mw.col.decks.save(dyn)
     # generate cards
     self.created_custom_study = True
     if not self.mw.col.sched.rebuild_filtered_deck(dyn["id"]):
         return showWarning(
             tr(TR.CUSTOM_STUDY_NO_CARDS_MATCHED_THE_CRITERIA_YOU))
     self.mw.moveToState("overview")
     QDialog.accept(self)
예제 #34
0
def get_definition(editor):
    # ideally, users wouldn't have to do this, but the API limit is just 1000 calls/day. That could easily happen with just a few users.
    if (MERRIAM_WEBSTER_API_KEY == "YOUR_KEY_HERE"):
        message = "AutoDefine requires use of Merriam-Webster's Collegiate Dictionary with Audio API. To get functionality working:\n"
        message += "1. Go to www.dictionaryapi.com and sign up for an account, requesting access to the Collegiate Dictionary.\n"
        message += "2. In Anki, go to Tools>Add-Ons>AutoDefine>Edit... and replace YOUR_KEY_HERE with your unique API key.\n"
        showInfo(message)
        return

    # Random Anki loading
    editor.loadNote()
    editor.web.setFocus()
    editor.web.eval("focusField(0);")
    editor.web.eval("caretToEnd();")
    allFields = editor.note.fields

    word = allFields[0]

    url = "http://www.dictionaryapi.com/api/v1/references/collegiate/xml/" + word + "?key=" + MERRIAM_WEBSTER_API_KEY
    etree = ET.parse(urllib.urlopen(url))
    allEntries = etree.findall("entry")

    definitionArray = []

    if (INSERT_PRONUNCIATIONS):
        # Parse all unique pronunciations, and convert them to URLs as per http://goo.gl/nL0vte
        allSounds = []
        for entry in allEntries:
            if entry.attrib["id"][:len(word)+1] == word + "[" or entry.attrib["id"] == word:
                for wav in entry.findall("sound/wav"):
                    rawWav = wav.text
                    # API-specific URL conversions
                    if rawWav[:3] == "bix":
                        midURL = "bix"
                    elif rawWav[:2] == "gg":
                        midURL = "gg"
                    elif rawWav[:1].isdigit():
                        midURL = "number"
                    else:
                        midURL = rawWav[:1]
                    wavURL = "http://media.merriam-webster.com/soundc11/" + midURL + "/" + rawWav
                    allSounds.append(editor.urlToFile(wavURL).strip())
        
        # we want to make this a non-duplicate set, so that we only get unique sound files.
        allSounds = OrderedSet(allSounds)
        for soundLocalFilename in reversed(allSounds):
            allFields[0] += '[sound:' + soundLocalFilename + ']'

    # Extract the type of word this is
    for entry in allEntries:
        if entry.attrib["id"][:len(word)+1] == word + "[" or entry.attrib["id"] == word:
            thisDef = entry.find("def")
            fl = entry.find("fl").text
            if fl == "verb":
                fl = "v."
            elif fl == "noun":
                fl = "n."
            elif fl == "adverb":
                fl = "adv."
            elif fl == "adjective":
                fl = "adj."

            thisDef.tail = "<b>" + fl + "</b>" # save the functional label (noun/verb/etc) in the tail

            # the <ssl> tag will contain the word 'obsolete' if the term is not in use anymore. However, for some reason, the tag
            # precedes the <dt> that it is associated with instead of being a child. We need to associate it here so that later
            # we can either remove or keep it regardless.
            previousWasSSL = False
            for child in thisDef:
                # this is a kind of poor way of going about things, but the ElementTree API doesn't seem to offer an alternative.
                if child.text == "obsolete" and child.tag == "ssl":
                    previousWasSSL = True
                if previousWasSSL and child.tag == "dt":
                    child.tail = "obsolete"
                    previousWasSSL = False


            definitionArray.append(thisDef)

    toReturn = ""
    for definition in definitionArray:
        lastFunctionalLabel = ""
        toPrint = ""
        for dtTag in definition.findall("dt"):

            if dtTag.tail == "obsolete":
                dtTag.tail = "" #take away the tail word so that when printing it does not show up.
                if IGNORE_ARCHAIC:
                    continue


            # We don't really care for 'verbal illustrations' or 'usage notes', even though they are occasionally useful.
            for usageNote in dtTag.findall("un"):
                dtTag.remove(usageNote)
            for verbalIllustration in dtTag.findall("vi"):
                dtTag.remove(verbalIllustration)

            # Directional cross reference doesn't make sense for us
            for dxTag in dtTag.findall("dx"):
                for dxtTag in dxTag.findall("dxt"):
                    for dxnTag in dxtTag.findall("dxn"):
                        dxtTag.remove(dxnTag)

            toPrint = ET.tostring(dtTag, "", "xml").strip() # extract raw XML from <dt>...</dt>
            toPrint = toPrint.replace("<sx>", "; ") # attempt to remove 'synonymous cross reference tag' and replace with semicolon
            toPrint = toPrint.replace("<dx>", "; ") # attempt to remove 'Directional cross reference tag' and replace with semicolon
            toPrint = re.sub('<[^>]*>', '', toPrint) # remove all other XML tags
            toPrint = re.sub(':', '', toPrint) # remove all colons, since they are usually useless and have been replaced with semicolons above
            toPrint = toPrint.replace(" ; ", "; ").strip() # erase space between semicolon and previous word, if exists, and strip any extraneous whitespace
            toPrint += "<br>\n"

            # add verb/noun/adjective
            if (lastFunctionalLabel != definition.tail):
                toPrint = definition.tail + " " + toPrint
                # but don't add an extra carriage return for the first definition
                #if (definition != definitionArray[0]):
                #    toPrint = "<br>\n" + toPrint
            lastFunctionalLabel = definition.tail
            toReturn += toPrint

    # final cleanup of <sx> tag bs
    toReturn = toReturn.replace(".</b> ; ", ".</b> ") #<sx> as first definition after "n. " or "v. "
    toReturn = toReturn.replace("\n; ", "\n") #<sx> as first definition after newline

    allFields[1] = toReturn
    editor.web.eval("setFields(%s, %d);" % (allFields, 0))

    # not sure exactly how saving works, but focusing different fields seems to help.
    editor.loadNote()
    editor.web.eval("focusField(0);")
    editor.web.eval("focusField(1);")
    editor.web.eval("focusField(0);")
    if (OPEN_IMAGES_IN_BROWSER):
        webbrowser.open("https://www.google.com/search?q= "+ word + "&safe=off&tbm=isch&tbs=isz:lt,islt:xga", 0, False)
    def showDialog(self, currentCard=None):
        # Handle for dialog open without a current card from IR model
        did = None
        cid = None
        if not currentCard:
            deck = mw._selectedDeck()
            did = deck['id']
        else:
            did = currentCard.did
            cid = currentCard.id

        cardDataList = self.getCardDataList(did, cid)
        if not cardDataList:
            showInfo(_('Please select an Incremental Reading deck.'))
            return

        d = QDialog(mw)
        l = QVBoxLayout()
        w = AnkiWebView()
        l.addWidget(w)

        script = '''
        var cardList = new Array();
        '''
        index = 0
        for cardData in cardDataList:
            index += 1
            script += "card = new Object();"
            script += "card.id = " + str(cardData['id']) + ";"
            script += "card.title = '" + str(cardData['title']) + "';"
            script += "card.isCurrent = " + str(cardData['isCurrent']) + ";"
            script += "card.checkbox = document.createElement('input');"
            script += "card.checkbox.type = 'checkbox';"
            if cardData['isCurrent'] == 'true':
                script += "card.checkbox.setAttribute('checked', 'true');"
            script += "cardList[cardList.length] = card;"

        script += """
        function buildCardData() {
            var container = document.getElementById('cardList');
            container.innerHTML = '';
            var list = document.createElement('div');
            list.setAttribute('style','overflow:auto;');
            var table = document.createElement('table');
            list.appendChild(table);
            container.appendChild(list);
            var row;
            var col;
            var cardData;
            for (var i = 0; i < cardList.length; i++) {
                row = document.createElement('tr');
                row.setAttribute('id','row' + i);
                cardData = cardList[i];

                col = document.createElement('td');
                col.setAttribute('style','width:4em;');
                col.innerHTML = '' + i;
                row.appendChild(col);

                col = document.createElement('td');
                col.setAttribute('style','width:10em;');
                col.innerHTML = '' + cardData.id;
                row.appendChild(col);

                col = document.createElement('td');
                col.setAttribute('style','width:30em;');
                col.innerHTML = '' + cardData.title;
                row.appendChild(col);

                col = document.createElement('td');
                col.setAttribute('style','width:2em;');
                col.appendChild(cardData.checkbox);
                row.appendChild(col);

                table.appendChild(row);
            }
        }

        function reposition(origIndex, newIndex, isTopOfRange) {
            if (newIndex < 0 || newIndex > (cardList.length-1)) return -1;
            if (cardList[newIndex].checkbox.checked) return -1;

            if (isTopOfRange) {
                document.getElementById('newPos').value = newIndex;
            }
            var removedCards = cardList.splice(origIndex,1);
            cardList.splice(newIndex, 0, removedCards[0]);
            return newIndex;
        }

        function moveSelectedUp() {
            var topOfRange = -1;
            for (var i = 0; i < cardList.length; i++) {
                if (cardList[i].checkbox.checked) {
                    if (topOfRange == -1) {
                        topOfRange = i;
                    }
                    if (i == topOfRange) {
                        if (document.getElementById('anchor').checked) {
                            continue; //Don't move end of range if anchored.
                        } else {
                            reposition(i, i - 1, true);
                        }
                    } else {
                        reposition(i, i - 1, false);
                    }
                }
            }
            buildCardData();
        }

        function moveSelectedDown() {
            var topOfRange = -1;
            var bottomOfRange = -1;
            for (var i = 0; i < cardList.length; i++) {
                if (cardList[i].checkbox.checked) {
                    if (topOfRange == -1) {
                        topOfRange = i;
                    }
                    bottomOfRange = i;
                }
            }
            for (var i = cardList.length-1; i > -1; i--) {
                if (cardList[i].checkbox.checked) {
                    if (i == bottomOfRange &&
                            document.getElementById('anchor').checked) {
                        continue; //Don't move end of range if anchored.
                    }
                    if (i == topOfRange) {
                        reposition(i, i + 1, true);
                    } else {
                        reposition(i, i + 1, false);
                    }
                }
            }
            buildCardData();
        }

        function selectAll() {
            for (var i = 0; i < cardList.length; i++) {
                cardList[i].checkbox.checked = true;
            }
        }

        function selectNone() {
            for (var i = 0; i < cardList.length; i++) {
                cardList[i].checkbox.checked = false;
            }
        }

        function directMove() {
            var newIndex = document.getElementById('newPos').value;
            var topOfRange = -1;
            origIndex = -1;
            for (var i = 0; i < cardList.length; i++) {
                if (cardList[i].checkbox.checked) {
                    if (topOfRange == -1) {
                        topOfRange = i;
                    }
                    if (origIndex == -1) {
                        origIndex = i;
                        sizeOfMove = (newIndex - origIndex);
                    }
                }
            }
            if (sizeOfMove < 0) {
                for (var i = 0; i < cardList.length; i++) {
                    if (cardList[i].checkbox.checked) {
                        if (i == topOfRange) {
                            reposition(i, i + sizeOfMove, true);
                        } else {
                            reposition(i, i + sizeOfMove, false);
                        }
                    }
                }
            } else {
                for (var i = cardList.length-1; i > -1; i--) {
                    if (cardList[i].checkbox.checked) {
                        if (i == topOfRange) {
                            reposition(i, i + sizeOfMove, true);
                        } else {
                            reposition(i, i + sizeOfMove, false);
                        }
                    }
                }
            }
            buildCardData();
        }

        function updatePositions() {
            var cids = new Array();
            for (var i=0; i < cardList.length; i++) {
                cids[cids.length] = parseInt(cardList[i].id);
            }
            return cids.join();
        };
        """

        newPosField = "<span style='font-weight:bold'>Card Position: </span><input type='text' id='newPos' size='5' value='0' />&nbsp;<span style='font-weight:bold'>of " + str(
            len(cardDataList)) + "</span>&nbsp;&nbsp;"
        newPosField += "<input type='button' value='Apply' onclick='directMove()' />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='font-weight:bold'>Pin Top/Bottom? </span><input type='checkbox' id='anchor'/>"

        upDownButtons = "<input type='button' value='Move Up' onclick='moveSelectedUp()'/><input type='button' value='Move Down' onclick='moveSelectedDown()'/>"
        upDownButtons += "<input type='button' value='Select All' onclick='selectAll()'/><input type='button' value='Select None' onclick='selectNone()'/>"

        html = "<html><head><script>" + script + "</script></head><body onLoad='buildCardData()'>"
        html += "<p>" + newPosField
        html += "<p>" + upDownButtons
        html += "<div id='cardList'></div>"
        html += "</body></html>"
        w.stdHtml(html)
        bb = QDialogButtonBox(QDialogButtonBox.Close | QDialogButtonBox.Save)
        bb.accepted.connect(d.accept)
        bb.rejected.connect(d.reject)
        bb.setOrientation(Qt.Horizontal)
        l.addWidget(bb)
        d.setLayout(l)
        d.setWindowModality(Qt.WindowModal)
        d.resize(500, 500)
        choice = d.exec_()
        if choice == 1:
            if ANKI_21:
                cids = w.page().runJavaScript('updatePositions()',
                                              self.callback)
            else:
                cids = w.page().mainFrame().evaluateJavaScript(
                    'updatePositions()')
                self.repositionCards(cids)
        elif currentCard:
            self.repositionCard(currentCard, -1)
예제 #36
0
 def onLangIdxChanged(self, idx):
     code = anki.lang.langs[idx][1]
     self.mw.pm.setLang(code)
     showInfo(_("Please restart Anki to complete language change."), parent=self)
    def _on_accept(self):

        if self._handle_save_to_default:
            params = {
                'num_audios': self.num_audios.text(),
                'num_plays': self.num_plays.text(),
                'num_copies': self.num_copies.text(),
                'default_waiting_time': self.default_waiting_time.text(),
                'additional_waiting_time': self.additional_waiting_time.text(),
                'sample_rate': self.sample_rate.text(),
            }
            dump_file = open('params', 'wb')
            dump(params, dump_file)
        path = None
        directory = None

        if not self.advance_mode:
            dialog = SaveFileDialog(self.deck_selection.currentText().replace(
                "::", "_"))
            path = dialog.filename
            if path == None:
                return
        else:
            init_directory = expanduser("~/Desktop")
            directory = str(
                QFileDialog.getExistingDirectory(
                    self, "Select directory to save outputs", init_directory,
                    QFileDialog.ShowDirsOnly))

        CustomMessageBox.showWithTimeout(1,
                                         "Start exporting",
                                         "Notification",
                                         icon=QMessageBox.Information,
                                         buttons=QMessageBox.Ok)
        combines = []
        names = []
        num_cps = []
        if self.advance_mode:
            with open(self.path) as f:
                i = 0
                for line in f:
                    if i == 0:
                        i += 1
                        continue
                    splitted_fields = line.split(',')
                    deck_name = splitted_fields[0]
                    num_audios = int(splitted_fields[1].strip())
                    num_plays = int(splitted_fields[2].strip())
                    num_copies = int(splitted_fields[3].strip())
                    default_waiting_time = float(splitted_fields[4].strip())
                    additional_waiting_time = float(splitted_fields[5].strip())
                    mode = splitted_fields[6].strip()
                    output_name = splitted_fields[7].strip()
                    channel = channel_map[self.channel.currentText()]
                    combines = generate_audio(deck_name, num_audios, num_plays,
                                              num_copies, default_waiting_time,
                                              additional_waiting_time, mode,
                                              self.change_channel, channel)
                    if '.mp3' not in output_name:
                        output_name += '.mp3'
                    if num_copies == 1:
                        combine = combines[0]
                        if platform.system() == 'Windows':
                            combine.export(directory + '\\' + output_name,
                                           format='mp3',
                                           parameters=['-ac',
                                                       str(channel)])
                        else:
                            combine.export(directory + '/' + output_name,
                                           format='mp3',
                                           parameters=['-ac',
                                                       str(channel)])
                    else:
                        for i in range(num_copies):
                            combine = combines[i]
                            new_name = output_name[:-4] + "-" + str(i +
                                                                    1) + ".mp3"
                            if platform.system() == 'Windows':
                                combine.export(
                                    directory + '\\' + new_name,
                                    format='mp3',
                                    parameters=['-ac', str(channel)])
                            else:
                                combine.export(
                                    directory + '/' + new_name,
                                    format='mp3',
                                    parameters=['-ac', str(channel)])
                utils.showInfo("Export to audio successfully!")
                self.advance_mode = False
                self.csv_file_label.setText('')
        else:
            ## get values
            deck_name = self.deck_selection.currentText()
            try:
                num_audios = int(self.num_audios.text().strip())
                num_plays = int(self.num_plays.text().strip())
                num_copies = int(self.num_copies.text().strip())
                default_waiting_time = float(
                    self.default_waiting_time.text().strip())
                additional_waiting_time = float(
                    self.additional_waiting_time.text().strip())
                _ = int(self.sample_rate.text().strip())
            except Exception as e:
                utils.showInfo("You must enter a positive integer.")
                return
            if num_audios <= 0 or num_plays <= 0 or num_copies < 0:
                utils.showInfo("You must enter a positive integer.")
                return
            mode = self.mode.currentText()
            channel = channel_map[self.channel.currentText()]
            practice_mode = practice_modes.index(
                self.practice_mode.currentText())
            combines = generate_audio(deck_name, num_audios, num_plays,
                                      num_copies, default_waiting_time,
                                      additional_waiting_time, mode,
                                      self.change_channel, channel,
                                      practice_mode)
            if len(combines) > 0:
                path = path[0].replace("::", "_")
                if num_copies == 1:
                    combines[0].export(path,
                                       format='mp3',
                                       parameters=['-ac', str(channel)])
                else:
                    for i in range(num_copies):
                        combine = combines[i]
                        new_path = path[:-4] + "-" + str(i + 1) + ".mp3"
                        combine.export(new_path,
                                       format='mp3',
                                       parameters=['-ac', str(channel)])
                utils.showInfo("Export to audios successfully!")
            else:
                utils.showInfo("Cannot export to audios.")
def generate_audio(deck_name,
                   num_audios,
                   num_plays,
                   num_copies,
                   default_waiting_time,
                   additional_waiting_time,
                   mode,
                   change_channel,
                   channel,
                   practice_mode=0):
    if isinstance(deck_name, str):
        deck_name = deck_name
    deck_name = deck_name.replace('"', '')
    deck_name = unicodedata.normalize('NFC', deck_name)
    deck = mw.col.decks.byName(deck_name)
    if deck == None:
        utils.showInfo("Deck {} does not exist.".format(deck_name))
    decks = []
    if len(mw.col.decks.children(deck['id'])) == 0:
        decks = [
            deck_name,
        ]
    else:
        decks = [name for (name, _) in mw.col.decks.children(deck['id'])]
    deck_audios = []
    for name in decks:
        query = 'deck:"{}"'.format(name)
        card_ids = mw.col.findCards(query=query)
        children_audios = [
        ]  ## each element of audios is a dict contain audios for front and back card
        for cid in card_ids:
            card = mw.col.getCard(cid)
            card_audios = []
            audio_fields_dict = {}
            audio_fields_list = []
            for field, value in card.note().items():
                match = prog.findall(value)
                if match:
                    audio_fields_dict[field] = []
                    audio_fields_list.append(field)
                    if platform.system() == 'Windows':
                        media_path = mw.col.path.rsplit(
                            '\\', 1)[0] + '\\collection.media\\'
                    else:
                        media_path = mw.col.path.rsplit(
                            '/', 1)[0] + '/collection.media/'
                    for audio in match:
                        file_path = media_path + audio
                        audio_fields_dict[field].append(file_path)

            front_audio_fields, back_audio_fields = split_audio_fields(
                card, audio_fields_list)

            audio_dict = {}
            audio_dict['cid'] = cid
            audio_dict['practice_mode'] = practice_mode % 2
            audio_dict['additional_waiting_time'] = additional_waiting_time
            audio_dict['default_waiting_time'] = default_waiting_time
            audio_dict['front'] = []
            audio_dict['back'] = []
            for faf in front_audio_fields:
                audio_dict['front'].extend(audio_fields_dict[faf])
            for baf in back_audio_fields:
                audio_dict['back'].extend(audio_fields_dict[baf])
            children_audios.append(audio_dict)
        deck_audios.append(children_audios)

    combines = []

    if mode == 'Random subdecks':
        for _ in range(num_copies):
            audios = []
            shuffle(deck_audios)
            for children_audios in deck_audios:
                shuffle(children_audios)
                for audio in children_audios:
                    audios.append(audio)
            audios = group_audios(audios, num_plays, num_audios)
            combines.append(
                combine_audios(audios, channel, default_waiting_time,
                               change_channel, additional_waiting_time,
                               practice_mode))
    else:
        for _ in range(num_copies):
            audios = []
            for children_audios in deck_audios:
                for audio in children_audios:
                    audios.append(audio)
            if mode == 'Random all':
                shuffle(audios)
                audios = group_audios(audios, num_plays, num_audios)
            elif mode == 'Overview':
                audios = group_audios(audios,
                                      num_plays,
                                      num_audios,
                                      overview=True)
            combines.append(
                combine_audios(audios, channel, default_waiting_time,
                               change_channel, additional_waiting_time,
                               practice_mode))
    return combines
예제 #39
0
def joinCard(isPrev=False, isNext=False):
    if mw.state == "review" and mw.reviewer.card != None and (
            mw.reviewer.card.model()["name"] == "movies2anki (add-on)"
            or mw.reviewer.card.model()["name"].startswith(
                "movies2anki - subs2srs")):
        m = re.match(
            r"^(.*?)_(\d+\.\d\d\.\d\d\.\d+)-(\d+\.\d\d\.\d\d\.\d+).*$",
            mw.reviewer.card.note()["Audio"])

        card_prefix, time_start, time_end = m.groups()
        time_start = timeToSeconds(time_start)
        time_end = timeToSeconds(time_end)

        cards = sorted(mw.col.findCards("deck:current ", order=True))
        card_idx = cards.index(mw.reviewer.card.id)

        prev_card_idx = card_idx - 1 if card_idx - 1 > 0 else 0
        next_card_idx = card_idx + 1
        if next_card_idx >= len(cards):
            next_card_idx = len(cards) - 1

        if (isPrev and mw.col.getCard(cards[prev_card_idx]).id == mw.reviewer.card.id) or \
            (isNext and mw.col.getCard(cards[next_card_idx]).id == mw.reviewer.card.id):
            tooltip("Nothing to do.")
            return

        curr_card = mw.col.getCard(cards[card_idx]).note()
        prev_card = mw.col.getCard(cards[prev_card_idx]).note()
        next_card = mw.col.getCard(cards[next_card_idx]).note()

        if (isPrev and prev_card["Source"] != curr_card["Source"]) or (
                isNext and curr_card["Source"] != next_card["Source"]):
            showInfo(
                "Cards can't be joined due to the Source field difference.")
            return

        curr_card_audio = curr_card["Audio"]
        prev_card_audio = prev_card["Audio"]
        next_card_audio = next_card["Audio"]

        m = re.match(r"^.*?_(\d+\.\d\d\.\d\d\.\d+)-(\d+\.\d\d\.\d\d\.\d+).*$",
                     curr_card_audio)

        curr_time_start, curr_time_end = m.groups()
        curr_time_start = timeToSeconds(curr_time_start)
        curr_time_end = timeToSeconds(curr_time_end)

        m = re.match(r"^.*?_(\d+\.\d\d\.\d\d\.\d+)-(\d+\.\d\d\.\d\d\.\d+).*$",
                     prev_card_audio)

        prev_time_start, prev_time_end = m.groups()
        prev_time_start = timeToSeconds(prev_time_start)
        prev_time_end = timeToSeconds(prev_time_end)

        m = re.match(r"^.*?_(\d+\.\d\d\.\d\d\.\d+)-(\d+\.\d\d\.\d\d\.\d+).*$",
                     next_card_audio)

        next_time_start, next_time_end = m.groups()
        next_time_start = timeToSeconds(next_time_start)
        next_time_end = timeToSeconds(next_time_end)

        if isPrev:
            time_start = prev_time_start

        if isNext:
            time_end = next_time_end

        c = mw.reviewer.card.note()
        for name, val in c.items():
            if name == "Id":
                c[name] = "%s_%s-%s" % (card_prefix, secondsToTime(time_start),
                                        secondsToTime(time_end))
            elif name == "Audio":
                c[name] = "%s_%s-%s.mp3" % (card_prefix,
                                            secondsToTime(time_start),
                                            secondsToTime(time_end))
            elif name == "Video":
                c[name] = "%s_%s-%s.mp4" % (card_prefix,
                                            secondsToTime(time_start),
                                            secondsToTime(time_end))
            elif name == "Source":
                pass
            elif name == "Path":
                pass
            elif name == "Audio Sound":
                c["Audio Sound"] = ""
            elif name == "Video Sound":
                c["Video Sound"] = ""
            else:
                if isPrev:
                    c[name] = prev_card[name] + "<br>" + c[name]
                else:
                    c[name] = c[name] + "<br>" + next_card[name]

        mw.checkpoint(_("Delete"))

        c.flush()

        if isPrev:
            cd = prev_card
        else:
            cd = next_card

        cnt = len(cd.cards())
        mw.col.remNotes([cd.id])
        mw.reset()

        tooltip(
            ngettext("Note joined and its %d card deleted.",
                     "Note joined and its %d cards deleted.", cnt) % cnt)
예제 #40
0
 def success(out: OpChangesWithCount) -> None:
     if out.count:
         tooltip(tr.browsing_notes_updated(count=out.count), parent=parent)
     else:
         showInfo(tr.browsing_tag_rename_warning_empty(), parent=parent)
예제 #41
0
def migaku(text):
    showInfo(text, False, "", "info", "Migaku Dictionary Add-on")
예제 #42
0
파일: sync.py 프로젝트: Aqueminivan/anki
    def onEvent(self, evt, *args):
        pu = self.mw.progress.update
        if evt == "badAuth":
            tooltip(
                _("AnkiWeb ID or password was incorrect; please try again."),
                parent=self.mw,
            )
            # blank the key so we prompt user again
            self.pm.profile["syncKey"] = None
            self.pm.save()
        elif evt == "corrupt":
            pass
        elif evt == "newKey":
            self.pm.profile["syncKey"] = args[0]
            self.pm.save()
        elif evt == "offline":
            tooltip(_("Syncing failed; internet offline."))
        elif evt == "upbad":
            self._didFullUp = False
            self._checkFailed()
        elif evt == "sync":
            m = None
            t = args[0]
            if t == "login":
                m = _("Syncing...")
            elif t == "upload":
                self._didFullUp = True
                m = _("Uploading to AnkiWeb...")
            elif t == "download":
                m = _("Downloading from AnkiWeb...")
            elif t == "sanity":
                m = _("Checking...")
            elif t == "findMedia":
                m = _("Checking media...")
            elif t == "upgradeRequired":
                showText(
                    _("""\
Please visit AnkiWeb, upgrade your deck, then try again."""))
            if m:
                self.label = m
                self._updateLabel()
        elif evt == "syncMsg":
            self.label = args[0]
            self._updateLabel()
        elif evt == "error":
            self._didError = True
            showText(_("Syncing failed:\n%s") % self._rewriteError(args[0]))
        elif evt == "clockOff":
            self._clockOff()
        elif evt == "checkFailed":
            self._checkFailed()
        elif evt == "mediaSanity":
            showWarning(
                _("""\
A problem occurred while syncing media. Please use Tools>Check Media, then \
sync again to correct the issue."""))
        elif evt == "noChanges":
            pass
        elif evt == "fullSync":
            self._confirmFullSync()
        elif evt == "downloadClobber":
            showInfo(
                _("Your AnkiWeb collection does not contain any cards. Please sync again and choose 'Upload' instead."
                  ))
        elif evt == "send":
            # posted events not guaranteed to arrive in order
            self.sentBytes = max(self.sentBytes, int(args[0]))
            self._updateLabel()
        elif evt == "recv":
            self.recvBytes = max(self.recvBytes, int(args[0]))
            self._updateLabel()
예제 #43
0
 def showWarning(self):
     if self.state.isChecked():
         showInfo(
             """Warning! Whistling Dixie is a dangerous addon that may not be compatible with other addons. Even if they are compatible now, it does not guarantee that it will always be compatible. Please backup/export your database first to prevent unknown addon conflict(s)."""
         )
예제 #44
0
def import_model_create(name):
    showInfo("create model : " + name)
    todo()
예제 #45
0
    def showDialog(self, currentCard=None):
        if currentCard:
            did = currentCard.did
        else:
            did = mw._selectedDeck()['id']

        cardInfo = self._getCardInfo(did)
        if not cardInfo:
            showInfo('Please select an Incremental Reading deck.')
            return

        dialog = QDialog(mw)
        layout = QVBoxLayout()
        self.cardListWidget = QListWidget()
        self.cardListWidget.setAlternatingRowColors(True)
        self.cardListWidget.setSelectionMode(
            QAbstractItemView.ExtendedSelection)
        self.cardListWidget.setWordWrap(True)

        posWidth = len(str(len(cardInfo) + 1))
        for i, card in enumerate(cardInfo, start=1):
            text = '❰ {} ❱\t{}'.format(
                str(i).zfill(posWidth), stripHTML(card['title']))
            item = QListWidgetItem(text)
            item.setData(Qt.UserRole, card)
            self.cardListWidget.addItem(item)

        upButton = QPushButton('Up')
        upButton.clicked.connect(self._moveUp)
        downButton = QPushButton('Down')
        downButton.clicked.connect(self._moveDown)
        topButton = QPushButton('Top')
        topButton.clicked.connect(self._moveToTop)
        bottomButton = QPushButton('Bottom')
        bottomButton.clicked.connect(self._moveToBottom)
        randomizeButton = QPushButton('Randomize')
        randomizeButton.clicked.connect(self._randomize)

        controlsLayout = QHBoxLayout()
        controlsLayout.addWidget(topButton)
        controlsLayout.addWidget(upButton)
        controlsLayout.addWidget(downButton)
        controlsLayout.addWidget(bottomButton)
        controlsLayout.addStretch()
        controlsLayout.addWidget(randomizeButton)

        buttonBox = QDialogButtonBox(QDialogButtonBox.Close
                                     | QDialogButtonBox.Save)
        buttonBox.accepted.connect(dialog.accept)
        buttonBox.rejected.connect(dialog.reject)
        buttonBox.setOrientation(Qt.Horizontal)

        layout.addLayout(controlsLayout)
        layout.addWidget(self.cardListWidget)
        layout.addWidget(buttonBox)

        dialog.setLayout(layout)
        dialog.setWindowModality(Qt.WindowModal)
        dialog.resize(500, 500)
        choice = dialog.exec_()

        if choice == 1:
            cids = []
            for i in range(self.cardListWidget.count()):
                card = self.cardListWidget.item(i).data(Qt.UserRole)
                cids.append(card['id'])

            self.reorder(cids)
예제 #46
0
파일: webview.py 프로젝트: rye761/anki
 def javaScriptAlert(self, frame: Any, text: str) -> None:
     showInfo(text)
예제 #47
0
def import_model_delete(id):
    showInfo("delete model : " + id)
    raise Exception("Fonction non créée")
예제 #48
0
    def findRecursive(self, index):
        from .forms import findtreeitems
        item = index.internalPointer()
        TAG_TYPE = item.fullname
        self.found = {}
        self.found[TAG_TYPE] = {}
        d = QDialog(self.browser)
        frm = findtreeitems.Ui_Dialog()
        frm.setupUi(d)

        # Restore btn states
        frm.input.setText(self.finder.get('txt', ''))
        frm.input.setFocus()
        frm.cb_case.setChecked(self.finder.get('case', 0))
        for idx, func in enumerate(
            (frm.btn_contains, frm.btn_exactly, frm.btn_startswith,
             frm.btn_endswith, frm.btn_regexp)):
            func.setChecked(0)
            if self.finder.get('radio', 0) == idx:
                func.setChecked(2)

        if not d.exec_():
            return

        txt = frm.input.text()
        if not txt:
            return
        txt = unicodedata.normalize("NFC", txt)
        options = Qt.MatchRecursive
        if txt == 'vote for pedro':
            mw.pm.profile['Blitzkrieg.VFP'] = True
            from .alt import disabledDebugStuff
            disabledDebugStuff()
        self.finder['txt'] = txt
        self.finder['case'] = frm.cb_case.isChecked()
        if self.finder['case']:
            options |= Qt.MatchCaseSensitive

        if frm.btn_exactly.isChecked():
            options |= Qt.MatchExactly
            self.finder['radio'] = 1
        elif frm.btn_startswith.isChecked():
            options |= Qt.MatchStartsWith
            self.finder['radio'] = 2
        elif frm.btn_endswith.isChecked():
            options |= Qt.MatchEndsWith
            self.finder['radio'] = 3
        elif frm.btn_regexp.isChecked():
            options |= Qt.MatchRegExp
            self.finder['radio'] = 4
        else:
            options |= Qt.MatchContains
            self.finder['radio'] = 0

        self.expandAllChildren(index, True)

        for idx in self.findItems(txt, options):
            itm = idx.internalPointer()
            if itm.type == TAG_TYPE:
                itm.background = QBrush(Qt.cyan)
                self.found[TAG_TYPE][itm.fullname] = True

        if not self.found[TAG_TYPE]:
            showInfo("Found nothing, nada, zilch!")
예제 #49
0
파일: util.py 프로젝트: ym1234/MorphMan21
def infoMsg(msg):
    showInfo(msg)
    printf(msg)
예제 #50
0
def show_card_count(message=""):
    cardCount = mw.col.cardCount()
    showInfo(("Card count: %d" % cardCount) + message)
예제 #51
0
 def _selectedDeck(self) -> Optional[Dict[str, Any]]:
     did = self.col.decks.selected()
     if not self.col.decks.nameOrNone(did):
         showInfo(_("Please select a deck."))
         return None
     return self.col.decks.get(did)
예제 #52
0
def on_run_ocr(browser: Browser):
    time_start = time.time()

    selected_nids = browser.selectedNotes()
    config = mw.addonManager.getConfig(__name__)
    num_notes = len(selected_nids)
    num_batches = ceil(num_notes / config["batch_size"])

    if num_notes == 0:
        showInfo("No cards selected.")
        return
    elif askUser(f"Are you sure you wish to run OCR processing on {num_notes} notes?") is False:
        return

    if config.get("tesseract_install_valid") is not True and config.get("text_output_location") == "new_field":
        showInfo(
            f"Note that because this addon changes the note template, you will see a warning about changing the "
            f"database and uploading to AnkiWeb. \n "
            f"This is normal, and will be shown each time you modify a note template.\n"
            f"This message will be only be shown once.")

    config["tesseract_install_valid"] = True  # Stop the above msg appearing multiple times
    mw.addonManager.writeConfig(__name__, config)

    try:
        progress = mw.progress
        progress.start(immediate=True, min=0, max=num_batches)
        progress.update(value=0, max=num_batches, label="Starting OCR processing...")
    except TypeError:  # old version of Qt/Anki
        progress = None

    ocr = OCR(col=mw.col,
              progress=progress,
              languages=config["languages"],
              text_output_location=config["text_output_location"],
              tesseract_exec_pth=config["tesseract_exec_path"] if config["override_tesseract_exec"] else None,
              batch_size=config["batch_size"], num_threads=config["num_threads"], use_batching=config["use_batching"],
              use_multithreading=config["use_multithreading"])
    try:
        ocr.run_ocr_on_notes(note_ids=selected_nids)
        if progress:
            progress.finish()
        time_taken = time.time() - time_start
        log_messages = logger.handlers[0].flush()
        showInfo(
            f"Processed OCR for {num_notes} notes in {round(time_taken, 1)}s ({round(time_taken / num_notes, 1)}s per note)\n"
            f"{log_messages}")

    except pytesseract.TesseractNotFoundError:
        if progress:
            progress.finish()
        showCritical(text=f"Could not find a valid Tesseract-OCR installation! \n"
                          f"Please visit the addon page in at https://ankiweb.net/shared/info/450181164 for"
                          f" install instructions")

    except (RuntimeError, Exception) as exc:
        from . import __version__ as anki_ocr_version
        from anki.buildinfo import version as anki_version
        import sys
        import platform

        if progress:
            progress.finish()
        msg = f"Error encountered during processing. Debug info: \n" \
              f"Anki Version: {anki_version} , AnkiOCR Version: {anki_ocr_version}\n" \
              f"Platform: {platform.system()} , Python Version: {sys.version}"
        log_messages = logger.handlers[0].flush()
        if len(log_messages) > 0:
            msg += f"Logging message generated during processing:\n{log_messages}"
        exception_str: List[str] = traceback.format_exception(etype=type(exc), value=exc, tb=exc.__traceback__)
        msg += "".join(exception_str)
        showInfo(msg)

    finally:

        browser.model.reset()
        mw.requireReset()
예제 #53
0
def bulk_fill_defs():
    prompt = PROMPT_TEMPLATE.format(
        field_names='<i>definition</i> and <i>alternative</i>',
        extra_info='',
    )

    progress_msg_template = '''
            <b>Processing:</b> %(hanzi)s<br>
            <b>Chinese notes:</b> %(has_fields)d<br>
            <b>Translated:</b> %(filled)d<br>
            <b>Failed:</b> %(failed)d'''

    field_groups = ['meaning', 'english', 'german', 'french']

    if not askUser(prompt):
        return

    n_targets = 0
    d_success = 0
    d_failed = 0
    failed_hanzi = []

    note_ids = Finder(mw.col).findNotes('deck:current')
    mw.progress.start(immediate=True, min=0, max=len(note_ids))

    for i, nid in enumerate(note_ids):
        note = mw.col.getNote(nid)
        copy = dict(note)
        hanzi = get_hanzi(copy)

        if has_any_field(copy, field_groups) and hanzi:
            n_targets += 1

            if all_fields_empty(copy, field_groups):
                result = fill_all_defs(hanzi, copy)
                if result:
                    d_success += 1
                else:
                    d_failed += 1
                    if d_failed < 20:
                        failed_hanzi += [hanzi]

            msg = progress_msg_template % {
                'hanzi': hanzi,
                'has_fields': n_targets,
                'filled': d_success,
                'failed': d_failed,
            }
            mw.progress.update(label=msg, value=i)

            save_note(note, copy)

    msg = '''
    <b>Translation complete</b><br>
    <b>Chinese notes:</b> %(has_fields)d<br>
    <b>Translated:</b> %(filled)d<br>
    <b>Failed:</b> %(failed)d''' % {
        'has_fields': n_targets,
        'filled': d_success,
        'failed': d_failed,
    }
    if d_failed > 0:
        msg += (
            '<div>Translation failures may come either from connection issues '
            "(if you're using an online translation service), or because some "
            'words are not it the dictionary (for local dictionaries).</div>'
            '<div>The following notes failed: ' + ', '.join(failed_hanzi) +
            '</div>')
    mw.progress.finish()
    showInfo(msg)
예제 #54
0
def bulk_fill_sound():
    prompt = PROMPT_TEMPLATE.format(
        field_names='<i>Sound</i>',
        extra_info=(
            '<div>There will be a 5 second delay between each sound request,'
            ' so this may take a while.</div>'),
    )

    if not askUser(prompt):
        return

    d_has_fields = 0
    d_already_had_sound = 0
    d_success = 0
    d_failed = 0

    note_ids = Finder(mw.col).findNotes('deck:current')
    mw.progress.start(immediate=True, min=0, max=len(note_ids))

    for i, nid in enumerate(note_ids):
        orig = mw.col.getNote(nid)
        copy = dict(orig)

        if has_any_field(copy, ['sound', 'mandarinSound',
                                'cantoneseSound']) and has_field(
                                    config['fields']['hanzi'], copy):
            d_has_fields += 1
            hanzi = get_first(config['fields']['hanzi'], copy)

            if all_fields_empty(copy,
                                ['sound', 'mandarinSound', 'cantoneseSound']):
                msg = '''
                <b>Processing:</b> %(hanzi)s<br>
                <b>Updated:</b> %(d_success)d notes<br>
                <b>Failed:</b> %(d_failed)d notes''' % {
                    'hanzi': get_hanzi(copy),
                    'd_success': d_success,
                    'd_failed': d_failed,
                }
                mw.progress.update(label=msg, value=i)
                s, f = fill_sound(hanzi, copy)
                d_success += s
                d_failed += f
                save_note(orig, copy)
                sleep(5)
            else:
                d_already_had_sound += 1

    mw.progress.finish()
    msg = '''
%(d_success)d new pronunciations downloaded

%(d_failed)d downloads failed

%(have)d/%(d_has_fields)d notes now have pronunciation''' % {
        'd_success': d_success,
        'd_failed': d_failed,
        'have': d_already_had_sound + d_success,
        'd_has_fields': d_has_fields,
    }
    if d_failed > 0:
        msg += ('TTS is taken from an online source. '
                'It may not always be fully responsive. '
                'Please check your network connexion, or retry later.')
    showInfo(msg)
예제 #55
0
 def onlyOneSelected(self):
     dirs = self.selectedAddons()
     if len(dirs) != 1:
         showInfo(_("Please select a single add-on first."))
         return
     return dirs[0]
예제 #56
0
 def accept(self):
     f = self.form
     i = self.radioIdx
     spin = f.spin.value()
     if i == RADIO_NEW:
         self.deck['extendNew'] = spin
         self.mw.col.decks.save(self.deck)
         self.mw.col.sched.extendLimits(spin, 0)
         self.mw.reset()
         return QDialog.accept(self)
     elif i == RADIO_REV:
         self.deck['extendRev'] = spin
         self.mw.col.decks.save(self.deck)
         self.mw.col.sched.extendLimits(0, spin)
         self.mw.reset()
         return QDialog.accept(self)
     elif i == RADIO_CRAM:
         tags = self._getTags()
     # the rest create a filtered deck
     cur = self.mw.col.decks.byName(_("Custom Study Session"))
     if cur:
         if not cur['dyn']:
             showInfo("Please rename the existing Custom Study deck first.")
             return QDialog.accept(self)
         else:
             # safe to empty
             self.mw.col.sched.emptyDyn(cur['id'])
             # reuse; don't delete as it may have children
             dyn = cur
             self.mw.col.decks.select(cur['id'])
     else:
         did = self.mw.col.decks.newDyn(_("Custom Study Session"))
         dyn = self.mw.col.decks.get(did)
     # and then set various options
     if i == RADIO_FORGOT:
         dyn['delays'] = [1]
         dyn['terms'][0] = ['rated:%d:1' % spin, DYN_MAX_SIZE, DYN_RANDOM]
         dyn['resched'] = False
     elif i == RADIO_AHEAD:
         dyn['delays'] = None
         dyn['terms'][0] = ['prop:due<=%d' % spin, DYN_MAX_SIZE, DYN_DUE]
         dyn['resched'] = True
     elif i == RADIO_PREVIEW:
         dyn['delays'] = None
         dyn['terms'][0] = [
             'is:new added:%s' % spin, DYN_MAX_SIZE, DYN_OLDEST
         ]
         dyn['resched'] = False
     elif i == RADIO_CRAM:
         dyn['delays'] = None
         type = f.cardType.currentRow()
         if type == TYPE_NEW:
             terms = "is:new "
             ord = DYN_ADDED
             dyn['resched'] = True
         elif type == TYPE_DUE:
             terms = "is:due "
             ord = DYN_DUE
             dyn['resched'] = True
         else:
             terms = ""
             ord = DYN_RANDOM
             dyn['resched'] = False
         dyn['terms'][0] = [(terms + tags).strip(), spin, ord]
     # add deck limit
     dyn['terms'][0][0] = "deck:\"%s\" %s " % (self.deck['name'],
                                               dyn['terms'][0][0])
     # generate cards
     if not self.mw.col.sched.rebuildDyn():
         return showWarning(
             _("No cards matched the criteria you provided."))
     self.mw.moveToState("overview")
     QDialog.accept(self)
예제 #57
0
파일: main.py 프로젝트: fossabot/anki
 def _selectedDeck(self):
     did = self.col.decks.selected()
     if not self.col.decks.nameOrNone(did):
         showInfo(_("Please select a deck."))
         return
     return self.col.decks.get(did)
예제 #58
0
파일: exporting.py 프로젝트: wo4wangle/anki
    def accept(self):
        self.exporter.includeSched = (self.frm.includeSched.isChecked())
        self.exporter.includeMedia = (self.frm.includeMedia.isChecked())
        self.exporter.includeTags = (self.frm.includeTags.isChecked())
        if not self.frm.deck.currentIndex():  #position 0 means: all decks.
            self.exporter.did = None
        else:
            name = self.decks[self.frm.deck.currentIndex()]
            self.exporter.did = self.col.decks.id(name)
        if self.isVerbatim:
            name = time.strftime("-%Y-%m-%d@%H-%M-%S",
                                 time.localtime(time.time()))
            deck_name = _("collection") + name
        else:
            # Get deck name and remove invalid filename characters
            deck_name = self.decks[self.frm.deck.currentIndex()]
            deck_name = re.sub('[\\\\/?<>:*|"^]', '_', deck_name)

        if not self.isVerbatim and self.isApkg and self.exporter.includeSched and self.col.schedVer(
        ) == 2:
            showInfo(
                "Please switch to the regular scheduler before exporting a single deck .apkg with scheduling."
            )
            return

        filename = '{0}{1}'.format(deck_name, self.exporter.ext)
        while 1:
            file = getSaveFile(self,
                               _("Export"),
                               "export",
                               self.exporter.key,
                               self.exporter.ext,
                               fname=filename)
            if not file:
                return
            if checkInvalidFilename(os.path.basename(file), dirsep=False):
                continue
            break
        self.hide()
        if file:
            self.mw.progress.start(immediate=True)
            try:
                f = open(file, "wb")
                f.close()
            except (OSError, IOError) as e:
                showWarning(_("Couldn't save file: %s") % str(e))
            else:
                os.unlink(file)
                exportedMedia = lambda cnt: self.mw.progress.update(
                    label=ngettext("Exported %d media file",
                                   "Exported %d media files", cnt) % cnt)
                addHook("exportedMediaFiles", exportedMedia)
                self.exporter.exportInto(file)
                remHook("exportedMediaFiles", exportedMedia)
                period = 3000
                if self.isVerbatim:
                    msg = _("Collection exported.")
                else:
                    if self.isTextNote:
                        msg = ngettext(
                            "%d note exported.", "%d notes exported.",
                            self.exporter.count) % self.exporter.count
                    else:
                        msg = ngettext(
                            "%d card exported.", "%d cards exported.",
                            self.exporter.count) % self.exporter.count
                tooltip(msg, period=period)
            finally:
                self.mw.progress.finish()
        QDialog.accept(self)
예제 #59
0
def showA(ar):
    showInfo(json.dumps(ar, ensure_ascii=False))
예제 #60
0
    def settings(self):
        addon_path = dirname(__file__)
        images = join(addon_path, 'user_files/images')
        audio = join(addon_path, 'user_files/audio_video')
        self.header_checkbox = QCheckBox("Header")
        self.header_checkbox.setFixedWidth(102)
        self.header_checkbox.setToolTip(
            """Shows a random line in \"Header Texts\" list.
        You can edit the list by pressing the \"Header Texts\" button down belw."""
        )
        self.image_checkbox = QCheckBox("Image")
        self.image_checkbox.setFixedWidth(102)
        self.image_checkbox.setToolTip(
            """Shows a random image from images folder.
        You can add images by copying images to the \"images\" foler in add-on folder. open the folder by pressing \"Open Images Folder\" button down below."""
        )
        self.audio_checkbox = QCheckBox("Audio/Video")
        self.audio_checkbox.setFixedWidth(102)
        self.audio_checkbox.setToolTip(
            """Plays a random audio from \"audio\" folder in add-on folder.
        You can add audio by copying them to the \"audio\" folder in add-on folder. open the folder by pressing \"Open Audio Folder\" button down below."""
        )
        line1 = QHBoxLayout()
        line1.addWidget(self.header_checkbox)
        line1.addWidget(self.image_checkbox)
        line1.addWidget(self.audio_checkbox)
        line1.addStretch()
        self.show_onAgain = QCheckBox("Again")
        self.show_onHard = QCheckBox("Hard")
        self.show_onGood = QCheckBox("Good")
        self.show_onEasy = QCheckBox("Easy")
        line2 = QHBoxLayout()
        line2.addWidget(self.show_onAgain)
        line2.addWidget(self.show_onHard)
        line2.addWidget(self.show_onGood)
        line2.addWidget(self.show_onEasy)
        viewChance_label = QLabel("Pop-Up Chance")
        viewChance_label.setToolTip(
            "Changes the posibility of pop-up window popping up.")
        viewChance_label.setFixedWidth(210)
        self.view_chance = QSpinBox()
        self.view_chance.setFixedWidth(210)
        self.view_chance.setRange(1, 100)
        self.view_chance.setSuffix("%")
        viewChance_holder = QHBoxLayout()
        viewChance_holder.addWidget(viewChance_label)
        viewChance_holder.addWidget(self.view_chance)
        SA_view_chance_label = QLabel("Show Answer Pop-Up Chance")
        SA_view_chance_label.setToolTip(
            "Changes the posibility of pop-up window popping up on show answer.\nSet on 0 to disable."
        )
        SA_view_chance_label.setFixedWidth(210)
        self.SA_view_chance = QSpinBox()
        self.SA_view_chance.setFixedWidth(210)
        self.SA_view_chance.setRange(0, 100)
        self.SA_view_chance.setSuffix("%")
        SA_view_chance_holder = QHBoxLayout()
        SA_view_chance_holder.addWidget(SA_view_chance_label)
        SA_view_chance_holder.addWidget(self.SA_view_chance)
        headerTextSize_label = QLabel("Header Font Size")
        headerTextSize_label.setToolTip(
            "Changes font size for the header text.")
        headerTextSize_label.setFixedWidth(210)
        self.headerText_fontSize = QSpinBox()
        self.headerText_fontSize.setFixedWidth(210)
        self.headerText_fontSize.setMinimum(1)
        self.headerText_fontSize.setSuffix("px")
        header_fontSize_holder = QHBoxLayout()
        header_fontSize_holder.addWidget(headerTextSize_label)
        header_fontSize_holder.addWidget(self.headerText_fontSize)
        headerFontStyle_label = QLabel("Header Font")
        headerFontStyle_label.setToolTip("Changes header font style.")
        headerFontStyle_label.setFixedWidth(210)
        self.headerText_fontStyle = QFontComboBox()
        self.headerText_fontStyle.setFixedWidth(210)
        header_fontStyle_holder = QHBoxLayout()
        header_fontStyle_holder.addWidget(headerFontStyle_label)
        header_fontStyle_holder.addWidget(self.headerText_fontStyle)
        imagesFolder_button = QPushButton("Open Images Folder")
        imagesFolder_button.clicked.connect(lambda: self.open_file(images))
        audioFolder_button = QPushButton("Open Audio/Video Folder")
        audioFolder_button.clicked.connect(lambda: self.open_file(audio))
        headerTexts_button = QPushButton("Header Texts")
        headerTexts_window = QDialog()
        headerTexts_window.setWindowIcon(QIcon(addon_path + "/icon.png"))
        headerTexts_window.setWindowTitle("Header Texts")

        header_tabs = QTabWidget()
        self.SA_headerTexts_textEditor = QPlainTextEdit()
        self.SA_headerTexts_textEditor.setWordWrapMode(QTextOption.NoWrap)
        SA_layout = QVBoxLayout()
        SA_layout.addWidget(self.SA_headerTexts_textEditor)
        SA_tab = QWidget()
        SA_tab.setLayout(SA_layout)
        header_tabs.addTab(SA_tab, "Show Answer")
        self.again_headerTexts_textEditor = QPlainTextEdit()
        self.again_headerTexts_textEditor.setWordWrapMode(QTextOption.NoWrap)
        again_layout = QVBoxLayout()
        again_layout.addWidget(self.again_headerTexts_textEditor)
        again_tab = QWidget()
        again_tab.setLayout(again_layout)
        header_tabs.addTab(again_tab, "Again")
        self.hard_headerTexts_textEditor = QPlainTextEdit()
        self.hard_headerTexts_textEditor.setWordWrapMode(QTextOption.NoWrap)
        hard_layout = QVBoxLayout()
        hard_layout.addWidget(self.hard_headerTexts_textEditor)
        hard_tab = QWidget()
        hard_tab.setLayout(hard_layout)
        header_tabs.addTab(hard_tab, "Hard")
        self.good_headerTexts_textEditor = QPlainTextEdit()
        self.good_headerTexts_textEditor.setWordWrapMode(QTextOption.NoWrap)
        good_layout = QVBoxLayout()
        good_layout.addWidget(self.good_headerTexts_textEditor)
        good_tab = QWidget()
        good_tab.setLayout(good_layout)
        header_tabs.addTab(good_tab, "Good")
        self.easy_headerTexts_textEditor = QPlainTextEdit()
        self.easy_headerTexts_textEditor.setWordWrapMode(QTextOption.NoWrap)
        easy_layout = QVBoxLayout()
        easy_layout.addWidget(self.easy_headerTexts_textEditor)
        easy_tab = QWidget()
        easy_tab.setLayout(easy_layout)
        header_tabs.addTab(easy_tab, "Easy")
        headers_vbox = QVBoxLayout()
        buttons = QDialogButtonBox()
        buttons.setStandardButtons(QDialogButtonBox.Close)
        buttons.rejected.connect(headerTexts_window.close)
        headers_vbox.addWidget(header_tabs)
        headers_vbox.addWidget(buttons)
        headerTexts_window.setLayout(headers_vbox)

        headerTexts_button.clicked.connect(lambda: headerTexts_window.exec())
        windowTtitles_button = QPushButton("Window Title Texts")
        windowTitles_window = QDialog()
        windowTitles_window.setWindowIcon(QIcon(addon_path + "/icon.png"))
        windowTitles_window.setWindowTitle("Window Title Texts")

        windowTitle_tabs = QTabWidget()
        self.SA_windowTitles_textEditor = QPlainTextEdit()
        self.SA_windowTitles_textEditor.setWordWrapMode(QTextOption.NoWrap)
        SA_layout = QVBoxLayout()
        SA_layout.addWidget(self.SA_windowTitles_textEditor)
        SA_tab = QWidget()
        SA_tab.setLayout(SA_layout)
        windowTitle_tabs.addTab(SA_tab, "Show Answer")
        self.again_windowTitles_textEditor = QPlainTextEdit()
        self.again_windowTitles_textEditor.setWordWrapMode(QTextOption.NoWrap)
        again_layout = QVBoxLayout()
        again_layout.addWidget(self.again_windowTitles_textEditor)
        again_tab = QWidget()
        again_tab.setLayout(again_layout)
        windowTitle_tabs.addTab(again_tab, "Again")
        self.hard_windowTitles_textEditor = QPlainTextEdit()
        self.hard_windowTitles_textEditor.setWordWrapMode(QTextOption.NoWrap)
        hard_layout = QVBoxLayout()
        hard_layout.addWidget(self.hard_windowTitles_textEditor)
        hard_tab = QWidget()
        hard_tab.setLayout(hard_layout)
        windowTitle_tabs.addTab(hard_tab, "Hard")
        self.good_windowTitles_textEditor = QPlainTextEdit()
        self.good_windowTitles_textEditor.setWordWrapMode(QTextOption.NoWrap)
        good_layout = QVBoxLayout()
        good_layout.addWidget(self.good_windowTitles_textEditor)
        good_tab = QWidget()
        good_tab.setLayout(good_layout)
        windowTitle_tabs.addTab(good_tab, "Good")
        self.easy_windowTitles_textEditor = QPlainTextEdit()
        self.easy_windowTitles_textEditor.setWordWrapMode(QTextOption.NoWrap)
        easy_layout = QVBoxLayout()
        easy_layout.addWidget(self.easy_windowTitles_textEditor)
        easy_tab = QWidget()
        easy_tab.setLayout(easy_layout)
        windowTitle_tabs.addTab(easy_tab, "Easy")
        windowTitles_vbox = QVBoxLayout()
        buttons = QDialogButtonBox()
        buttons.setStandardButtons(QDialogButtonBox.Close)
        buttons.rejected.connect(windowTitles_window.close)
        windowTitles_vbox.addWidget(windowTitle_tabs)
        windowTitles_vbox.addWidget(buttons)
        windowTitles_window.setLayout(windowTitles_vbox)

        windowTtitles_button.clicked.connect(
            lambda: windowTitles_window.exec())
        buttonTexts_button = QPushButton("Button Texts")
        buttonTexts_window = QDialog()
        buttonTexts_window.setWindowIcon(QIcon(addon_path + "/icon.png"))
        buttonTexts_window.setWindowTitle("Button Texts")

        button_tabs = QTabWidget()
        self.SA_buttonTexts_textEditor = QPlainTextEdit()
        self.SA_buttonTexts_textEditor.setWordWrapMode(QTextOption.NoWrap)
        SA_layout = QVBoxLayout()
        SA_layout.addWidget(self.SA_buttonTexts_textEditor)
        SA_tab = QWidget()
        SA_tab.setLayout(SA_layout)
        button_tabs.addTab(SA_tab, "Show Answer")
        self.again_buttonTexts_textEditor = QPlainTextEdit()
        self.again_buttonTexts_textEditor.setWordWrapMode(QTextOption.NoWrap)
        again_layout = QVBoxLayout()
        again_layout.addWidget(self.again_buttonTexts_textEditor)
        again_tab = QWidget()
        again_tab.setLayout(again_layout)
        button_tabs.addTab(again_tab, "Again")
        self.hard_buttonTexts_textEditor = QPlainTextEdit()
        self.hard_buttonTexts_textEditor.setWordWrapMode(QTextOption.NoWrap)
        hard_layout = QVBoxLayout()
        hard_layout.addWidget(self.hard_buttonTexts_textEditor)
        hard_tab = QWidget()
        hard_tab.setLayout(hard_layout)
        button_tabs.addTab(hard_tab, "Hard")
        self.good_buttonTexts_textEditor = QPlainTextEdit()
        self.good_buttonTexts_textEditor.setWordWrapMode(QTextOption.NoWrap)
        good_layout = QVBoxLayout()
        good_layout.addWidget(self.good_buttonTexts_textEditor)
        good_tab = QWidget()
        good_tab.setLayout(good_layout)
        button_tabs.addTab(good_tab, "Good")
        self.easy_buttonTexts_textEditor = QPlainTextEdit()
        self.easy_buttonTexts_textEditor.setWordWrapMode(QTextOption.NoWrap)
        easy_layout = QVBoxLayout()
        easy_layout.addWidget(self.easy_buttonTexts_textEditor)
        easy_tab = QWidget()
        easy_tab.setLayout(easy_layout)
        button_tabs.addTab(easy_tab, "Easy")
        buttons_vbox = QVBoxLayout()
        buttons = QDialogButtonBox()
        buttons.setStandardButtons(QDialogButtonBox.Close)
        buttons.rejected.connect(buttonTexts_window.close)
        buttons_vbox.addWidget(button_tabs)
        buttons_vbox.addWidget(buttons)
        buttonTexts_window.setLayout(buttons_vbox)

        buttonTexts_button.clicked.connect(lambda: buttonTexts_window.exec())
        apply_button = QPushButton("Apply")
        apply_button.clicked.connect(self.onApply)
        apply_button.clicked.connect(
            lambda: showInfo("<div style='color: red;\
        font-size: 15px;'> Changes will take effect after you restart anki. </div>",
                             title="Review Pop-Up Settings"))
        apply_button.clicked.connect(lambda: self.hide())
        cancel_button = QPushButton("Cancel")
        cancel_button.clicked.connect(lambda: self.hide())
        bottom_line = QHBoxLayout()
        bottom_line.addWidget(apply_button)
        bottom_line.addWidget(cancel_button)
        self.layout = QVBoxLayout()
        self.layout.addLayout(line1)
        self.layout.addLayout(line2)
        self.layout.addLayout(viewChance_holder)
        self.layout.addLayout(SA_view_chance_holder)
        self.layout.addLayout(header_fontStyle_holder)
        self.layout.addLayout(header_fontSize_holder)
        self.layout.addWidget(imagesFolder_button)
        self.layout.addWidget(audioFolder_button)
        self.layout.addWidget(headerTexts_button)
        self.layout.addWidget(windowTtitles_button)
        self.layout.addWidget(buttonTexts_button)
        self.layout.addLayout(bottom_line)