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.setSelectionMode( QAbstractItemView.ExtendedSelection) posWidth = len(str(len(cardInfo) + 1)) for i, card in enumerate(cardInfo, start=1): text = '❰ {} ❱\t{}'.format(str(i).zfill(posWidth), 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) randomizeButton = QPushButton('Randomize') randomizeButton.clicked.connect(self._randomize) controlsLayout = QHBoxLayout() controlsLayout.addStretch() controlsLayout.addWidget(upButton) controlsLayout.addWidget(downButton) 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)
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' /> <span style='font-weight:bold'>of " + str( len(cardDataList)) + "</span> " newPosField += "<input type='button' value='Apply' onclick='directMove()' /> <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)
def showDialog(self, currentCard=None): if currentCard: self.did = currentCard.did elif mw._selectedDeck(): self.did = mw._selectedDeck()['id'] else: return if not self._getCardInfo(self.did): 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) self.cardListWidget.itemDoubleClicked.connect(lambda: showBrowser( self.cardListWidget.currentItem().data(Qt.UserRole)['nid'])) self._updateListItems() 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)
def showIRSchedulerDialog(self, currentCard): #Handle for dialog open without a current card from IRead2 model deckID = None; cardID = None; if(currentCard == None): deck = mw._selectedDeck(); deckID = deck['id']; else: deckID = currentCard.did; cardID = currentCard.id; #Get the card data for the deck. Make sure it is an Incremental Reading deck (has IRead2 cards) before showing dialog cardDataList = self.getCardDataList(deckID, cardID); hasIRead2Cards = False; for cd in cardDataList: if(cd['title'] != 'No Title'): hasIRead2Cards = True; if(hasIRead2Cards == False): showInfo(_("Please select an Incremental Reading deck.")) return; d = QDialog(self.mw) l = QVBoxLayout() l.setMargin(0) w = AnkiWebView() l.addWidget(w) #Add python object to take values back from javascript callback = IRSchedulerCallback(); #callback.setCard(currentCard); w.page().mainFrame().addToJavaScriptWindowObject("callback", callback); #Script functions move up / move down / delete / open getIRSchedulerDialogScript = """ var cardList = new Array(); """ index = 0; for cardData in cardDataList: index+=1; getIRSchedulerDialogScript += "card = new Object();"; getIRSchedulerDialogScript += "card.id = " + str(cardData['id']) + ";"; getIRSchedulerDialogScript += "card.title = '" + str(cardData['title']) + "';"; getIRSchedulerDialogScript += "card.isCurrent = " + str(cardData['isCurrent']) + ";"; getIRSchedulerDialogScript += "card.checkbox = document.createElement('input');"; getIRSchedulerDialogScript += "card.checkbox.type = 'checkbox';"; if(cardData['isCurrent'] == 'true'): getIRSchedulerDialogScript += "card.checkbox.setAttribute('checked', 'true');"; getIRSchedulerDialogScript += "cardList[cardList.length] = card;"; getIRSchedulerDialogScript += """ 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); } callback.updatePositions(cids); }; """; #Incremental Reading list as a list of nested <div> tags (like a table, but more flexible) #position,title,series id, sequence number,card id (hidden) newPosField = "<span style='font-weight:bold'>Card Position: </span><input type='text' id='newPos' size='5' value='0' /> <span style='font-weight:bold'>of " + str(len(cardDataList)) + "</span> "; newPosField += "<input type='button' value='Apply' onclick='directMove()' /> <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>" + getIRSchedulerDialogScript + "</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.connect(bb, SIGNAL("accepted()"), d, SLOT("accept()")) bb.connect(bb, SIGNAL("rejected()"), d, SLOT("reject()")) bb.setOrientation(QtCore.Qt.Horizontal); l.addWidget(bb) d.setLayout(l) d.setWindowModality(Qt.WindowModal) d.resize(500, 500) choice = d.exec_(); if(choice == 1): w.eval("updatePositions()"); else: if(currentCard != None): self.repositionCard(currentCard, -1);