def test4SaveCards(self): for index in range(50): forbidden = "['word1', 'word2', 'word3', 'word4']" card = CardModel("word_" + str(index + 1), forbidden, "Book", "345") self.session.add(card) self.session.flush() self.session.commit() self.assertEqual(CardModel.numberOfRows(self.session), 50)
def __init__(self, parent = None): QMainWindow.__init__(self, parent) config.load() self.setFont(QFont("Fixed", 8)) # set up controls # items panel self._cardModel = CardModel() self._cardModelIndex = QModelIndex() # current index for card model self.setWindowTitle("Mentor") self.setWindowIcon(QIcon(QPixmap(":/images/mentor.png"))) self.setGeometry(config.GUI_GEOMETRY) if config.GUI_MAXIMIZED: self.setWindowState(Qt.WindowMaximized) self.createCentralWidget() self.createActions() self.createMenus() self.createToolbars() self.createStatusBar() self.propagateFonts(self, QFont("Fixed", 8)) self.connect(qApp, SIGNAL('aboutToQuit()'), self.qApp_aboutToQuit) QTimer.singleShot(0, self._openRecentFile)
def testSaveCard(self): delete_db(engine) AppModelBase.metadata.create_all(engine) forbidden = "{'word1', 'word2', 'word3', 'word4'}" card = CardModel(buzzword="unit test", forbidden_words=forbidden, source="Book", source_page="345", skipped_count=0, won_count=0, lost_count=0, is_phrase=IS_PHRASE) self.session.add(card) self.session.commit() card = CardModel.findCardById(self.session, 1) self.assertEqual(card.buzzword, "unit test")
def test5AddUsedCard(self): game = GameModel.getGameById(1, self.session) card = CardModel.findCardById(self.session, 2) game.addUsedCard(card) self.session.flush() self.session.commit() self.assertTrue(card in game.usedCards) unusedCards = game.getUnusedCards() self.assertEqual(len(unusedCards), 49)
def start_game_db(Session): session = Session() players = list() players.append( PlayerModel(nickname='nwhite', email='*****@*****.**', role=4)) players.append( PlayerModel(nickname='nwhite2', email='*****@*****.**', role=4)) players.append( PlayerModel(nickname='nwhite3', email='*****@*****.**', role=4)) players.append( PlayerModel(nickname='nwhite4', email='*****@*****.**', role=4)) numberOfTeams = 2 minRequiredPlayers = 2 maxPlayersPerTeam = 2 game = GameModel(name='game1', initiator=players[0], numberOfTeams=numberOfTeams, minRequiredPlayers=minRequiredPlayers, maxPlayersPerTeam=maxPlayersPerTeam) for index in range(50): print("Putting card.") forbidden = "{'word1', 'word2', 'word3', 'word4'}" card = CardModel("word_" + str(index + 1), forbidden, "Book", "345") session.add(card) session.add(game) session.commit() for i in range(numberOfTeams): teamName = 'team' + str(i) team = TeamModel(teamName) if (i == 0): team.addPlayer(players[0]) team.addPlayer(players[1]) else: team.addPlayer(players[2]) team.addPlayer(players[3]) game.addTeam(team) game.gameState = GAME_READY session.commit() session.close()
def mutate(root, info, idNumber, name, dob=None, address=None, hometown=None, cardName=None): card = CardModel( idNumber=idNumber, name=name, dob=dob, address=address, hometown=hometown, cardName=cardName, ) ok = True SaveCard(card) return CreateCard(card=card, ok=ok)
def getQuizletCards(login='******', client_id='SN77uEA94G', endpoint='258934949'): # Getting the cards from quizlet. session = globalVars.Session() quizletClient = quizlet.QuizletClient(client_id=client_id, login=login) data = quizletClient.sets.endpoint.get(endpoint) count = 0 for term in data['terms']: count += 1 definitions = term['definition'].split('\n') buzzword = term['term'].strip() buzzword.split() card = CardModel(buzzword=buzzword, forbidden_words=json.dumps(definitions[:-1]), source=definitions[-1], source_page=' '.join(definitions[-1].split()[-2:]), is_phrase=(len(buzzword.split()) > 1), quizletEndpoint=endpoint) session.add(card) session.commit() session.close()
def setUp(self): self.model = CardModel() self.model.open(':memory:') self.view = DummyView() self.view.setModel(self.model)
class TestCardModel(unittest.TestCase): def setUp(self): self.model = CardModel() self.model.open(':memory:') self.view = DummyView() self.view.setModel(self.model) def tearDown(self): self.model.close() def test_filePath(self): # test on open model self.assertEqual(self.model.filepath(), ':memory:') # test on closed model self.model.close() self.assertEqual(self.model.filepath(), None) def test_isActive(self): self.assertEqual(self.model.isActive(), True) # test on closed model self.model.close() self.assertEqual(self.model.isActive(), False) def test_checkActive(self): # open model should not raise any exception self.model._checkActive() # test if raises correct exception self.model.close() self.assertRaises(CardModel.ModelNotActiveError, self.model._checkActive) def test_columnCount(self): # test on empty model self.assertEqual(self.model.columnCount(), 5) # test on closed model self.model.close() self.assertEqual(self.model.columnCount(), 0) def test_rowCount(self): # test on empty database self.assertEqual(self.model.rowCount(), 0) # add three empty rows self.model.addNewCard() self.model.addNewCard() self.model.addNewCard() self.assertEqual(self.model.rowCount(), 3) # test on closed model self.model.close() self.assertEqual(self.model.rowCount(), 0) def test_checkIndex(self): # test if _checkIndex raises correct exception # test on None self.assertRaises(CardModel.InvalidIndexError, self.model._checkIndex, None) # test on empty idx = QModelIndex() self.assertRaises(CardModel.InvalidIndexError, self.model._checkIndex, idx) def test_index(self): # test index on empty model idx1 = self.model.index(0, 0) self.assertEqual(idx1, QModelIndex()) # add two cards and check their ids self.model.addNewCard() self.model.addNewCard() idx1 = self.model.index(0, 0) idx2 = self.model.index(1, 0) idx3 = self.model.index(2, 0) self.assertEqual(idx1.internalId(), 1) self.assertEqual(idx2.internalId(), 2) self.assertEqual(idx3, QModelIndex()) def test_data(self): # test if generates error with invalid index idx = QModelIndex() self.assertRaises(CardModel.InvalidIndexError, self.model.data, idx) def test_previousNextIndex(self): # previous index on empty index self.model.addNewCard() self.model.addNewCard() idx1 = self.model.index(0, 0) idx2 = self.model.index(1, 1) # test previous self.assertEqual(self.model.getPreviousIndex(idx2).internalId(), idx1.internalId()) # test next self.assertEqual(self.model.getNextIndex(idx1).internalId(), idx2.internalId()) def test_addNewCard(self): # test if adding new card generates a proper signal self.assertEqual(self.view.got_reset, False) self.model.addNewCard() self.model.addNewCard() self.model.addNewCard() self.assertEqual(self.view.got_reset, True) def test_deleteCard(self): # test if deleting card generates a proper signal # add 2 cards self.assertEqual(self.view.got_reset, False) self.model.addNewCard() self.model.addNewCard() self.assertEqual(self.view.got_reset, True) # reset view self.view.got_reset = False # delete first index = self.model.index(0, 0) self.model.deleteCard(index) # did it generate signal ? self.assertEqual(self.view.got_reset, True) # delete again self.view.got_reset = False index = self.model.index(0, 0) self.model.deleteCard(index) # did it generate signal? self.assertEqual(self.view.got_reset, True) # row count should be 0 now self.assertEqual(self.model.rowCount(), 0) # try to delete on empty model index = self.model.index(0, 0) self.assertEqual(index, QModelIndex()) # should generate invalid index self.assertRaises(CardModel.InvalidIndexError, self.model.deleteCard, index) def test_updateCard(self): self.model.addNewCard() idx = self.model.index(0, 0) self.model.updateCard(idx, 'testquestion', 'testanswer') # test if got signal self.assertEqual(self.view.got_dataChanged, True) # test if data is correct data = self.model.data(idx, Qt.UserRole) self.assertEqual(data.question, 'testquestion') self.assertEqual(data.answer, 'testanswer') def test_importQAFile(self): # # test if clean actually cleans the file self.model.addNewCard() self.model.addNewCard() qa = StringIO(r""" q: question1 a: answer1 q: question2 a: answer2""") self.model.importQAFile(qa, True) self.assertEqual(self.model.rowCount(), 2) idx = self.model.index(0, 0) card1 = self.model.data(self.model.index(0, 0), Qt.UserRole) self.assertEqual(card1.question, 'question1\n') self.assertEqual(card1.answer, 'answer1\n') card2 = self.model.data(self.model.index(1, 0), Qt.UserRole) self.assertEqual(card2.question, 'question2\n') self.assertEqual(card2.answer, 'answer2') # test import on closed model self.model.close() self.assertRaises(CardModel.ModelNotActiveError, self.model.importQAFile, 'sample')
class TestCardModel(unittest.TestCase): def setUp(self): self.model = CardModel() self.model.open(':memory:') self.view = DummyView() self.view.setModel(self.model) def tearDown(self): self.model.close() def test_filePath(self): # test on open model self.assertEqual(self.model.filepath(), ':memory:') # test on closed model self.model.close() self.assertEqual(self.model.filepath(), None) def test_isActive(self): self.assertEqual(self.model.isActive(), True) # test on closed model self.model.close() self.assertEqual(self.model.isActive(), False) def test_checkActive(self): # open model should not raise any exception self.model._checkActive() # test if raises correct exception self.model.close() self.assertRaises(CardModel.ModelNotActiveError, self.model._checkActive) def test_columnCount(self): # test on empty model self.assertEqual(self.model.columnCount(), 5) # test on closed model self.model.close() self.assertEqual(self.model.columnCount(), 0) def test_rowCount(self): # test on empty database self.assertEqual(self.model.rowCount(), 0) # add three empty rows self.model.addNewCard() self.model.addNewCard() self.model.addNewCard() self.assertEqual(self.model.rowCount(), 3) # test on closed model self.model.close() self.assertEqual(self.model.rowCount(), 0) def test_checkIndex(self): # test if _checkIndex raises correct exception # test on None self.assertRaises(CardModel.InvalidIndexError, self.model._checkIndex, None) # test on empty idx = QModelIndex() self.assertRaises(CardModel.InvalidIndexError, self.model._checkIndex, idx) def test_index(self): # test index on empty model idx1 = self.model.index(0, 0) self.assertEqual(idx1, QModelIndex()) # add two cards and check their ids self.model.addNewCard() self.model.addNewCard() idx1 = self.model.index(0, 0) idx2 = self.model.index(1, 0) idx3 = self.model.index(2, 0) self.assertEqual(idx1.internalId(), 1) self.assertEqual(idx2.internalId(), 2) self.assertEqual(idx3, QModelIndex()) def test_data(self): # test if generates error with invalid index idx = QModelIndex() self.assertRaises(CardModel.InvalidIndexError, self.model.data, idx) def test_previousNextIndex(self): # previous index on empty index self.model.addNewCard() self.model.addNewCard() idx1 = self.model.index(0, 0) idx2 = self.model.index(1, 1) # test previous self.assertEqual( self.model.getPreviousIndex(idx2).internalId(), idx1.internalId()) # test next self.assertEqual( self.model.getNextIndex(idx1).internalId(), idx2.internalId()) def test_addNewCard(self): # test if adding new card generates a proper signal self.assertEqual(self.view.got_reset, False) self.model.addNewCard() self.model.addNewCard() self.model.addNewCard() self.assertEqual(self.view.got_reset, True) def test_deleteCard(self): # test if deleting card generates a proper signal # add 2 cards self.assertEqual(self.view.got_reset, False) self.model.addNewCard() self.model.addNewCard() self.assertEqual(self.view.got_reset, True) # reset view self.view.got_reset = False # delete first index = self.model.index(0, 0) self.model.deleteCard(index) # did it generate signal ? self.assertEqual(self.view.got_reset, True) # delete again self.view.got_reset = False index = self.model.index(0, 0) self.model.deleteCard(index) # did it generate signal? self.assertEqual(self.view.got_reset, True) # row count should be 0 now self.assertEqual(self.model.rowCount(), 0) # try to delete on empty model index = self.model.index(0, 0) self.assertEqual(index, QModelIndex()) # should generate invalid index self.assertRaises(CardModel.InvalidIndexError, self.model.deleteCard, index) def test_updateCard(self): self.model.addNewCard() idx = self.model.index(0, 0) self.model.updateCard(idx, 'testquestion', 'testanswer') # test if got signal self.assertEqual(self.view.got_dataChanged, True) # test if data is correct data = self.model.data(idx, Qt.UserRole) self.assertEqual(data.question, 'testquestion') self.assertEqual(data.answer, 'testanswer') def test_importQAFile(self): # # test if clean actually cleans the file self.model.addNewCard() self.model.addNewCard() qa = StringIO(r""" q: question1 a: answer1 q: question2 a: answer2""") self.model.importQAFile(qa, True) self.assertEqual(self.model.rowCount(), 2) idx = self.model.index(0, 0) card1 = self.model.data(self.model.index(0, 0), Qt.UserRole) self.assertEqual(card1.question, 'question1\n') self.assertEqual(card1.answer, 'answer1\n') card2 = self.model.data(self.model.index(1, 0), Qt.UserRole) self.assertEqual(card2.question, 'question2\n') self.assertEqual(card2.answer, 'answer2') # test import on closed model self.model.close() self.assertRaises(CardModel.ModelNotActiveError, self.model.importQAFile, 'sample')
def testRemoveForbiddenWords(self): card = CardModel.findCardById(self.session, 1) card.removeForbiddenWords() self.assertEqual(card.forbiddenWords, "")
def testCountCard(self): self.assertEqual(CardModel.numberOfRows(self.session), 1)
class MainWindow(QMainWindow): """Central window for the Mentor app""" def __init__(self, parent = None): QMainWindow.__init__(self, parent) config.load() self.setFont(QFont("Fixed", 8)) # set up controls # items panel self._cardModel = CardModel() self._cardModelIndex = QModelIndex() # current index for card model self.setWindowTitle("Mentor") self.setWindowIcon(QIcon(QPixmap(":/images/mentor.png"))) self.setGeometry(config.GUI_GEOMETRY) if config.GUI_MAXIMIZED: self.setWindowState(Qt.WindowMaximized) self.createCentralWidget() self.createActions() self.createMenus() self.createToolbars() self.createStatusBar() self.propagateFonts(self, QFont("Fixed", 8)) self.connect(qApp, SIGNAL('aboutToQuit()'), self.qApp_aboutToQuit) QTimer.singleShot(0, self._openRecentFile) # FIXME there must be a way to configure another way! def propagateFonts(self, widget, font): for c in widget.children(): if isinstance(c, QWidget): c.setFont(font) self.propagateFonts(c, font) def createCentralWidget(self): self.gridView = CardGridView(self) self.gridView.setModel(self._cardModel) self.contentView = CardContentView(self) self.contentView.setModel(self._cardModel) self.splitter = QSplitter(Qt.Horizontal) self.splitter.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.splitter.addWidget(self.gridView) self.splitter.addWidget(self.contentView) self.splitter.setSizes([200, 500]) self.setCentralWidget(self.splitter) ########################## # connecting # FIXME connecting these 4 times cause sometimes I don't get proper # messages # when I edit something and press Down # and then click on what I edited then selection changed does not catch # it self.connect(self.gridView.selectionModel(), \ SIGNAL('currentChanged(QModelIndex, QModelIndex)'), \ self.gridView_currentChanged) self.connect(self.gridView, SIGNAL('activated(QModelIndex)'), \ self.gridView_activated) self.connect(self.gridView, SIGNAL('clicked(QModelIndex)'), \ self.gridView_activated) self.connect(self, SIGNAL('cardModelIndexChanged'), self.gridView_cardModelIndexChanged) self.connect(self, SIGNAL('cardModelIndexChanged'), self.contentView.currentChanged) def cardModel(self): return self._cardModel def setCardModel(self, model): self._cardModel = model def cardModelIndex(self): return self._cardModelIndex def setCardModelIndex(self, index): old = self._cardModelIndex # if old != index: self._cardModelIndex = index self.emit(SIGNAL('cardModelIndexChanged'), index, old) def createActions(self): # File actions self.actNewDeck = QAction(tr("&New deck..."), self) self.actNewDeck.setStatusTip(tr("Create a new deck...")) self.connect(self.actNewDeck, SIGNAL("triggered()"), self.on_actNewDeck_triggered) self.actOpenDeck = QAction(tr("&Open deck..."), self) self.actOpenDeck.setShortcut(QKeySequence(tr("Ctrl+O"))) self.actOpenDeck.setStatusTip(tr("Open an existing deck...")) self.connect(self.actOpenDeck, SIGNAL("triggered()"), self.on_actOpenDeck_triggered) self.actCloseDeck = QAction(tr("&Close deck"), self) self.actCloseDeck.setStatusTip(tr("Close currently active deck")) self.connect(self.actCloseDeck, SIGNAL("triggered()"), self.on_actCloseDeck_triggered) self.actCopyDeck = QAction(tr("&Copy deck..."), self) self.actCopyDeck.setStatusTip(tr("Copy an existing deck...")) self.connect(self.actCopyDeck, SIGNAL("triggered()"), self.on_actCopyDeck_triggered) self.actDeleteDeck = QAction(tr("&Delete deck..."), self) self.actDeleteDeck.setStatusTip(tr("Delete an existing deck...")) self.connect(self.actDeleteDeck, SIGNAL("triggered()"), self.on_actDeleteDeck_triggered) self.actRepairDeck = QAction(tr("&Repair deck..."), self) self.actRepairDeck.setStatusTip(tr("Repair an existing deck...")) self.connect(self.actRepairDeck, SIGNAL("triggered()"), self.on_actRepairDeck_triggered) self.actMergeDeck = QAction(tr("&Merge deck..."), self) self.actMergeDeck.setStatusTip(tr("Merge an existing deck...")) self.connect(self.actMergeDeck, SIGNAL("triggered()"), self.on_actMergeDeck_triggered) self.actImportQA = QAction(tr("&Import from QA file..."), self) self.actImportQA.setStatusTip(tr("Import from QA file...")) self.connect(self.actImportQA, SIGNAL("triggered()"), self.on_actImportQA_triggered) self.actImportXML = QAction(tr("&Import from XML file..."), self) self.actImportXML.setStatusTip(tr("Import from XML file...")) self.connect(self.actImportXML, SIGNAL("triggered()"), self.on_actImportXML_triggered) self.actImportProbe = QAction(tr("&Import from PRB file..."), self) self.actImportProbe.setStatusTip(tr("Import from a PRB file...")) self.connect(self.actImportProbe, SIGNAL("triggered()"), self.on_actImportProbe_triggered) self.actImportSuperMemo = QAction(tr("&Import from SuperMemo..."), self) self.actImportProbe.setStatusTip(tr("Import from a SuperMemo...")) self.connect(self.actImportProbe, SIGNAL("triggered()"), self.on_actImportProbe_triggered) self.actExportQA = QAction(tr("&Export to QA file..."), self) self.actExportQA.setStatusTip(tr("Export to QA file...")) self.connect(self.actExportQA, SIGNAL("triggered()"), self.on_actExportQA_triggered) self.actExportXML = QAction(tr("&Export to XML file..."), self) self.actExportXML.setStatusTip(tr("Export to XML file...")) self.connect(self.actExportXML, SIGNAL("triggered()"), self.on_actExportXML_triggered) self.actExportProbe = QAction(tr("&Export to PRB file..."), self) self.actExportProbe.setStatusTip(tr("Export to PRB file...")) self.connect(self.actExportProbe, SIGNAL("triggered()"), self.on_actExportProbe_triggered) self.actExportSuperMemo = QAction(tr("&Export to SuperMemo..."), self) self.actExportProbe.setStatusTip(tr("Export to SuperMemo...")) self.connect(self.actExportProbe, SIGNAL("triggered()"), self.on_actExportProbe_triggered) self.actProperties = QAction(tr("&Properties..."), self) self.actExportProbe.setStatusTip(tr("Display deck properties...")) self.connect(self.actExportProbe, SIGNAL("triggered()"), self.on_actExportProbe_triggered) # Recent file actions self.actRecentFiles = [] for i in range(config.GUI_RECENTFILES_MAX): self.actRecentFiles.append(QAction(self)) self.actRecentFiles[i].setVisible(False) self.connect(self.actRecentFiles[i], SIGNAL("triggered()"), self.on_actRecentFiles_triggered) # self.actExit = QAction(tr("E&xit"), self) self.actExit.setShortcut(QKeySequence(tr("Ctrl+Q"))) self.actExit.setStatusTip(tr("Exits the application.")) self.connect(self.actExit, SIGNAL("triggered()"), qApp, SLOT("quit()")) # Edit actions self.actUndo = QAction(tr("&Undo"), self) self.actUndo.setShortcut(QKeySequence(tr("Ctrl+Z"))) self.actRedo = QAction(tr("Re&do"), self) self.actRedo.setShortcut(QKeySequence(tr("Ctrl+Y"))) self.actCut = QAction(tr("Cu&t"), self) self.actCut.setShortcut(QKeySequence(tr("Ctrl+X"))) self.actCopy = QAction(tr("&Copy"), self) self.actUndo.setShortcut(QKeySequence(tr("Ctrl+C"))) self.actPaste = QAction(tr("&Paste"), self) self.actPaste.setShortcut(QKeySequence(tr("Ctrl+V"))) self.actCutAppend = QAction(tr("Cut and append"), self) self.actCutAppend.setShortcut(QKeySequence(tr("Ctrl+Shift+X"))) self.actCopyAppend = QAction(tr("Copy and append"), self) self.actCopyAppend.setShortcut(QKeySequence(tr("Ctrl+Shift+C"))) self.actSelectAll = QAction(tr("Select &all"), self) self.actSelectAll.setShortcut(QKeySequence(tr("Ctrl+A"))) self.actSelectLine = QAction(tr("Select &line"), self) self.actSelectWord = QAction(tr("Select &word"), self) self.actSelectWord.setShortcut(QKeySequence(tr("Ctrl+J"))) self.actDelete = QAction(tr("&Delete"), self) self.actDelete.setShortcut(QKeySequence(tr("DEL"))) self.actDeleteLine = QAction(tr("&Delete &line"), self) self.actDeleteLine.setShortcut(QKeySequence(tr("Ctrl+E"))) self.actDeleteToStartLine = QAction(tr("Delete to &start of line"), self) self.actDeleteToStartLine.setShortcut(QKeySequence(tr("Ctrl+F11"))) self.actDeleteToEndLine = QAction(tr("Delete to &end of line"), self) self.actDeleteToEndLine.setShortcut(QKeySequence(tr("Ctrl+F12"))) # Cards actions self.actFirstCard = QAction(tr("&First"), self) self.actFirstCard.setShortcut(QKeySequence("Shift+Ctrl+PgUp")) self.connect(self.actFirstCard, SIGNAL("triggered()"), self.on_actFirstCard_triggered) self.actPreviousCard = QAction(tr("&Previous"), self) self.actPreviousCard.setShortcut(QKeySequence("Ctrl+PgUp")) self.connect(self.actPreviousCard, SIGNAL("triggered()"), self.on_actPreviousCard_triggered) self.actNextCard = QAction(tr("&Next"), self) self.actNextCard.setShortcut(QKeySequence("Ctrl+PgDown")) self.connect(self.actNextCard, SIGNAL("triggered()"), self.on_actNextCard_triggered) self.actLastCard = QAction(tr("&Last"), self) self.actLastCard.setShortcut(QKeySequence("Shift+Ctrl+PgDown")) self.connect(self.actLastCard, SIGNAL("triggered()"), self.on_actLastCard_triggered) self.actAddCard = QAction(tr("&Add"), self) self.actAddCard.setShortcut(QKeySequence(tr("Ctrl+N"))) self.connect(self.actAddCard, SIGNAL("triggered()"), self.on_actAddCard_triggered) self.actInsertCard = QAction(tr("&Insert"), self) self.actInsertCard.setShortcut(QKeySequence(tr("Ctrl+Ins"))) self.connect(self.actInsertCard, SIGNAL("triggered()"), self.on_actInsertCard_triggered) self.actDeleteCard = QAction(tr("&Delete"), self) self.actDeleteCard.setShortcut(QKeySequence(tr("Ctrl+Del"))) self.connect(self.actDeleteCard, SIGNAL("triggered()"), self.on_actDeleteCard_triggered) self.actSort = QAction(tr("&Sort..."), self) self.actFilter = QAction(tr("&Filter..."), self) # Cards action -> from Edit/SuperMemo self.actNewItem = QAction(tr("Add a new i&tem"), self) self.actNewItem.setShortcut(QKeySequence(tr("Alt+A"))) self.actNewArticle = QAction(tr("Add a new &article"), self) self.actNewArticle.setShortcut(QKeySequence(tr("Ctrl+Alt+N"))) self.actNewTask = QAction(tr("Add a &new task"), self) self.actNewTask.setShortcut(QKeySequence("Ctrl+Alt+A")) # Search actions self.actFindElements = QAction(tr("&Find elements"), self) self.actFindElements.setShortcut(QKeySequence(tr("Ctrl+F"))) self.actFindTexts = QAction(tr("Fi&nd texts"), self) self.actFindTexts.setShortcut(QKeySequence(tr("Ctrl+S"))) self.actFindWord = QAction(tr("Fin&d word"), self) self.actFindString = QAction(tr("Find st&ring"), self) self.actFindString.setShortcut(QKeySequence(tr("F3"))) self.actTextRegistry = QAction(tr("Te&xt registry"), self) self.actTextRegistry.setShortcut(QKeySequence(tr("Ctrl+Alt+X"))) self.actImages = QAction(tr("&Images"), self) self.actSounds = QAction(tr("&Sounds"), self) self.actTemplates = QAction(tr("&Templates"), self) self.actCategories = QAction(tr("&Categories"), self) self.actTasklists = QAction(tr("Tas&klists"), self) self.actOtherRegistries = QAction(tr("&Other registries"), self) self.actFont = QAction(tr("&Font"), self) self.actTranslation = QAction(tr("&Translation"), self) self.actPronunciationByWord = QAction(tr("&Pronunciation by word"), self) self.actPronunciationBySound = QAction(tr("Pronunciation by soun&d"), self) self.actComment = QAction(tr("&Comment"), self) self.actVideo = QAction(tr("&Video"), self) self.actScript = QAction(tr("&Script"), self) self.actProgram = QAction(tr("&OLE Object"), self) self.actGotoAncestor = QAction(tr("Go to &ancestor"), self) self.actGotoElement = QAction(tr("Go to &element"), self) self.actGotoElement.setShortcut(QKeySequence(tr("Ctrl+G"))) # Learn actions self.actLearnAllStages = QAction(tr("&All stages"), self) self.actLearnAllStages.setShortcut(QKeySequence(tr("Ctrl+L"))) self.actLearnOutstanding = QAction(tr("1. &Outstanding material"), self) self.actLearnNew = QAction(tr("2. &New material"), self) self.actLearnNew.setShortcut(QKeySequence(tr("Ctrl-F2"))) self.actLearnFinalDrill = QAction(tr("3. &Final drill"), self) self.actLearnFinalDrill.setShortcut(QKeySequence(tr("Ctrl+F2"))) self.connect(self.actLearnFinalDrill, SIGNAL("triggered()"), self.on_actFinalDrill_triggered) self.actReadingList = QAction(tr("&Reading list"), self) self.actReadingList.setShortcut(QKeySequence(tr("Shift+Ctrl+F4"))) self.actPostponeTopics = QAction(tr("&Topics"), self) self.actPostponeItems = QAction(tr("&Items"), self) self.actPostponeAll = QAction(tr("&All"), self) self.actRandomizeRepetitions = QAction(tr("Randomi&ze repetitions"), self) self.actRandomizeRepetitions.setShortcut(QKeySequence("Shift+Ctrl+F11")) self.actRandomLearning = QAction(tr("Ran&dom learning"), self) self.actRandomLearning.setShortcut(QKeySequence("Ctrl+F11")) self.actCutDrills = QAction("&Cut drills", self) # View actions self.actAll = QAction(tr("&All"), self) self.actOutstanding = QAction(tr("&Outstanding"), self) self.actMemorized = QAction(tr("&Memorized"), self) self.actPending = QAction(tr("&Pending"), self) self.actDismissed = QAction(tr("&Dismissed"), self) self.actTopic = QAction(tr("&Topic"), self) self.actItems = QAction(tr("&Items"), self) self.actTasks = QAction(tr("Ta&ks"), self) self.actLastBrowser = QAction(tr("&Last browser"), self) self.actSearchResults = QAction(tr("&Search results"), self) self.actSubset = QAction(tr("S&ubset"), self) self.actFilter = QAction(tr("&Filter..."), self) self.actLeeches = QAction(tr("&Leeches"), self) self.actLeeches.setShortcut(QKeySequence("Shift+F3")) self.actSemiLeeches = QAction(tr("&Semi-leeches"), self) self.actDrill = QAction(tr("&Drill"), self) self.actRange = QAction(tr("&Range"), self) self.actHistory = QAction(tr("&History"), self) self.actBranch = QAction(tr("&Branch"), self) # Tools actions self.actWorkload = QAction(tr("&Workload"), self) self.actWorkload.setShortcut(QKeySequence("Ctrl+W")) self.actPlan = QAction(tr("&Plan"), self) self.actWorkload.setShortcut(QKeySequence("Ctrl+P")) self.actMercy = QAction(tr("&Mercy"), self) self.actMercy.setShortcut(QKeySequence("Ctrl+Y")) self.actTasklist = QAction(tr("&Tasklist"), self) self.actTasklist.setShortcut(QKeySequence("F4")) self.actReadingList = QAction(tr("&Reading list"), self) self.actReadingList.setShortcut(QKeySequence(tr("Ctrl+F4"))) self.actStatistics = QAction(tr("S&tatistics"), self) self.actElementData = QAction(tr("&Element data"), self) self.actAnalysis = QAction(tr("&Analysis"), self) self.actAnalysis.setShortcut(QKeySequence(tr("Ctrl+Alt+I"))) self.actSimulation = QAction(tr("&Simulation"), self) self.actReport = QAction(tr("&Report"), self) self.actRandomizeDrill = QAction(tr("&Drill"), self) self.actRandomizePending = QAction(tr("&Pending"), self) self.actRandomTest = QAction(tr("&Resume test"), self) self.actRandomAll = QAction(tr("&All"), self) self.actRandomAll.setShortcut(QKeySequence(tr("Alt+F11"))) self.actRandomPending = QAction(tr("&Pending"), self) self.actRandomMemorized = QAction(tr("&Memorized"), self) self.actRandomDismissed = QAction(tr("&Dismissed"), self) self.actRandomTopics = QAction(tr("&Topics"), self) self.actRandomItems = QAction(tr("&Items"), self) self.actRandomFilter = QAction(tr("&Filter"), self) self.actRandomLeeches = QAction(tr("&Leeches"), self) self.actRandomSubset = QAction(tr("&Subset"), self) self.actRandomBranch = QAction(tr("&Branch"), self) self.actOptions = QAction(tr("&Options"), self) self.actOptions.setShortcut(tr("Ctrl+Alt+O")) self.connect(self.actOptions, SIGNAL("triggered()"), self.on_actOptions_triggered) # Window actions self.actDock = QAction(tr("&Dock"), self) self.actToolbarRead = QAction(tr("&Read"), self) self.actToolbarCompose = QAction("&Compose", self) self.actToolbarFormat = QAction("&Format", self) self.actToolbarTime = QAction("&Time", self) self.actToolbarActions = QAction("&Actions", self) self.actDockToolbars = QAction("&Dock toolbars", self) self.actStatusBar = QAction(tr("&Status bar"), self) self.actBackground = QAction(tr("&Background"), self) self.actBackground.setShortcut(QKeySequence(tr("Ctrl+Alt+F10"))) self.actHints = QAction(tr("H&ints"), self) self.actSelectCategory = QAction(tr("&Category"), self) self.actSelectCategory.setShortcut(QKeySequence(tr("Ctrl+Alt+C"))) self.actSelectTasklist = QAction(tr("&Tasklist"), self) self.actSelectTasklist.setShortcut(QKeySequence(tr("Ctrl+Alt+T"))) self.actSelectNextWindow = QAction(tr("&Next window"), self) self.actSelectNextWindow.setShortcut(QKeySequence(tr("Ctrl+F6"))) self.actLayoutManager = QAction(tr("&Layout Manager"), self) self.actApplyDefaultLayout = QAction(tr("&Apply default layout"), self) self.actClassLayout = QAction(tr("&Class layout"), self) self.actClassLayout.setShortcut(QKeySequence(tr("F5"))) self.actSaveCustomLayout = QAction(tr("&Save custom layout"), self) self.actSaveAsDefault = QAction(tr("Sa&ve as default"), self) self.actSaveAsDefault.setShortcut(QKeySequence(tr("Shift+Ctrl+F5"))) self.actBackgroundColor = QAction(tr("&Background color"), self) self.actLayoutLastUsed = QAction(tr("Last used"), self) self.actLayoutContents = QAction(tr("Contents"), self) self.actLayoutClassic = QAction(tr("Classic"), self) self.actLayoutBrowser = QAction(tr("Browser"), self) # Help actions self.actWelcome = QAction(tr("&Welcome - ABC"), self) self.actGuide = QAction(tr("&Guide"), self) self.actTroubleshooter = QAction(tr("&Troubleshooter"), self) self.actFaq = QAction(tr("&FAQ"), self) self.actHintsAndTips = QAction(tr("&Hints and tips"), self) self.actContext = QAction(tr("C&ontext F1"), self) self.actContext.setShortcut(QKeySequence("F1")) self.actOnlineHelp = QAction(tr("&On-line help"), self) self.actNews = QAction(tr("&News"), self) self.actWebFaq = QAction(tr("&FAQ"), self) self.actLibrary = QAction(tr("SuperMemo &Library"), self) self.actSupport = QAction(tr("&Support"), self) self.actBugReport = QAction(tr("&Bug report"), self) self.actQuestionnaire = QAction(tr("&Questionnaire"), self) self.actRecommended = QAction(tr("&Recommended SuperMemo"), self) self.actQuestionOfDay = QAction(tr("&Question of the Day"), self) self.actAbout = QAction(tr("&About"), self) self.actAbout.setStatusTip(tr("Show the program and author information")) self.connect(self.actAbout, SIGNAL("triggered()"), self.on_actAbout_triggered) def createMenus(self): self.menuBar().setFont(QFont("Fixed", 8)) # File menu mnuFile = self.menuBar().addMenu(tr("&File")) mnuFile.addAction(self.actNewDeck) mnuFile.addAction(self.actOpenDeck) mnuFile.addAction(self.actCloseDeck) mnuFile.addSeparator() mnuFile.addAction(self.actCopyDeck) mnuFile.addAction(self.actDeleteDeck) mnuFile.addAction(self.actRepairDeck) mnuFile.addAction(self.actMergeDeck) mnuFile.addSeparator() mnuImport = mnuFile.addMenu(tr("Import")) mnuImport.addAction(self.actImportQA) mnuImport.addAction(self.actImportXML) mnuImport.addAction(self.actImportProbe) mnuImport.addAction(self.actImportSuperMemo) mnuExport = mnuFile.addMenu(tr("Export")) mnuExport.addAction(self.actExportQA) mnuExport.addAction(self.actExportXML) mnuExport.addAction(self.actExportProbe) mnuExport.addAction(self.actExportSuperMemo) mnuFile.addSeparator() mnuFile.addAction(self.actProperties) mnuFile.addSeparator() for act in self.actRecentFiles: mnuFile.addAction(act) mnuFile.addSeparator() mnuFile.addAction(self.actExit) # Menu Edit mnuEdit = self.menuBar().addMenu(tr("&Edit")) mnuEdit.addAction(self.actUndo) mnuEdit.addAction(self.actRedo) mnuEdit.addSeparator() mnuEdit.addAction(self.actCut) mnuEdit.addAction(self.actCopy) mnuEdit.addAction(self.actPaste) mnuEdit.addAction(self.actCutAppend) mnuEdit.addAction(self.actCopyAppend) mnuEdit.addSeparator() mnuEdit.addAction(self.actSelectAll) mnuEdit.addAction(self.actSelectLine) mnuEdit.addAction(self.actSelectWord) mnuEdit.addSeparator() mnuEdit.addAction(self.actDelete) mnuEdit.addAction(self.actDeleteLine) mnuEdit.addAction(self.actDeleteToStartLine) mnuEdit.addAction(self.actDeleteToEndLine) # Cards menu mnuCards = self.menuBar().addMenu(tr("&Cards")) mnuCards.addAction(self.actFirstCard) mnuCards.addAction(self.actPreviousCard) mnuCards.addAction(self.actNextCard) mnuCards.addAction(self.actLastCard) mnuCards.addSeparator() mnuCards.addAction(self.actAddCard) mnuCards.addAction(self.actInsertCard) mnuCards.addAction(self.actDeleteCard) mnuCards.addSeparator() mnuCards.addAction(self.actSort) mnuCards.addAction(self.actFilter) mnuCards.addSeparator() mnuCards.addAction(self.actNewItem) mnuCards.addAction(self.actNewArticle) mnuCards.addAction(self.actNewTask) mnuCards.addSeparator() actImportWeb = mnuCards.addAction(tr("Import &web pages")) actImportWeb.setShortcut(QKeySequence("Shift+F8")) mnuCards.addSeparator() actAddToCategory = mnuCards.addAction(tr("Add &to category")) actAddToReading = mnuCards.addAction(tr("Add to &reading list")) actAddToTasklist = mnuCards.addAction(tr("Add to ta&sklist")) mnuCards.addSeparator() actCreateCategory = mnuCards.addAction(tr("Create &category")) actCreateTasklist = mnuCards.addAction(tr("Create &tasklist")) # Search menu mnuSearch = self.menuBar().addMenu(tr("&Search")) mnuSearch.addAction(self.actFindElements) mnuSearch.addAction(self.actFindTexts) mnuSearch.addAction(self.actFindWord) mnuSearch.addAction(self.actFindString) mnuSearch.addSeparator() mnuSearch.addAction(self.actTextRegistry) mnuSearch.addAction(self.actImages) mnuSearch.addAction(self.actSounds) mnuSearch.addSeparator() mnuSearch.addAction(self.actTemplates) mnuSearch.addAction(self.actCategories) mnuSearch.addAction(self.actTasklists) mnuSearchOtherReg = mnuSearch.addMenu(tr("&Other registries")) mnuSearchOtherReg.addAction(self.actFont) mnuSearchOtherReg.addSeparator() mnuSearchOtherReg.addAction(self.actTranslation) mnuSearchOtherReg.addAction(self.actPronunciationByWord) mnuSearchOtherReg.addAction(self.actPronunciationBySound) mnuSearchOtherReg.addAction(self.actComment) mnuSearchOtherReg.addSeparator() mnuSearchOtherReg.addAction(self.actVideo) mnuSearchOtherReg.addAction(self.actScript) mnuSearchOtherReg.addAction(self.actProgram) mnuSearch.addSeparator() mnuSearch.addAction(self.actGotoAncestor) mnuSearch.addAction(self.actGotoElement) # Learn menu mnuLearn = self.menuBar().addMenu(tr("&Learn")) mnuLearn.addAction(self.actLearnAllStages) mnuLearnSelected = mnuLearn.addMenu(tr("&Selected stages")) mnuLearnSelected.addAction(self.actLearnOutstanding) mnuLearnSelected.addAction(self.actLearnNew) mnuLearnSelected.addAction(self.actLearnFinalDrill) mnuLearnSelected.addSeparator() mnuLearnSelected.addAction(self.actReadingList) mnuPostpone = mnuLearn.addMenu(tr("&Postpone")) mnuPostpone.addAction(self.actPostponeTopics) mnuPostpone.addAction(self.actPostponeItems) mnuPostpone.addAction(self.actPostponeAll) mnuLearn.addSeparator() mnuRandom = mnuLearn.addMenu(tr("&Random")) mnuRandom.addAction(self.actRandomizeRepetitions) mnuRandom.addAction(self.actRandomLearning) mnuLearn.addAction(self.actCutDrills) # View menu mnuView = self.menuBar().addMenu(tr("&View")) mnuView.addAction(self.actAll) mnuView.addAction(self.actOutstanding) mnuView.addSeparator() mnuView.addAction(self.actMemorized) mnuView.addAction(self.actPending) mnuView.addAction(self.actDismissed) mnuView.addSeparator() mnuView.addAction(self.actTopic) mnuView.addAction(self.actItems) mnuView.addAction(self.actTasks) mnuView.addSeparator() mnuView.addAction(self.actLastBrowser) mnuView.addAction(self.actSearchResults) mnuView.addAction(self.actSubset) mnuView.addAction(self.actFilter) mnuView.addSeparator() mnuOtherBrowsers = mnuView.addMenu(tr("Other &browsers")) mnuOtherBrowsers.addAction(self.actLeeches) mnuOtherBrowsers.addAction(self.actSemiLeeches) mnuOtherBrowsers.addAction(self.actDrill) mnuOtherBrowsers.addAction(self.actRange) mnuOtherBrowsers.addAction(self.actHistory) mnuOtherBrowsers.addAction(self.actBranch) # Tools mehu mnuTools = self.menuBar().addMenu(tr("T&ools")) mnuTools.addAction(self.actWorkload) mnuTools.addAction(self.actPlan) mnuTools.addAction(self.actMercy) mnuTools.addAction(self.actTasklist) mnuTools.addAction(self.actReadingList) mnuStatistics = mnuTools.addMenu(tr("&Statistics")) mnuStatistics.addAction(self.actStatistics) mnuStatistics.addAction(self.actElementData) mnuStatistics.addAction(self.actAnalysis) mnuStatistics.addAction(self.actSimulation) mnuStatistics.addAction(self.actReport) mnuRandomize = mnuTools.addMenu(tr("&Randomize")) mnuRandomize.addAction(self.actRandomizeDrill) mnuRandomize.addAction(self.actRandomizePending) mnuRandom = mnuTools.addMenu(tr("R&andom test")) mnuRandom.addAction(self.actRandomTest) mnuRandom.addSeparator() mnuRandom.addAction(self.actRandomAll) mnuRandom.addAction(self.actRandomPending) mnuRandom.addAction(self.actRandomMemorized) mnuRandom.addAction(self.actRandomDismissed) mnuRandom.addSeparator() mnuRandom.addAction(self.actRandomTopics) mnuRandom.addAction(self.actRandomItems) mnuRandom.addSeparator() mnuRandom.addAction(self.actRandomFilter) mnuRandom.addAction(self.actRandomLeeches) mnuRandom.addSeparator() mnuRandom.addAction(self.actRandomSubset) mnuRandom.addSeparator() mnuRandom.addAction(self.actRandomBranch) mnuTools.addSeparator() mnuTools.addAction(self.actOptions) # Window menu mnuWindow = self.menuBar().addMenu(tr("&Window")) mnuWindow.addAction(self.actDock) mnuToolbars = mnuWindow.addMenu(tr("&Toolbars")) mnuToolbars.addAction(self.actToolbarRead) mnuToolbars.addAction(self.actToolbarCompose) mnuToolbars.addAction(self.actToolbarFormat) mnuToolbars.addAction(self.actToolbarTime) mnuToolbars.addAction(self.actToolbarActions) mnuToolbars.addSeparator() mnuToolbars.addAction(self.actDockToolbars) mnuWindow.addAction(self.actStatusBar) mnuWindow.addAction(self.actBackground) mnuWindow.addAction(self.actHints) mnuSelect = mnuWindow.addMenu(tr("S&elect")) mnuSelect.addAction(self.actSelectCategory) mnuSelect.addAction(self.actSelectTasklist) mnuSelect.addAction(self.actSelectNextWindow) mnuLayout = mnuWindow.addMenu(tr("&Layout")) mnuLayout.addAction(self.actLayoutManager) mnuLayout.addSeparator() mnuLayout.addAction(self.actApplyDefaultLayout) mnuLayout.addAction(self.actClassLayout) mnuLayout.addSeparator() mnuLayout.addAction(self.actSaveCustomLayout) mnuLayout.addAction(self.actSaveAsDefault) mnuLayout.addSeparator() mnuLayout.addAction(self.actBackgroundColor) mnuWindow.addSeparator() mnuWindow.addAction(self.actLayoutLastUsed) mnuWindow.addAction(self.actLayoutContents) mnuWindow.addAction(self.actLayoutClassic) mnuWindow.addAction(self.actLayoutBrowser) # Help menu mnuHelp = self.menuBar().addMenu(tr("&Help")) mnuHelp.addAction(self.actWelcome) mnuHelp.addAction(self.actGuide) mnuHelp.addAction(self.actTroubleshooter) mnuHelp.addAction(self.actFaq) mnuHelp.addAction(self.actHintsAndTips) mnuHelp.addAction(self.actContext) mnuHelp.addSeparator() mnuHelpWeb = mnuHelp.addMenu(tr("W&eb")) mnuHelpWeb.addAction(self.actOnlineHelp) mnuHelpWeb.addAction(self.actNews) mnuHelpWeb.addAction(self.actWebFaq) mnuHelpEmail = mnuHelp.addMenu(tr("E-&mail")) mnuHelpEmail.addAction(self.actSupport) mnuHelpEmail.addAction(self.actLibrary) mnuHelpEmail.addSeparator() mnuHelpEmail.addAction(self.actBugReport) mnuHelpEmail.addAction(self.actQuestionnaire) mnuHelpEmail.addAction(self.actRecommended) mnuHelp.addSeparator() mnuHelp.addAction(self.actQuestionOfDay) mnuHelp.addSeparator() mnuHelp.addAction(self.actAbout) def createToolbars(self): # File toolbar tbFile = self.addToolBar(tr("File")) tbFile.addAction(self.actAbout) tbFile.addAction(self.actNewDeck) tbFile.addAction(self.actExit) tbFile.addAction(self.actNewItem) tbFile.addAction(self.actNewArticle) tbFile.addAction(self.actNewTask) tbFile.addAction(self.actMemorized) tbFile.addAction(self.actPending) tbFile.addAction(self.actDismissed) tbFile.addAction(self.actTasks) tbFile.addAction(self.actLastBrowser) tbFile.addAction(self.actSubset) tbFile.addAction(self.actLeeches) tbFile.setVisible(False) # Other toolbar tbView = self.addToolBar(tr("View")) tbView.addAction(self.actLeeches) tbView.addAction(self.actSemiLeeches) tbView.addAction(self.actDrill) tbView.addAction(self.actRange) tbView.addAction(self.actHistory) tbView.addAction(self.actBranch) tbView.setVisible(False) def createStatusBar(self): self.statusBar().showMessage(tr("Ready.")) def _refreshAppState(self): """Sets control active or inactive depending on the database state.""" # active/inactive actions # FIXME why are they not disabled/enabled ? self.actAddCard.setEnabled(self._cardModel.isActive()) self.actDeleteCard.setEnabled(self._cardModel.isActive()) self.actPreviousCard.setEnabled(self._cardModel.isActive()) self.actNextCard.setEnabled(self._cardModel.isActive()) # window title if self._cardModel.isActive(): basename = os.path.basename(self._cardModel.filepath()) self.setWindowTitle('Mentor - ' + os.path.splitext(basename)[0]) else: self.setWindowTitle('Mentor') # recent files list for i in range(len(config.GUI_RECENTFILES)): self.actRecentFiles[i].setVisible(True) self.actRecentFiles[i].setText(config.GUI_RECENTFILES[i]) self.actRecentFiles[i].setData(QVariant(config.GUI_RECENTFILES[i])) for i in range(len(config.GUI_RECENTFILES), config.GUI_RECENTFILES_MAX): self.actRecentFiles[i].setVisible(False) def _openDeckFile(self, fname): """Open deck with givem file name.""" fname = str(fname) problem = False # FIXME running setCardModelIndex to empty # to clean all other views # I must redesign the model/view thing self.setCardModelIndex(QModelIndex()) self.cardModel().close() try: self.cardModel().open(fname) self.setCardModelIndex(self.cardModel().index(0, 0)) config.add_most_recent_file(fname) except: config.remove_recent_file(fname) self.setCardModelIndex(QModelIndex()) problem = True finally: self._refreshAppState() if problem: show_info('Problem opening deck file %s.' % fname) def _newDeckFile(self, fname): """Creates a new deck with given file name.""" fname = str(fname) problem = False # FIXME running setCardModelIndex with QModelIndex is HACK to clean # all other views - it must be run before closing cardModel # I must redesign the model/view thing self.setCardModelIndex(QModelIndex()) self.cardModel().close() try: # we want to overwrite if os.path.isfile(fname): os.remove(fname) self.cardModel().open(fname) self.setCardModelIndex(self.cardModel().index(0, 0)) config.add_most_recent_file(fname) except: config.remove_most_recent_file(fname) self.setCardModelIndex(QModelIndex()) problem = True finally: self._refreshAppState() if problem: show_info('Problem creating a new deck file %s.' % fname) def _openRecentFile(self): if config.get_most_recent_file(): self._openDeckFile(config.get_most_recent_file()) self._refreshAppState() def qApp_aboutToQuit(self): if self.isMaximized(): config.GUI_MAXIMIZED = True else: config.GUI_MAXIMIZED = False config.GUI_GEOMETRY = self.geometry() config.save() def on_actNewDeck_triggered(self): fileName = QFileDialog.getSaveFileName(self, \ tr("New deck"), ".", tr("Mentor Card Deck files (*.mcd)")) if fileName: self._newDeckFile(fileName) def on_actOpenDeck_triggered(self): fname = QFileDialog.getOpenFileName(self, \ tr("Open deck"), ".", tr("Mentor Card Deck files (*.mcd)")) if fname: self._openDeckFile(fname) def on_actCloseDeck_triggered(self): self.setCardModelIndex(QModelIndex()) self.cardModel().close() self._refreshAppState() def on_actFirstCard_triggered(self): pass def on_actPreviousCard_triggered(self): """Moves current selection up by 1 row. If no selection is made then selects last item.""" # move row up currentIndex = self.cardModelIndex() prevIndex = self._cardModel.getPreviousIndex(currentIndex) self.setCardModelIndex(prevIndex) def on_actNextCard_triggered(self): """Moves current selection down by 1 row. If no selection is made then selects first item.""" currentIndex = self.cardModelIndex() nextIndex = self.cardModel().getNextIndex(currentIndex) self.setCardModelIndex(nextIndex) def on_actLastCard_triggered(self): pass def on_actAddCard_triggered(self): self.cardModel().addNewCard() # TODO what if it's not added at the end? newIndex = self.cardModel().index(self.cardModel().rowCount() - 1, 0) # go to newly added record self.setCardModelIndex(newIndex) def on_actInsertCard_triggered(self): pass def on_actDeleteCard_triggered(self): currentIndex = self.cardModelIndex() if currentIndex.isValid(): # try to find currently selected row # and go to the same row # if rows are missing then go to last currentRow = currentIndex.row() self.cardModel().deleteCard(currentIndex) # go to new index newIndex = self.cardModel().index(min(currentRow, self.cardModel().rowCount() - 1), 0) self.setCardModelIndex(newIndex) def on_actAbout_triggered(self): show_info(tr("MENTOR version %s\nA learning tool\n\nDistributed under license: %s.\n\nAuthors: \n%s" \ % (__version__, __license__, str(__author__))), self) def on_actCopyDeck_triggered(self): pass def on_actDeleteDeck_triggered(self): pass def on_actRepairDeck_triggered(self): pass def on_actMergeDeck_triggered(self): pass def on_actImportQA_triggered(self): # TODO must this have disabled if not database is open # TODO Option if want to clear existing or append fname = QFileDialog.getOpenFileName(self, \ tr("Import Q&A file"), ".", tr("Q&A files (*.*)")) if fname: self.cardModel().importQAFile(str(fname)) self.setCardModelIndex(self.cardModel().index(0, 0)) self._refreshAppState() def on_actImportXML_triggered(self): pass def on_actImportProbe_triggered(self): pass def on_actImportProbe_triggered(self): pass def on_actExportQA_triggered(self): pass def on_actExportXML_triggered(self): pass def on_actExportProbe_triggered(self): pass def on_actExportProbe_triggered(self): pass def on_actExportProbe_triggered(self): pass def on_actOptions_triggered(self): pass def on_actRecentFiles_triggered(self): self._openDeckFile(self.sender().text()) def on_actFinalDrill_triggered(self): dialog = DrillWindow(self) # FIXME # load cards from model # should it work that way? # should model be more general (and have other operations?) or be # dedicated to browsing list only ? # maybe all operations should be done on the database level # and models only for browsing lists cards = [] for row in range(self.cardModel().rowCount()): idx = self.cardModel().index(row, 0) card = self.cardModel().data(idx, Qt.UserRole) cards.append(card) dialog.loadCards(cards) dialog.exec_() def gridView_currentChanged(self, current, previous): self.setCardModelIndex(current) def gridView_activated(self, current): self.setCardModelIndex(current) def gridView_cardModelIndexChanged(self, current, previous): selection = self.gridView.selectionModel() selectedIndex = selection.selectedIndexes() if len(selectedIndex) > 0: selectedIndex = selectedIndex[0] else: selectedIndex = QModelIndex() # if is changed then update list view and card model if current != selectedIndex: selection.setCurrentIndex(current, QItemSelectionModel.SelectCurrent)