changing model support

This commit is contained in:
Damien Elmes 2009-02-04 21:44:41 +09:00
parent fea4003ff7
commit 13c5a398b3
4 changed files with 313 additions and 51 deletions

View file

@ -425,14 +425,15 @@ class EditDeck(QMainWindow):
self.connect(self.dialog.actionDelete, SIGNAL("triggered()"), self.deleteCards) self.connect(self.dialog.actionDelete, SIGNAL("triggered()"), self.deleteCards)
self.connect(self.dialog.actionAddTag, SIGNAL("triggered()"), self.addTags) self.connect(self.dialog.actionAddTag, SIGNAL("triggered()"), self.addTags)
self.connect(self.dialog.actionDeleteTag, SIGNAL("triggered()"), self.deleteTags) 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.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.actionSelectFacts, SIGNAL("triggered()"), self.selectFacts)
self.connect(self.dialog.actionInvertSelection, SIGNAL("triggered()"), self.invertSelection) self.connect(self.dialog.actionInvertSelection, SIGNAL("triggered()"), self.invertSelection)
self.connect(self.dialog.actionReverseOrder, SIGNAL("triggered()"), self.reverseOrder) 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 # jumps
self.connect(self.dialog.actionFirstCard, SIGNAL("triggered()"), self.onFirstCard) self.connect(self.dialog.actionFirstCard, SIGNAL("triggered()"), self.onFirstCard)
self.connect(self.dialog.actionLastCard, SIGNAL("triggered()"), self.onLastCard) 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.actionNextCard, SIGNAL("triggered()"), self.onNextCard)
self.connect(self.dialog.actionFind, SIGNAL("triggered()"), self.onFind) self.connect(self.dialog.actionFind, SIGNAL("triggered()"), self.onFind)
self.connect(self.dialog.actionFact, SIGNAL("triggered()"), self.onFact) self.connect(self.dialog.actionFact, SIGNAL("triggered()"), self.onFact)
# help
self.connect(self.dialog.actionGuide, SIGNAL("triggered()"), self.onHelp)
runHook('editor.setupMenus', self) runHook('editor.setupMenus', self)
def onClose(self): def onClose(self):
@ -627,28 +630,31 @@ where id in (%s)""" % ",".join([
self.updateSearch() self.updateSearch()
self.updateAfterCardChange() self.updateAfterCardChange()
def onChangeTemplate(self): def onChangeModel(self):
sc = self.selectedCards() sf = self.selectedFacts()
models = self.deck.s.column0(""" cms = self.deck.s.column0("""
select distinct modelId from cards, facts where select distinct modelId from facts
cards.id in %s and cards.factId = facts.id""" % ids2str(sc)) where id in %s""" % ids2str(sf))
if not len(models) == 1: if not len(cms) == 1:
ui.utils.showInfo( ui.utils.showInfo(
_("Can only change templates in a single model."), _("Can only change one model at a time."),
parent=self) parent=self)
return return
cms = [x.id for x in d = ChangeModelDialog(self, self.currentCard.fact.model,
self.currentCard.fact.model.cardModels] self.currentCard.cardModel)
d = ChangeTemplateDialog(self, cms)
d.exec_() d.exec_()
n = _("Change Template") self.parent.setProgressParent(self)
if d.newId: if d.ret:
n = _("Change Model")
self.deck.setUndoStart(n) self.deck.setUndoStart(n)
self.deck.changeCardModel(sc, d.newId) self.deck.changeModel(sf, *d.ret)
self.deck.setUndoEnd(n) self.deck.setUndoEnd(n)
self.updateSearch() self.updateSearch()
self.updateAfterCardChange() self.updateAfterCardChange()
# Edit: selection
######################################################################
def selectFacts(self): def selectFacts(self):
sm = self.dialog.tableView.selectionModel() sm = self.dialog.tableView.selectionModel()
cardIds = dict([(x, 1) for x in self.selectedFactsAsCards()]) 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.model.reset()
self.focusCurrentCard() self.focusCurrentCard()
# Undo/Redo # Edit: undo/redo
###################################################################### ######################################################################
def onUndo(self): def onUndo(self):
@ -725,6 +731,15 @@ cards.id in %s and cards.factId = facts.id""" % ids2str(sc))
def onFact(self): def onFact(self):
self.editor.focusFirst() self.editor.focusFirst()
# Help
######################################################################
def onHelp(self):
QDesktopServices.openUrl(QUrl(ankiqt.appWiki + "Editor"))
# Generate card dialog
######################################################################
class AddCardChooser(QDialog): class AddCardChooser(QDialog):
def __init__(self, parent, cms): def __init__(self, parent, cms):
@ -768,41 +783,121 @@ order by ordinal""" % ids2str(self.cms))
QDesktopServices.openUrl(QUrl(ankiqt.appWiki + QDesktopServices.openUrl(QUrl(ankiqt.appWiki +
"Editor#GenerateCards")) "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) QDialog.__init__(self, parent, Qt.Window)
self.parent = parent self.parent = parent
self.cms = cms self.oldModel = oldModel
self.newId = None self.oldTemplate = oldTemplate
self.dialog = ankiqt.forms.addcardmodels.Ui_Dialog() self.form = ankiqt.forms.changemodel.Ui_Dialog()
self.dialog.setupUi(self) self.form.setupUi(self)
self.connect(self.dialog.buttonBox, SIGNAL("helpRequested()"), # 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.onHelp)
self.setWindowTitle(_("Change Template")) restoreGeom(self, "changeModel")
self.dialog.list.setSelectionMode(QAbstractItemView.SingleSelection) self.modelChanged(self.oldModel)
self.displayCards() self.ret = None
restoreGeom(self, "changeTemplate")
def displayCards(self): def modelChanged(self, model):
self.cms = self.parent.deck.s.all(""" self.targetModel = model
select id, name from cardModels # just changing template?
where id in %s self.form.fieldMap.setEnabled(self.targetModel != self.oldModel)
order by ordinal""" % ids2str(self.cms)) self.rebuildTemplateMap()
self.items = [] self.rebuildFieldMap()
for cm in self.cms:
item = QListWidgetItem(cm[1], self.dialog.list) def rebuildTemplateMap(self, key=None, attr=None):
self.dialog.list.addItem(item) if not key:
self.items.append(item) 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): def accept(self):
ret = None saveGeom(self, "changeModel")
r = self.dialog.list.selectionModel().selectedRows() # check maps
if r: fmap = self.getFieldMap()
self.newId = self.cms[r[0].row()][0] cmap = self.getTemplateMap()
saveGeom(self, "changeTemplate") if not cmap or (self.targetModel != self.oldModel and
QDialog.accept(self) 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): def onHelp(self):
QDesktopServices.openUrl(QUrl(ankiqt.appWiki + QDesktopServices.openUrl(QUrl(ankiqt.appWiki +
"Editor#ChangeTemplate")) "Editor#ChangeModel"))

View file

@ -12,7 +12,7 @@ import ankiqt.forms
class ModelChooser(QHBoxLayout): 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) QHBoxLayout.__init__(self)
self.parent = parent self.parent = parent
self.main = main self.main = main
@ -21,8 +21,9 @@ class ModelChooser(QHBoxLayout):
self.setMargin(0) self.setMargin(0)
self.setSpacing(4) self.setSpacing(4)
self.shortcuts = [] self.shortcuts = []
label = QLabel(_("<b>Model</b>:")) if label:
self.addWidget(label) self.modelLabel = QLabel(_("<b>Model</b>:"))
self.addWidget(self.modelLabel)
self.models = QComboBox() self.models = QComboBox()
s = QShortcut(QKeySequence(_("Shift+Alt+m")), self.parent) s = QShortcut(QKeySequence(_("Shift+Alt+m")), self.parent)
s.connect(s, SIGNAL("activated()"), s.connect(s, SIGNAL("activated()"),

View file

@ -13,6 +13,14 @@
<string>Edit Items</string> <string>Edit Items</string>
</property> </property>
<widget class="QWidget" name="centralwidget" > <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" > <layout class="QVBoxLayout" name="verticalLayout" >
<property name="spacing" > <property name="spacing" >
<number>0</number> <number>0</number>
@ -162,7 +170,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>599</width> <width>599</width>
<height>24</height> <height>23</height>
</rect> </rect>
</property> </property>
<widget class="QMenu" name="menuEdit" > <widget class="QMenu" name="menuEdit" >
@ -175,6 +183,7 @@
<addaction name="actionSelectAll" /> <addaction name="actionSelectAll" />
<addaction name="actionSelectFacts" /> <addaction name="actionSelectFacts" />
<addaction name="actionInvertSelection" /> <addaction name="actionInvertSelection" />
<addaction name="separator" />
<addaction name="actionReverseOrder" /> <addaction name="actionReverseOrder" />
</widget> </widget>
<widget class="QMenu" name="menuActions" > <widget class="QMenu" name="menuActions" >
@ -185,9 +194,10 @@
<addaction name="actionDeleteTag" /> <addaction name="actionDeleteTag" />
<addaction name="separator" /> <addaction name="separator" />
<addaction name="actionAddCards" /> <addaction name="actionAddCards" />
<addaction name="actionChangeTemplate" /> <addaction name="actionChangeModel" />
<addaction name="separator" /> <addaction name="separator" />
<addaction name="actionReschedule" /> <addaction name="actionReschedule" />
<addaction name="separator" />
<addaction name="actionDelete" /> <addaction name="actionDelete" />
</widget> </widget>
<widget class="QMenu" name="menuJump" > <widget class="QMenu" name="menuJump" >
@ -202,9 +212,16 @@
<addaction name="actionNextCard" /> <addaction name="actionNextCard" />
<addaction name="actionLastCard" /> <addaction name="actionLastCard" />
</widget> </widget>
<widget class="QMenu" name="menu_Help" >
<property name="title" >
<string>&amp;Help</string>
</property>
<addaction name="actionGuide" />
</widget>
<addaction name="menuActions" /> <addaction name="menuActions" />
<addaction name="menuEdit" /> <addaction name="menuEdit" />
<addaction name="menuJump" /> <addaction name="menuJump" />
<addaction name="menu_Help" />
</widget> </widget>
<action name="actionDelete" > <action name="actionDelete" >
<property name="icon" > <property name="icon" >
@ -372,6 +389,16 @@
<string>Reverse &amp;Order</string> <string>Reverse &amp;Order</string>
</property> </property>
</action> </action>
<action name="actionGuide" >
<property name="text" >
<string>&amp;Guide...</string>
</property>
</action>
<action name="actionChangeModel" >
<property name="text" >
<string>Change &amp;Model...</string>
</property>
</action>
</widget> </widget>
<resources> <resources>
<include location="../icons.qrc" /> <include location="../icons.qrc" />

139
designer/changemodel.ui Normal file
View 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>&lt;b>Old Model&lt;/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>&lt;b>New Model&lt;/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>