def __init__(self): self.edictDictionary = edict.EdictDictionary(loadToMemory = True, loadEnamdict = True) self.cedictDictionary = cedict.CedictDictionary() self.kengdicDictionary = kengdic.KengdicDictionary() self.dict = self.edictDictionary QWidget.__init__(self) self.setWindowTitle("Kanji lookup") self.resize(500, 600) self.setWindowIcon(QIcon("icon.png")) self.historyWindow = HistoryWindow(self) self.txtRadicalsInput = QLineEdit(self) self.txtRadicalsInput.textChanged.connect(self.ontxtRadicalsTextChanged) self.lstOutput = QListWidget(self) self.lstOutput.setFlow(QListView.LeftToRight) self.lstOutput.setWrapping(True) self.lstOutput.itemActivated.connect(self.onlstOutputItemActivated) self.lstOutput.setStyleSheet("QListWidget {font-size: 70px}") self.txtOutputAggregation = QTextEdit(self) self.txtOutputAggregation.setStyleSheet("font-size: 50px") self.txtOutputAggregation.setMaximumHeight(120) self.txtOutputAggregation.textChanged.connect(self.ontxtOutputAggregationTextChanged) self.txtOutputAggregation.selectionChanged.connect(self.handleSelectionChangesOrCursorMovements) self.txtOutputAggregation.cursorPositionChanged.connect(self.handleSelectionChangesOrCursorMovements) self.txtOutputAggregation.installEventFilter(self) self.btnSaveWord = QPushButton("Save word", self) self.btnSaveWord.clicked.connect(self.onbtnSaveWordClicked) self.btnShowRadicals = QPushButton("Show radicals...", self) self.btnShowRadicals.clicked.connect(self.onbtnShowRadicalsClicked) self.btnShowHistory = QPushButton("History...", self) self.btnShowHistory.clicked.connect(self.onbtnShowHistoryClicked) self.btnSearchWord = QPushButton("Search...", self) self.btnSearchWord.clicked.connect(self.onbtnSearchWordClicked) self.lblSplittedWordsList = QLabel(self) self.lblSplittedWordsList.setStyleSheet("font-size: 20px") self.lblSplittedWordsList.linkActivated.connect(self.onlblSplittedWordsListlinkActivated) self.txtTranslations = QTextBrowser(self) self.txtTranslations.setReadOnly(True) self.txtTranslations.setOpenLinks(False) self.txtTranslations.setStyleSheet("font-size: 25px") #stuff for making HTML a bit faster (http://stackoverflow.com/questions/3120258/qtextedit-inserthtml-is-very-slow) self.txtTranslations.setAcceptRichText(False) self.txtTranslations.setContextMenuPolicy(Qt.NoContextMenu) self.txtTranslations.setUndoRedoEnabled(False) self.txtTranslations.anchorClicked.connect(self.onTxtTranslationsAnchorClicked) self.lblStrokeCount = QLabel("Stroke count:") self.spnStrokeCount = QSpinBox(self) self.spnStrokeCount.valueChanged.connect(self.onspnStrokeCountValueChanged) self.cmbLanguage = QComboBox(self) self.cmbLanguage.addItem("Japanese", "JAPANESE") self.cmbLanguage.addItem("Chinese", "CHINESE") self.cmbLanguage.addItem("Korean", "KOREAN") self.cmbLanguage.currentIndexChanged.connect(self.onLanguageChanged) self.chkAlwaysOnTop = QCheckBox("AOT", self) self.chkAlwaysOnTop.stateChanged.connect(self.onchkAlwaysOnTopStateChanged) self.chkAlwaysOnTop.setCheckState(Qt.Unchecked) self.chkListenToClipboard = QCheckBox("Listen to clipboard", self) self.chkListenToClipboard.setCheckState(Qt.Unchecked) #Layout self.mainLayout = QVBoxLayout(self) self.mainLayout.addWidget(self.txtRadicalsInput) self.mainLayout.addWidget(self.lstOutput) self.bottomLayout = QHBoxLayout() self.bottomLayout.addWidget(self.txtOutputAggregation) self.buttonsLayout = QVBoxLayout() self.buttonsLayout.addWidget(self.btnSaveWord) self.buttonsLayout.addWidget(self.btnShowRadicals) self.buttonsLayout.addWidget(self.btnShowHistory) self.buttonsLayout.addWidget(self.btnSearchWord) self.bottomLayout.addLayout(self.buttonsLayout) self.mainLayout.addLayout(self.bottomLayout) self.mainLayout.addWidget(self.lblSplittedWordsList) self.mainLayout.addWidget(self.txtTranslations) self.strokeCountLayout = QHBoxLayout() self.strokeCountLayout.addWidget(self.lblStrokeCount) self.strokeCountLayout.addWidget(self.spnStrokeCount) self.strokeCountLayout.addWidget(self.cmbLanguage) self.strokeCountLayout.addWidget(self.chkAlwaysOnTop) self.strokeCountLayout.addWidget(self.chkListenToClipboard) self.mainLayout.addLayout(self.strokeCountLayout) self.lblStrokeCount.adjustSize() QApplication.clipboard().dataChanged.connect(self.clipboardChanged)
class MainWindow(QWidget): def eventFilter(self, object, event): if object == self.txtOutputAggregation: if (event.type() == QEvent.KeyPress): if event.key() == Qt.Key_Up: self.cmbLanguage.setCurrentIndex((self.cmbLanguage.currentIndex() + 1) % self.cmbLanguage.count() ) if event.key() == Qt.Key_Down: self.cmbLanguage.setCurrentIndex((self.cmbLanguage.currentIndex() - 1) % self.cmbLanguage.count() ) return False # if I got here, it means it's an event I'll just let Qt handle in its default way return QObject.eventFilter(self, object, event) def __init__(self): self.edictDictionary = edict.EdictDictionary(loadToMemory = True, loadEnamdict = True) self.cedictDictionary = cedict.CedictDictionary() self.kengdicDictionary = kengdic.KengdicDictionary() self.dict = self.edictDictionary QWidget.__init__(self) self.setWindowTitle("Kanji lookup") self.resize(500, 600) self.setWindowIcon(QIcon("icon.png")) self.historyWindow = HistoryWindow(self) self.txtRadicalsInput = QLineEdit(self) self.txtRadicalsInput.textChanged.connect(self.ontxtRadicalsTextChanged) self.lstOutput = QListWidget(self) self.lstOutput.setFlow(QListView.LeftToRight) self.lstOutput.setWrapping(True) self.lstOutput.itemActivated.connect(self.onlstOutputItemActivated) self.lstOutput.setStyleSheet("QListWidget {font-size: 70px}") self.txtOutputAggregation = QTextEdit(self) self.txtOutputAggregation.setStyleSheet("font-size: 50px") self.txtOutputAggregation.setMaximumHeight(120) self.txtOutputAggregation.textChanged.connect(self.ontxtOutputAggregationTextChanged) self.txtOutputAggregation.selectionChanged.connect(self.handleSelectionChangesOrCursorMovements) self.txtOutputAggregation.cursorPositionChanged.connect(self.handleSelectionChangesOrCursorMovements) self.txtOutputAggregation.installEventFilter(self) self.btnSaveWord = QPushButton("Save word", self) self.btnSaveWord.clicked.connect(self.onbtnSaveWordClicked) self.btnShowRadicals = QPushButton("Show radicals...", self) self.btnShowRadicals.clicked.connect(self.onbtnShowRadicalsClicked) self.btnShowHistory = QPushButton("History...", self) self.btnShowHistory.clicked.connect(self.onbtnShowHistoryClicked) self.btnSearchWord = QPushButton("Search...", self) self.btnSearchWord.clicked.connect(self.onbtnSearchWordClicked) self.lblSplittedWordsList = QLabel(self) self.lblSplittedWordsList.setStyleSheet("font-size: 20px") self.lblSplittedWordsList.linkActivated.connect(self.onlblSplittedWordsListlinkActivated) self.txtTranslations = QTextBrowser(self) self.txtTranslations.setReadOnly(True) self.txtTranslations.setOpenLinks(False) self.txtTranslations.setStyleSheet("font-size: 25px") #stuff for making HTML a bit faster (http://stackoverflow.com/questions/3120258/qtextedit-inserthtml-is-very-slow) self.txtTranslations.setAcceptRichText(False) self.txtTranslations.setContextMenuPolicy(Qt.NoContextMenu) self.txtTranslations.setUndoRedoEnabled(False) self.txtTranslations.anchorClicked.connect(self.onTxtTranslationsAnchorClicked) self.lblStrokeCount = QLabel("Stroke count:") self.spnStrokeCount = QSpinBox(self) self.spnStrokeCount.valueChanged.connect(self.onspnStrokeCountValueChanged) self.cmbLanguage = QComboBox(self) self.cmbLanguage.addItem("Japanese", "JAPANESE") self.cmbLanguage.addItem("Chinese", "CHINESE") self.cmbLanguage.addItem("Korean", "KOREAN") self.cmbLanguage.currentIndexChanged.connect(self.onLanguageChanged) self.chkAlwaysOnTop = QCheckBox("AOT", self) self.chkAlwaysOnTop.stateChanged.connect(self.onchkAlwaysOnTopStateChanged) self.chkAlwaysOnTop.setCheckState(Qt.Unchecked) self.chkListenToClipboard = QCheckBox("Listen to clipboard", self) self.chkListenToClipboard.setCheckState(Qt.Unchecked) #Layout self.mainLayout = QVBoxLayout(self) self.mainLayout.addWidget(self.txtRadicalsInput) self.mainLayout.addWidget(self.lstOutput) self.bottomLayout = QHBoxLayout() self.bottomLayout.addWidget(self.txtOutputAggregation) self.buttonsLayout = QVBoxLayout() self.buttonsLayout.addWidget(self.btnSaveWord) self.buttonsLayout.addWidget(self.btnShowRadicals) self.buttonsLayout.addWidget(self.btnShowHistory) self.buttonsLayout.addWidget(self.btnSearchWord) self.bottomLayout.addLayout(self.buttonsLayout) self.mainLayout.addLayout(self.bottomLayout) self.mainLayout.addWidget(self.lblSplittedWordsList) self.mainLayout.addWidget(self.txtTranslations) self.strokeCountLayout = QHBoxLayout() self.strokeCountLayout.addWidget(self.lblStrokeCount) self.strokeCountLayout.addWidget(self.spnStrokeCount) self.strokeCountLayout.addWidget(self.cmbLanguage) self.strokeCountLayout.addWidget(self.chkAlwaysOnTop) self.strokeCountLayout.addWidget(self.chkListenToClipboard) self.mainLayout.addLayout(self.strokeCountLayout) self.lblStrokeCount.adjustSize() QApplication.clipboard().dataChanged.connect(self.clipboardChanged) # pid = ctypes.windll.kernel32.GetCurrentProcessId() # ctypes.windll.user32.AllowSetForegroundWindow(pid) # t = hotkeythread.HotkeyThread() # t.registerHotkey(win32con.MOD_CONTROL | win32con.MOD_ALT, ord("K"), self.focusWindow, self) # t.start() def clipboardChanged(self): print("clipboardChanged()") if self.chkListenToClipboard.checkState() == Qt.Checked: self.txtOutputAggregation.setPlainText(QApplication.clipboard().text()) def focusWindow(self): self.showNormal() self.activateWindow() self.raise_() self.txtOutputAggregation.setFocus() def resizeEvent(self, event): self.populateList(False) def populateList(self, fullList): kanjis = lookup.getKanjiFromRadicals(self.txtRadicalsInput.text().lower().replace("、", ",").split(",")) # Sorting first by ord() value and then by stroke count, I ensure that kanji # with the same stoke count will always be ordered in a consistent way (by ord() value) kanjis = sorted(kanjis, key=ord) kanjis = sorted(kanjis, key=kanjidic.getStrokeCount) if self.spnStrokeCount.value() > 0: kanjis = list(filter(lambda x: kanjidic.getStrokeCount(x) == self.spnStrokeCount.value(), kanjis)) self.lstOutput.clear() if fullList: self.lstOutput.addItems(kanjis) else: self.lstOutput.addItems(kanjis[:100]) if len(kanjis) > 100: self.lstOutput.addItem("...") if len(kanjis) > 0: self.lstOutput.item(0).setSelected(True) if not fullList: # it's true when i click the "..." item, i want the scrollbar stay as it is self.lstOutput.scrollToTop() def ontxtRadicalsTextChanged(self): self.populateList(False) def onlstOutputItemActivated(self, item): if item.text() == "...": self.populateList(True) self.lstOutput.item(100).setSelected(True) else: if (QApplication.keyboardModifiers() & Qt.ShiftModifier) == Qt.ShiftModifier: self.txtOutputAggregation.setPlainText("") self.txtOutputAggregation.insert(item.text()) def onbtnShowRadicalsClicked(self): text = "" for k in self.txtOutputAggregation.toPlainText(): radicals = lookup.getRadicalsFromKanji(k) if len(radicals) == 0: continue if text != "": text += "<br/>" text += k + ":<br/>" for r in radicals: text += r + ": " + lookup.getRadicalName(r) + "<br/>" popup = Popup(self, text) # print("popup.show()") popup.show() def showTranslations(self, word): translations = self.dict.getTranslation(word) if translations is None: self.txtTranslations.setPlainText("-- not found --") else: # print(str(time.clock()), "self.txtTranslations.setHtml()") if len(translations) > 50: translations = translations[0:50] + ["..."] self.txtTranslations.setHtml("<br/>--------<br/>".join(translations).replace("\n", "<br/>")) # print(str(time.clock()), "self.txtTranslations.setHtml() - fine") def onbtnShowHistoryClicked(self): self.historyWindow.show() def onspnStrokeCountValueChanged(self, value): self.populateList(False) def onbtnSearchWordClicked(self): if self.txtOutputAggregation.toPlainText().strip() == "": return self.setCursor(Qt.WaitCursor) text = "" if self.txtOutputAggregation.textCursor().hasSelection(): text = self.txtOutputAggregation.textCursor().selectedText() else: text = self.txtOutputAggregation.toPlainText() popup = ListPopup(self) # print("popup.show(self.dict.findWordsFromFragment(text))") popup.show(self.dict.findWordsFromFragment(text)) self.unsetCursor() def onbtnSaveWordClicked(self): if self.txtOutputAggregation.textCursor().hasSelection(): text = self.txtOutputAggregation.textCursor().selectedText() else: text = self.txtOutputAggregation.toPlainText() f = open("savedwords.txt", "a", encoding="utf8") f.write(text + "\n") f.close() QMessageBox.information(self, "saved", "saved") def ontxtOutputAggregationTextChanged(self): self.historyWindow.addEntry(self.txtOutputAggregation.toPlainText()) input = self.txtOutputAggregation.toPlainText() if input == "": self.txtTranslations.setPlainText("") self.lblSplittedWordsList.setText("") return # print(str(time.clock()), "words = self.dict.splitSentence(input)") words = self.dict.splitSentence(input) # print(str(time.clock()), "text = ''") text = "" for w in words: text += "<a href='word'>word</a> ".replace("word", w) # print(str(time.clock()), "self.lblSplittedWordsList.setText(text)") self.lblSplittedWordsList.setText(text) def handleSelectionChangesOrCursorMovements(self): # print(str(time.clock()), "self.handleSelectionChangesOrCursorMovements() - inizio") if self.txtOutputAggregation.textCursor().hasSelection(): self.showTranslations(self.txtOutputAggregation.textCursor().selectedText()) else: # This is utter rubbish... Relies on the fact that splitSentence() returns # all the extra whitespace between words, and weird things happen when the cursor's # between two words # merda = len(re.sub("\s*?", "", self.txtOutputAggregation.text()[:newPosition])) i = 0 for w in self.dict.splitSentence(self.txtOutputAggregation.toPlainText()): if len(w) + i >= self.txtOutputAggregation.textCursor().position(): self.showTranslations(w) return else: i += len(w) def onlblSplittedWordsListlinkActivated(self, link): self.showTranslations(link) def onLanguageChanged(self, checked): self.setCursor(Qt.WaitCursor) currLanguage = self.cmbLanguage.itemData(self.cmbLanguage.currentIndex()) if currLanguage == "CHINESE": self.dict = self.cedictDictionary elif currLanguage == "JAPANESE": self.dict = self.edictDictionary elif currLanguage == "KOREAN": self.dict = self.kengdicDictionary self.ontxtOutputAggregationTextChanged() self.handleSelectionChangesOrCursorMovements() self.unsetCursor() def onTxtTranslationsAnchorClicked(self, url): self.playMp3("datasets/chineseSounds/" + url.path() + ".mp3.wav") def playMp3(self, path): wave_obj = sa.WaveObject.from_wave_file(path) play_obj = wave_obj.play() # play_obj.wait_done() def onchkAlwaysOnTopStateChanged(self, state): show = self.isVisible() #originalPosition = self.mapToGlobal(self.pos()) if state == Qt.Checked: self.setWindowFlags(Qt.WindowStaysOnTopHint) else: flags = self.windowFlags() flags = flags & ~Qt.WindowStaysOnTopHint self.setWindowFlags(flags) if show: self.show()