Example #1
0
class ImportSettingsDialog(QDialog):
    def __init__(self):
        global mw
        QDialog.__init__(self, mw)
        self.mw = mw
        self.form = dialog.Ui_Form()
        self.form.setupUi(self)
        self.form.buttonBox.accepted.connect(self.accept)
        self.form.buttonBox.rejected.connect(self.reject)
        self.form.browse.clicked.connect(self.onBrowse)
        self.deck = DeckChooser(self.mw, self.form.deckArea, label=False)
        # The path to the media directory chosen by user
        self.mediaDir = None
        # The number of fields in the note type we are using
        self.fieldCount = 0
        self.populateModelList()
        self.exec_()

    def populateModelList(self):
        """Fill in the list of available note types to select from."""
        models = mw.col.models.all()
        for m in models:
            item = QListWidgetItem(m['name'])
            # Put the model in the widget to conveniently fetch later
            item.model = m
            self.form.modelList.addItem(item)
        self.form.modelList.sortItems()
        self.form.modelList.currentRowChanged.connect(self.populateFieldGrid)
        # Triggers a selection so the fields will be populated
        self.form.modelList.setCurrentRow(0)

    def populateFieldGrid(self):
        """Fill in the fieldMapGrid QGridLayout.

        Each row in the grid contains two columns:
        Column 0 = QLabel with name of field
        Column 1 = QComboBox with selection of mappings ("actions")
        The first two fields will default to Media and File Name, so we have
        special cases for rows 0 and 1. The final row is a spacer."""

        self.clearLayout(self.form.fieldMapGrid)
        # Add note fields to grid
        row = 0
        for field in self.form.modelList.currentItem().model['flds']:
            self.createRow(field['name'], row)
            row += 1
        # Add special fields to grid
        for name in SPECIAL_FIELDS:
            self.createRow(name, row, special=True)
            row += 1
        self.fieldCount = row
        self.form.fieldMapGrid.addItem(
            QSpacerItem(0, 0, QSizePolicy.Minimum, QSizePolicy.Expanding), row, 0)

    def createRow(self, name, idx, special=False):
        lbl = QLabel(name)
        cmb = QComboBox()
        cmb.addItems(ACTIONS)
        # piggy-back the special flag on QLabel
        lbl.special = special
        self.form.fieldMapGrid.addWidget(lbl, idx, 0)
        self.form.fieldMapGrid.addWidget(cmb, idx, 1)
        if idx == 0: cmb.setCurrentIndex(1)
        if idx == 1: cmb.setCurrentIndex(2)

    def getDialogResult(self):
        """
        将用户在界面中保存的设置作为一个元组返回。元组包含以下内容:
        - 文件路径
        - 卡组
        - 笔记类型
        - 导入信息与笔记类型各领域的对应关系
        - 是否导入
        """

        if self.result() == QDialog.Rejected: return None, None, None, None, False

        model = self.form.modelList.currentItem().model
        # Iterate the grid rows to populate the field map
        fieldList = []
        did = self.deck.selectedId()
        grid = self.form.fieldMapGrid
        for row in range(self.fieldCount):
            # QLabel with field name
            field = grid.itemAtPosition(row, 0).widget().text()
            # Piggy-backed special flag
            special = grid.itemAtPosition(row, 0).widget().special
            # QComboBox with index from the action list
            actionIdx = grid.itemAtPosition(row, 1).widget().currentIndex()
            fieldList.append((field, actionIdx, special))
        return self.mediaDir, did, model, fieldList, True

    def onBrowse(self):
        """
        Show the directory selection dialog.
        """
        path = QFileDialog.getOpenFileName(mw, caption = '导入文件', filter = '文本文件 (*.html *.md)')[0]
        if not path:
            return
        self.mediaDir = path
        self.form.mediaDir.setText(self.mediaDir)
        self.form.mediaDir.setStyleSheet("")

    def accept(self):
        """
        如果用户没有选择就导入,那么不接受此消息并将文件名的边框设为红色。
        """
        if not self.mediaDir:
            self.form.mediaDir.setStyleSheet("border: 1px solid red")
            return
        QDialog.accept(self)

    def clearLayout(self, layout):
        """
        Convenience method to remove child widgets from a layout.
        """
        while layout.count():
            child = layout.takeAt(0)
            if child.widget() is not None:
                child.widget().deleteLater()
            elif child.layout() is not None:
                self.clearLayout(child.layout())
Example #2
0
class Kind2AnkiDialog(QDialog):
    def __init__(self):
        global mw
        QDialog.__init__(self, mw, Qt.Window)
        self.mw = mw
        self.frm = kind2anki_ui.Ui_kind2ankiDialog()
        self.frm.setupUi(self)

        self.t = ThreadTranslate()
        self.t.done.connect(importToAnki)
        self.t.startProgress.connect(startProgressBar)

        b = QPushButton(_("Import"))
        self.frm.buttonBox.addButton(b, QDialogButtonBox.AcceptRole)
        self.deck = DeckChooser(self.mw, self.frm.deckArea, label=False)
        self.frm.importMode.setCurrentIndex(
            self.mw.pm.profile.get('importMode', 1))

        self.daysSinceLastRun = self.getDaysSinceLastRun()
        self.frm.importDays.setValue(self.daysSinceLastRun)

        self.exec_()

    def accept(self):
        try:
            db_path = getDBPath()
            self.writeCurrentTimestampToFile()  # update lastRun timestamp

            target_language = self.frm.languageSelect.currentText()
            includeUsage = self.frm.includeUsage.isChecked()
            doTranslate = self.frm.doTranslate.isChecked()
            importDays = self.frm.importDays.value()

            #if doTranslate:
            #    showInfo("Translating words from database, it can take a while...")
            #else:
            #    showInfo("Fetching words from database, it can take a while...")

            self.t.dialog = self
            self.t.args = (db_path, target_language, includeUsage, doTranslate,
                           importDays)

            self.t.start()

        except urllib.error.URLError:
            showInfo("Cannot connect")
        except IOError:
            showInfo("DB file not selected, exiting")
        except sqlite3.DatabaseError:
            showInfo("Selected file is not a DB")
        finally:
            self.close()
            self.mw.reset()

    def setupImporter(self, temp_file_path):
        self.importer = TextImporter(self.mw.col, str(temp_file_path))
        self.importer.initMapping()
        self.importer.allowHTML = True
        self.importer.importMode = self.frm.importMode.currentIndex()
        self.mw.pm.profile['importMode'] = self.importer.importMode
        self.importer.delimiter = ';'

    def selectDeck(self):
        did = self.deck.selectedId()
        if did != self.importer.model['did']:
            self.importer.model['did'] = did
            self.mw.col.models.save(self.importer.model)
        self.mw.col.decks.select(did)

    def getDaysSinceLastRun(self):
        path = self.getLastRunFilePath()
        if os.path.isfile(path):
            with open(path, "r") as f:
                timestamp = int(f.read())
            days = self.getDaysSinceTimestamp(timestamp) + 1  # round up
        else:
            days = 10

        return days

    def getDaysSinceTimestamp(self, timestamp):
        now = datetime.datetime.now()
        previous = datetime.datetime.fromtimestamp(timestamp)
        return (now - previous).days

    def writeCurrentTimestampToFile(self):
        path = self.getLastRunFilePath()
        now = datetime.datetime.now()
        with open(path, "w") as f:
            f.write(str(int(time.mktime(now.timetuple()))))

    def getLastRunFilePath(self):
        dir_path = os.path.dirname(os.path.realpath(__file__))
        return os.path.join(dir_path, "lastRun.txt")