示例#1
0
文件: clayout.py 项目: solarmist/anki
    def setupMainArea(self):
        w = self.mainArea = QWidget()
        l = QHBoxLayout()
        l.setContentsMargins(0,0,0,0)
        l.setSpacing(3)
        left = QWidget()
        # template area
        tform = self.tform = aqt.forms.template.Ui_Form()
        tform.setupUi(left)
        tform.label1.setText(" →")
        tform.label2.setText(" →")
        tform.labelc1.setText(" ↗")
        tform.labelc2.setText(" ↘")
        if self.style().objectName() == "gtk+":
            # gtk+ requires margins in inner layout
            tform.tlayout1.setContentsMargins(0, 11, 0, 0)
            tform.tlayout2.setContentsMargins(0, 11, 0, 0)
            tform.tlayout3.setContentsMargins(0, 11, 0, 0)
        tform.groupBox_3.setTitle(_(
            "Styling (shared between cards)"))
        tform.front.textChanged.connect(self.saveCard)
        tform.css.textChanged.connect(self.saveCard)
        tform.back.textChanged.connect(self.saveCard)
        l.addWidget(left, 5)
        # preview area
        right = QWidget()
        pform = self.pform = aqt.forms.preview.Ui_Form()
        pform.setupUi(right)
        if self.style().objectName() == "gtk+":
            # gtk+ requires margins in inner layout
            pform.frontPrevBox.setContentsMargins(0, 11, 0, 0)
            pform.backPrevBox.setContentsMargins(0, 11, 0, 0)

        self.setupWebviews()

        l.addWidget(right, 5)
        w.setLayout(l)
class ChangeModelDialog(QDialog):
    """
    Dialog that allows user to create field and template maps from one note model to another
    Extrated from main Anki codebase, largely untouched.
    """
    def __init__(self, collection, note_id_list, old_model=None, parent=None):
        QDialog.__init__(self, parent)
        self.collection = collection
        self.note_id_list = note_id_list
        self.old_model = old_model
        if self.old_model is None:
            first_note = Note(collection, id=note_id_list[0])
            self.old_model = first_note.model()

        # todo consider extracting UI file
        self.form = aqt.forms.changemodel.Ui_Dialog()
        self.form.setupUi(self)
        self.setWindowModality(Qt.WindowModal)
        self.setup()

        self.pauseUpdate = False
        self.model_changed(self.collection.models.current())

        aqt.utils.restoreGeom(self, "changeModel")
        anki.hooks.addHook("reset", self.on_reset)
        anki.hooks.addHook("currentModelChanged", self.on_reset)

    def setup(self):
        # maps
        self.flayout = QHBoxLayout()
        self.flayout.setContentsMargins(0, 0, 0, 0)
        self.fwidg = None
        self.form.fieldMap.setLayout(self.flayout)
        self.tlayout = QHBoxLayout()
        self.tlayout.setContentsMargins(0, 0, 0, 0)
        self.twidg = None
        self.form.templateMap.setLayout(self.tlayout)
        if self.style().objectName() == "gtk+":
            # gtk+ requires margins in inner layout
            self.form.verticalLayout_2.setContentsMargins(0, 11, 0, 0)
            self.form.verticalLayout_3.setContentsMargins(0, 11, 0, 0)
        # model chooser
        import aqt.modelchooser
        self.form.oldModelLabel.setText(self.old_model['name'])
        self.modelChooser = aqt.modelchooser.ModelChooser(
            aqt.mw, self.form.modelChooserWidget, label=False)
        self.modelChooser.models.setFocus()
        self.form.buttonBox.helpRequested.connect(self.on_help)

    def on_reset(self):
        self.model_changed(self.collection.models.current())

    def model_changed(self, model):
        self.targetModel = model
        self.rebuild_template_map()
        self.rebuild_field_map()

    def rebuild_template_map(self, key=None, attr=None):
        if not key:
            key = "t"
            attr = "tmpls"
        map_widget = getattr(self, key + "widg")
        layout = getattr(self, key + "layout")
        src = self.old_model[attr]
        dst = self.targetModel[attr]
        if map_widget:
            layout.removeWidget(map_widget)
            map_widget.deleteLater()
            setattr(self, key + "MapWidget", None)
        map_widget = QWidget()
        map_widget_layout = QGridLayout()
        combos = []
        targets = [entity['name'] for entity in dst] + [_("Nothing")]
        indices = {}
        for i, entity in enumerate(src):
            map_widget_layout.addWidget(
                QLabel(_("Change %s to:") % entity['name']), i, 0)
            combo_box = QComboBox()
            combo_box.addItems(targets)
            idx = min(i, len(targets) - 1)
            combo_box.setCurrentIndex(idx)
            indices[combo_box] = idx
            combo_box.currentIndexChanged.connect(
                lambda entry_id: self.on_combo_changed(entry_id, combo_box, key
                                                       ))
            combos.append(combo_box)
            map_widget_layout.addWidget(combo_box, i, 1)
        map_widget.setLayout(map_widget_layout)
        layout.addWidget(map_widget)
        setattr(self, key + "widg", map_widget)
        setattr(self, key + "layout", layout)
        setattr(self, key + "combos", combos)
        setattr(self, key + "indices", indices)

    def rebuild_field_map(self):
        return self.rebuild_template_map(key="f", attr="flds")

    def on_combo_changed(self, combo_box_index, combo_box, key):
        indices = getattr(self, key + "indices")
        if self.pauseUpdate:
            indices[combo_box] = combo_box_index
            return
        combos = getattr(self, key + "combos")
        if combo_box_index == combo_box.count() - 1:
            # set to 'nothing'
            return
        # find another combo with same index
        for c in combos:
            if c == combo_box:
                continue
            if c.currentIndex() == combo_box_index:
                self.pauseUpdate = True
                c.setCurrentIndex(indices[combo_box])
                self.pauseUpdate = False
                break
        indices[combo_box] = combo_box_index

    def get_template_map(self, old=None, combos=None, new=None):
        if not old:
            old = self.old_model['tmpls']
            combos = self.tcombos
            new = self.targetModel['tmpls']
        model_map = {}
        for i, f in enumerate(old):
            idx = combos[i].currentIndex()
            if idx == len(new):
                # ignore
                model_map[f['ord']] = None
            else:
                f2 = new[idx]
                model_map[f['ord']] = f2['ord']
        return model_map

    def get_field_map(self):
        return self.get_template_map(old=self.old_model['flds'],
                                     combos=self.fcombos,
                                     new=self.targetModel['flds'])

    def cleanup(self):
        anki.hooks.remHook("reset", self.on_reset)
        anki.hooks.remHook("currentModelChanged", self.on_reset)
        self.modelChooser.cleanup()
        aqt.utils.saveGeom(self, "changeModel")

    def reject(self):
        # self.cleanup()
        # return QDialog.reject(self)
        # Todo: bad, consider disabling button/modifying the ui
        return self.accept()

    def accept(self):
        # check maps
        field_map = self.get_field_map()
        templates_map = self.get_template_map()
        if any(True for template in list(templates_map.values()) if template is None) and \
                not aqt.utils.askUser(_(
                    "Any cards mapped to nothing will be deleted. "
                    "If a note has no remaining cards, it will be lost. "
                    "Are you sure you want to continue?")):
            return

        self.collection.models.change(self.old_model, self.note_id_list,
                                      self.targetModel, field_map,
                                      templates_map)

        self.cleanup()

        QDialog.accept(self)

    def closeEvent(self, event):
        event.ignore()

    @staticmethod
    def on_help():
        aqt.utils.openHelp("browsermisc")
示例#3
0
class ChangeModelDialog(QDialog):
    """
    Dialog that allows user to create field and template maps from one note model to another
    Extrated from main Anki codebase, largely untouched.
    """

    def __init__(self, collection, note_id_list, old_model=None, parent=None):
        QDialog.__init__(self, parent)
        self.collection = collection
        self.note_id_list = note_id_list
        self.old_model = old_model
        if self.old_model is None:
            first_note = Note(collection, id=note_id_list[0])
            self.old_model = first_note.model()

        # todo consider extracting UI file
        self.form = aqt.forms.changemodel.Ui_Dialog()
        self.form.setupUi(self)
        self.setWindowModality(Qt.WindowModal)
        self.setup()

        self.pauseUpdate = False
        self.model_changed(self.collection.models.current())

        aqt.utils.restoreGeom(self, "changeModel")
        anki.hooks.addHook("reset", self.on_reset)
        anki.hooks.addHook("currentModelChanged", self.on_reset)

    def setup(self):
        # maps
        self.flayout = QHBoxLayout()
        self.flayout.setContentsMargins(0, 0, 0, 0)
        self.fwidg = None
        self.form.fieldMap.setLayout(self.flayout)
        self.tlayout = QHBoxLayout()
        self.tlayout.setContentsMargins(0, 0, 0, 0)
        self.twidg = None
        self.form.templateMap.setLayout(self.tlayout)
        if self.style().objectName() == "gtk+":
            # gtk+ requires margins in inner layout
            self.form.verticalLayout_2.setContentsMargins(0, 11, 0, 0)
            self.form.verticalLayout_3.setContentsMargins(0, 11, 0, 0)
        # model chooser
        import aqt.modelchooser
        self.form.oldModelLabel.setText(self.old_model['name'])
        self.modelChooser = aqt.modelchooser.ModelChooser(
            aqt.mw, self.form.modelChooserWidget, label=False)
        self.modelChooser.models.setFocus()
        self.form.buttonBox.helpRequested.connect(self.on_help)

    def on_reset(self):
        self.model_changed(self.collection.models.current())

    def model_changed(self, model):
        self.targetModel = model
        self.rebuild_template_map()
        self.rebuild_field_map()

    def rebuild_template_map(self, key=None, attr=None):
        if not key:
            key = "t"
            attr = "tmpls"
        map_widget = getattr(self, key + "widg")
        layout = getattr(self, key + "layout")
        src = self.old_model[attr]
        dst = self.targetModel[attr]
        if map_widget:
            layout.removeWidget(map_widget)
            map_widget.deleteLater()
            setattr(self, key + "MapWidget", None)
        map_widget = QWidget()
        map_widget_layout = QGridLayout()
        combos = []
        targets = [entity['name'] for entity in dst] + [_("Nothing")]
        indices = {}
        for i, entity in enumerate(src):
            map_widget_layout.addWidget(QLabel(_("Change %s to:") % entity['name']), i, 0)
            combo_box = QComboBox()
            combo_box.addItems(targets)
            idx = min(i, len(targets) - 1)
            combo_box.setCurrentIndex(idx)
            indices[combo_box] = idx
            combo_box.currentIndexChanged.connect(
                lambda entry_id: self.on_combo_changed(entry_id, combo_box, key))
            combos.append(combo_box)
            map_widget_layout.addWidget(combo_box, i, 1)
        map_widget.setLayout(map_widget_layout)
        layout.addWidget(map_widget)
        setattr(self, key + "widg", map_widget)
        setattr(self, key + "layout", layout)
        setattr(self, key + "combos", combos)
        setattr(self, key + "indices", indices)

    def rebuild_field_map(self):
        return self.rebuild_template_map(key="f", attr="flds")

    def on_combo_changed(self, combo_box_index, combo_box, key):
        indices = getattr(self, key + "indices")
        if self.pauseUpdate:
            indices[combo_box] = combo_box_index
            return
        combos = getattr(self, key + "combos")
        if combo_box_index == combo_box.count() - 1:
            # set to 'nothing'
            return
        # find another combo with same index
        for c in combos:
            if c == combo_box:
                continue
            if c.currentIndex() == combo_box_index:
                self.pauseUpdate = True
                c.setCurrentIndex(indices[combo_box])
                self.pauseUpdate = False
                break
        indices[combo_box] = combo_box_index

    def get_template_map(self, old=None, combos=None, new=None):
        if not old:
            old = self.old_model['tmpls']
            combos = self.tcombos
            new = self.targetModel['tmpls']
        model_map = {}
        for i, f in enumerate(old):
            idx = combos[i].currentIndex()
            if idx == len(new):
                # ignore
                model_map[f['ord']] = None
            else:
                f2 = new[idx]
                model_map[f['ord']] = f2['ord']
        return model_map

    def get_field_map(self):
        return self.get_template_map(
            old=self.old_model['flds'],
            combos=self.fcombos,
            new=self.targetModel['flds'])

    def cleanup(self):
        anki.hooks.remHook("reset", self.on_reset)
        anki.hooks.remHook("currentModelChanged", self.on_reset)
        self.modelChooser.cleanup()
        aqt.utils.saveGeom(self, "changeModel")

    def reject(self):
        # self.cleanup()
        # return QDialog.reject(self)
        # Todo: bad, consider disabling button/modifying the ui
        return self.accept()

    def accept(self):
        # check maps
        field_map = self.get_field_map()
        templates_map = self.get_template_map()
        if any(True for template in list(templates_map.values()) if template is None) and \
                not aqt.utils.askUser(_(
                    "Any cards mapped to nothing will be deleted. "
                    "If a note has no remaining cards, it will be lost. "
                    "Are you sure you want to continue?")):
                return

        self.collection.models.change(self.old_model, self.note_id_list, self.targetModel, field_map, templates_map)

        self.cleanup()

        QDialog.accept(self)

    def closeEvent(self, event):
        event.ignore()

    @staticmethod
    def on_help():
        aqt.utils.openHelp("browsermisc")