mirror of
https://github.com/ankitects/anki.git
synced 2025-09-19 06:22:22 -04:00
changing model support
This commit is contained in:
parent
fea4003ff7
commit
13c5a398b3
4 changed files with 313 additions and 51 deletions
|
@ -425,14 +425,15 @@ class EditDeck(QMainWindow):
|
|||
self.connect(self.dialog.actionDelete, SIGNAL("triggered()"), self.deleteCards)
|
||||
self.connect(self.dialog.actionAddTag, SIGNAL("triggered()"), self.addTags)
|
||||
self.connect(self.dialog.actionDeleteTag, SIGNAL("triggered()"), self.deleteTags)
|
||||
self.connect(self.dialog.actionAddCards, SIGNAL("triggered()"), self.addCards)
|
||||
self.connect(self.dialog.actionChangeTemplate, SIGNAL("triggered()"), self.onChangeTemplate)
|
||||
self.connect(self.dialog.actionReschedule, SIGNAL("triggered()"), self.reschedule)
|
||||
self.connect(self.dialog.actionAddCards, SIGNAL("triggered()"), self.addCards)
|
||||
self.connect(self.dialog.actionChangeModel, SIGNAL("triggered()"), self.onChangeModel)
|
||||
# edit
|
||||
self.connect(self.dialog.actionUndo, SIGNAL("triggered()"), self.onUndo)
|
||||
self.connect(self.dialog.actionRedo, SIGNAL("triggered()"), self.onRedo)
|
||||
self.connect(self.dialog.actionSelectFacts, SIGNAL("triggered()"), self.selectFacts)
|
||||
self.connect(self.dialog.actionInvertSelection, SIGNAL("triggered()"), self.invertSelection)
|
||||
self.connect(self.dialog.actionReverseOrder, SIGNAL("triggered()"), self.reverseOrder)
|
||||
self.connect(self.dialog.actionUndo, SIGNAL("triggered()"), self.onUndo)
|
||||
self.connect(self.dialog.actionRedo, SIGNAL("triggered()"), self.onRedo)
|
||||
# jumps
|
||||
self.connect(self.dialog.actionFirstCard, SIGNAL("triggered()"), self.onFirstCard)
|
||||
self.connect(self.dialog.actionLastCard, SIGNAL("triggered()"), self.onLastCard)
|
||||
|
@ -440,6 +441,8 @@ class EditDeck(QMainWindow):
|
|||
self.connect(self.dialog.actionNextCard, SIGNAL("triggered()"), self.onNextCard)
|
||||
self.connect(self.dialog.actionFind, SIGNAL("triggered()"), self.onFind)
|
||||
self.connect(self.dialog.actionFact, SIGNAL("triggered()"), self.onFact)
|
||||
# help
|
||||
self.connect(self.dialog.actionGuide, SIGNAL("triggered()"), self.onHelp)
|
||||
runHook('editor.setupMenus', self)
|
||||
|
||||
def onClose(self):
|
||||
|
@ -627,28 +630,31 @@ where id in (%s)""" % ",".join([
|
|||
self.updateSearch()
|
||||
self.updateAfterCardChange()
|
||||
|
||||
def onChangeTemplate(self):
|
||||
sc = self.selectedCards()
|
||||
models = self.deck.s.column0("""
|
||||
select distinct modelId from cards, facts where
|
||||
cards.id in %s and cards.factId = facts.id""" % ids2str(sc))
|
||||
if not len(models) == 1:
|
||||
def onChangeModel(self):
|
||||
sf = self.selectedFacts()
|
||||
cms = self.deck.s.column0("""
|
||||
select distinct modelId from facts
|
||||
where id in %s""" % ids2str(sf))
|
||||
if not len(cms) == 1:
|
||||
ui.utils.showInfo(
|
||||
_("Can only change templates in a single model."),
|
||||
_("Can only change one model at a time."),
|
||||
parent=self)
|
||||
return
|
||||
cms = [x.id for x in
|
||||
self.currentCard.fact.model.cardModels]
|
||||
d = ChangeTemplateDialog(self, cms)
|
||||
d = ChangeModelDialog(self, self.currentCard.fact.model,
|
||||
self.currentCard.cardModel)
|
||||
d.exec_()
|
||||
n = _("Change Template")
|
||||
if d.newId:
|
||||
self.parent.setProgressParent(self)
|
||||
if d.ret:
|
||||
n = _("Change Model")
|
||||
self.deck.setUndoStart(n)
|
||||
self.deck.changeCardModel(sc, d.newId)
|
||||
self.deck.changeModel(sf, *d.ret)
|
||||
self.deck.setUndoEnd(n)
|
||||
self.updateSearch()
|
||||
self.updateAfterCardChange()
|
||||
|
||||
# Edit: selection
|
||||
######################################################################
|
||||
|
||||
def selectFacts(self):
|
||||
sm = self.dialog.tableView.selectionModel()
|
||||
cardIds = dict([(x, 1) for x in self.selectedFactsAsCards()])
|
||||
|
@ -673,7 +679,7 @@ cards.id in %s and cards.factId = facts.id""" % ids2str(sc))
|
|||
self.model.reset()
|
||||
self.focusCurrentCard()
|
||||
|
||||
# Undo/Redo
|
||||
# Edit: undo/redo
|
||||
######################################################################
|
||||
|
||||
def onUndo(self):
|
||||
|
@ -725,6 +731,15 @@ cards.id in %s and cards.factId = facts.id""" % ids2str(sc))
|
|||
def onFact(self):
|
||||
self.editor.focusFirst()
|
||||
|
||||
# Help
|
||||
######################################################################
|
||||
|
||||
def onHelp(self):
|
||||
QDesktopServices.openUrl(QUrl(ankiqt.appWiki + "Editor"))
|
||||
|
||||
# Generate card dialog
|
||||
######################################################################
|
||||
|
||||
class AddCardChooser(QDialog):
|
||||
|
||||
def __init__(self, parent, cms):
|
||||
|
@ -768,41 +783,121 @@ order by ordinal""" % ids2str(self.cms))
|
|||
QDesktopServices.openUrl(QUrl(ankiqt.appWiki +
|
||||
"Editor#GenerateCards"))
|
||||
|
||||
class ChangeTemplateDialog(QDialog):
|
||||
# Change model dialog
|
||||
######################################################################
|
||||
|
||||
def __init__(self, parent, cms):
|
||||
class ChangeModelDialog(QDialog):
|
||||
|
||||
def __init__(self, parent, oldModel, oldTemplate):
|
||||
QDialog.__init__(self, parent, Qt.Window)
|
||||
self.parent = parent
|
||||
self.cms = cms
|
||||
self.newId = None
|
||||
self.dialog = ankiqt.forms.addcardmodels.Ui_Dialog()
|
||||
self.dialog.setupUi(self)
|
||||
self.connect(self.dialog.buttonBox, SIGNAL("helpRequested()"),
|
||||
self.oldModel = oldModel
|
||||
self.oldTemplate = oldTemplate
|
||||
self.form = ankiqt.forms.changemodel.Ui_Dialog()
|
||||
self.form.setupUi(self)
|
||||
# maps
|
||||
self.fieldMapWidget = None
|
||||
self.fieldMapLayout = QHBoxLayout()
|
||||
self.form.fieldMap.setLayout(self.fieldMapLayout)
|
||||
self.templateMapWidget = None
|
||||
self.templateMapLayout = QHBoxLayout()
|
||||
self.form.templateMap.setLayout(self.templateMapLayout)
|
||||
# model chooser
|
||||
self.parent.deck.currentModel = oldModel
|
||||
self.form.oldModelLabel.setText(self.oldModel.name)
|
||||
self.modelChooser = ui.modelchooser.ModelChooser(self,
|
||||
self.parent,
|
||||
self.parent.deck,
|
||||
self.modelChanged,
|
||||
cards=False,
|
||||
label=False)
|
||||
self.form.modelChooserWidget.setLayout(self.modelChooser)
|
||||
self.modelChooser.models.setFocus()
|
||||
self.connect(self.form.buttonBox, SIGNAL("helpRequested()"),
|
||||
self.onHelp)
|
||||
self.setWindowTitle(_("Change Template"))
|
||||
self.dialog.list.setSelectionMode(QAbstractItemView.SingleSelection)
|
||||
self.displayCards()
|
||||
restoreGeom(self, "changeTemplate")
|
||||
restoreGeom(self, "changeModel")
|
||||
self.modelChanged(self.oldModel)
|
||||
self.ret = None
|
||||
|
||||
def displayCards(self):
|
||||
self.cms = self.parent.deck.s.all("""
|
||||
select id, name from cardModels
|
||||
where id in %s
|
||||
order by ordinal""" % ids2str(self.cms))
|
||||
self.items = []
|
||||
for cm in self.cms:
|
||||
item = QListWidgetItem(cm[1], self.dialog.list)
|
||||
self.dialog.list.addItem(item)
|
||||
self.items.append(item)
|
||||
def modelChanged(self, model):
|
||||
self.targetModel = model
|
||||
# just changing template?
|
||||
self.form.fieldMap.setEnabled(self.targetModel != self.oldModel)
|
||||
self.rebuildTemplateMap()
|
||||
self.rebuildFieldMap()
|
||||
|
||||
def rebuildTemplateMap(self, key=None, attr=None):
|
||||
if not key:
|
||||
key = "template"
|
||||
attr = "cardModels"
|
||||
map = getattr(self, key + "MapWidget")
|
||||
lay = getattr(self, key + "MapLayout")
|
||||
src = getattr(self.oldModel, attr)
|
||||
dst = getattr(self.targetModel, attr)
|
||||
if map:
|
||||
lay.removeWidget(map)
|
||||
map.deleteLater()
|
||||
setattr(self, key + "MapWidget", None)
|
||||
map = QWidget()
|
||||
l = QGridLayout()
|
||||
combos = []
|
||||
targets = [x.name for x in dst] + [_("Nothing")]
|
||||
qtargets = QStringList(targets)
|
||||
for i, x in enumerate(src):
|
||||
l.addWidget(QLabel(_("Change %s to:") % x.name), i, 0)
|
||||
cb = QComboBox()
|
||||
cb.addItems(qtargets)
|
||||
cb.setCurrentIndex(min(i, len(targets)-1))
|
||||
combos.append(cb)
|
||||
l.addWidget(cb, i, 1)
|
||||
map.setLayout(l)
|
||||
lay.addWidget(map)
|
||||
setattr(self, key + "MapWidget", map)
|
||||
setattr(self, key + "MapLayout", lay)
|
||||
setattr(self, key + "Combos", combos)
|
||||
|
||||
def rebuildFieldMap(self):
|
||||
return self.rebuildTemplateMap(key="field", attr="fieldModels")
|
||||
|
||||
def getTemplateMap(self, old=None, combos=None, new=None):
|
||||
if not old:
|
||||
old = self.oldModel.cardModels
|
||||
combos = self.templateCombos
|
||||
new = self.targetModel.cardModels
|
||||
map = {}
|
||||
for i, f in enumerate(old):
|
||||
idx = combos[i].currentIndex()
|
||||
if idx == len(new):
|
||||
# ignore
|
||||
map[f] = None
|
||||
else:
|
||||
f2 = new[idx]
|
||||
if f2 in map.values():
|
||||
return None
|
||||
map[f] = f2
|
||||
return map
|
||||
|
||||
def getFieldMap(self):
|
||||
return self.getTemplateMap(
|
||||
old=self.oldModel.fieldModels,
|
||||
combos=self.fieldCombos,
|
||||
new=self.targetModel.fieldModels)
|
||||
|
||||
def accept(self):
|
||||
ret = None
|
||||
r = self.dialog.list.selectionModel().selectedRows()
|
||||
if r:
|
||||
self.newId = self.cms[r[0].row()][0]
|
||||
saveGeom(self, "changeTemplate")
|
||||
QDialog.accept(self)
|
||||
saveGeom(self, "changeModel")
|
||||
# check maps
|
||||
fmap = self.getFieldMap()
|
||||
cmap = self.getTemplateMap()
|
||||
if not cmap or (self.targetModel != self.oldModel and
|
||||
not fmap):
|
||||
return ui.utils.showInfo(
|
||||
_("Targets must be unique."), parent=self)
|
||||
if self.targetModel == self.oldModel:
|
||||
self.ret = (self.targetModel, None, cmap)
|
||||
return QDialog.accept(self)
|
||||
self.ret = (self.targetModel, fmap, cmap)
|
||||
return QDialog.accept(self)
|
||||
|
||||
def onHelp(self):
|
||||
QDesktopServices.openUrl(QUrl(ankiqt.appWiki +
|
||||
"Editor#ChangeTemplate"))
|
||||
"Editor#ChangeModel"))
|
||||
|
|
|
@ -12,7 +12,7 @@ import ankiqt.forms
|
|||
|
||||
class ModelChooser(QHBoxLayout):
|
||||
|
||||
def __init__(self, parent, main, deck, onChangeFunc, cards=True):
|
||||
def __init__(self, parent, main, deck, onChangeFunc, cards=True, label=True):
|
||||
QHBoxLayout.__init__(self)
|
||||
self.parent = parent
|
||||
self.main = main
|
||||
|
@ -21,8 +21,9 @@ class ModelChooser(QHBoxLayout):
|
|||
self.setMargin(0)
|
||||
self.setSpacing(4)
|
||||
self.shortcuts = []
|
||||
label = QLabel(_("<b>Model</b>:"))
|
||||
self.addWidget(label)
|
||||
if label:
|
||||
self.modelLabel = QLabel(_("<b>Model</b>:"))
|
||||
self.addWidget(self.modelLabel)
|
||||
self.models = QComboBox()
|
||||
s = QShortcut(QKeySequence(_("Shift+Alt+m")), self.parent)
|
||||
s.connect(s, SIGNAL("activated()"),
|
||||
|
|
|
@ -13,6 +13,14 @@
|
|||
<string>Edit Items</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>23</y>
|
||||
<width>599</width>
|
||||
<height>439</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout" >
|
||||
<property name="spacing" >
|
||||
<number>0</number>
|
||||
|
@ -162,7 +170,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>599</width>
|
||||
<height>24</height>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuEdit" >
|
||||
|
@ -175,6 +183,7 @@
|
|||
<addaction name="actionSelectAll" />
|
||||
<addaction name="actionSelectFacts" />
|
||||
<addaction name="actionInvertSelection" />
|
||||
<addaction name="separator" />
|
||||
<addaction name="actionReverseOrder" />
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuActions" >
|
||||
|
@ -185,9 +194,10 @@
|
|||
<addaction name="actionDeleteTag" />
|
||||
<addaction name="separator" />
|
||||
<addaction name="actionAddCards" />
|
||||
<addaction name="actionChangeTemplate" />
|
||||
<addaction name="actionChangeModel" />
|
||||
<addaction name="separator" />
|
||||
<addaction name="actionReschedule" />
|
||||
<addaction name="separator" />
|
||||
<addaction name="actionDelete" />
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuJump" >
|
||||
|
@ -202,9 +212,16 @@
|
|||
<addaction name="actionNextCard" />
|
||||
<addaction name="actionLastCard" />
|
||||
</widget>
|
||||
<widget class="QMenu" name="menu_Help" >
|
||||
<property name="title" >
|
||||
<string>&Help</string>
|
||||
</property>
|
||||
<addaction name="actionGuide" />
|
||||
</widget>
|
||||
<addaction name="menuActions" />
|
||||
<addaction name="menuEdit" />
|
||||
<addaction name="menuJump" />
|
||||
<addaction name="menu_Help" />
|
||||
</widget>
|
||||
<action name="actionDelete" >
|
||||
<property name="icon" >
|
||||
|
@ -372,6 +389,16 @@
|
|||
<string>Reverse &Order</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionGuide" >
|
||||
<property name="text" >
|
||||
<string>&Guide...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionChangeModel" >
|
||||
<property name="text" >
|
||||
<string>Change &Model...</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../icons.qrc" />
|
||||
|
|
139
designer/changemodel.ui
Normal file
139
designer/changemodel.ui
Normal file
|
@ -0,0 +1,139 @@
|
|||
<ui version="4.0" >
|
||||
<class>Dialog</class>
|
||||
<widget class="QDialog" name="Dialog" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>294</width>
|
||||
<height>331</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<string>Change Model</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout" >
|
||||
<property name="spacing" >
|
||||
<number>10</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout" >
|
||||
<property name="verticalSpacing" >
|
||||
<number>4</number>
|
||||
</property>
|
||||
<item row="0" column="0" >
|
||||
<widget class="QLabel" name="label_6" >
|
||||
<property name="text" >
|
||||
<string><b>Old Model</b>:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" >
|
||||
<widget class="QLabel" name="oldModelLabel" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy vsizetype="Preferred" hsizetype="Expanding" >
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
<property name="margin" >
|
||||
<number>4</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" >
|
||||
<widget class="QLabel" name="label" >
|
||||
<property name="text" >
|
||||
<string><b>New Model</b>:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" >
|
||||
<widget class="QWidget" native="1" name="modelChooserWidget" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy vsizetype="Preferred" hsizetype="Expanding" >
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="templateMap" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy vsizetype="Expanding" hsizetype="Preferred" >
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title" >
|
||||
<string>Templates</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="fieldMap" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy vsizetype="Expanding" hsizetype="Preferred" >
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title" >
|
||||
<string>Fields</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons" >
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Help|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>Dialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel" >
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel" >
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>Dialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel" >
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel" >
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
Loading…
Reference in a new issue