From: Urban Wallasch Date: Mon, 14 Jun 2021 11:20:57 +0000 (+0200) Subject: * Added search options to GUI, partially implemented. X-Git-Tag: v0.1.0~147 X-Git-Url: https://git.packet-gain.de/?a=commitdiff_plain;h=cbadf5febcd5e61e27412f09267ede468571314b;p=jiten-pai.git * Added search options to GUI, partially implemented. * GUI improvements, refactoring. --- diff --git a/jiten-pai.py b/jiten-pai.py index 6fde4e9..1772c36 100755 --- a/jiten-pai.py +++ b/jiten-pai.py @@ -26,6 +26,7 @@ import io import os import re import argparse +import unicodedata from configparser import RawConfigParser as ConfigParser from PyQt5.QtCore import * from PyQt5.QtWidgets import * @@ -38,6 +39,12 @@ from PyQt5.QtGui import * def die(rc=0): sys.exit(rc) +def contains_cjk(s): + for c in s: + if "Lo" == unicodedata.category(c): + return True + return False + ############################################################ # configuration @@ -59,6 +66,9 @@ cfg = { class jpMainWindow(QMainWindow): def __init__(self, *args, title='', **kwargs): super().__init__(*args, **kwargs) + self.init_ui(title) + + def init_ui(self, title=''): #jpIcon() self.setWindowTitle(title) #self.setWindowIcon(jpIcon.jitenpai) @@ -74,10 +84,10 @@ class jpMainWindow(QMainWindow): edit_menu = menubar.addMenu('&Edit') copy_action = QAction('&Copy', self) copy_action.setShortcut('Ctrl+C') - copy_action.triggered.connect(lambda: self.clipboard.setText(self.result_pane.textCursor().selectedText())) + copy_action.triggered.connect(self.kbd_copy) paste_action = QAction('&Paste', self) paste_action.setShortcut('Ctrl+V') - paste_action.triggered.connect(lambda: self.search_box.lineEdit().setText(self.clipboard.text())) + paste_action.triggered.connect(self.kbd_paste) pref_action = QAction('Prefere&nces', self) # TODO: preferences dialog #pref_action.triggered.connect() @@ -89,8 +99,54 @@ class jpMainWindow(QMainWindow): help_menu = menubar.addMenu('&Help') about_action = QAction('&About', self) help_menu.addAction(about_action) + # options + japopt_group = QGroupBox('Japanese Search Options') + self.japopt_exact = QRadioButton('Exact Matches') + self.japopt_exact.setChecked(True) + self.japopt_start = QRadioButton('Start With Expression') + self.japopt_end = QRadioButton('End With Expression') + self.japopt_any = QRadioButton('Any Matches') + japopt_layout = QVBoxLayout() + japopt_layout.addWidget(self.japopt_exact) + japopt_layout.addWidget(self.japopt_start) + japopt_layout.addWidget(self.japopt_end) + japopt_layout.addWidget(self.japopt_any) + japopt_layout.addStretch() + japopt_group.setLayout(japopt_layout) + engopt_group = QGroupBox('English Search Options') + self.engopt_expr = QRadioButton('Whole Expressions') + self.engopt_word = QRadioButton('Whole Words') + self.engopt_any = QRadioButton('Any Matches') + self.engopt_any.setChecked(True) + engopt_layout = QVBoxLayout() + engopt_layout.addWidget(self.engopt_expr) + engopt_layout.addWidget(self.engopt_word) + engopt_layout.addWidget(self.engopt_any) + engopt_layout.addStretch() + engopt_group.setLayout(engopt_layout) + genopt_group = QGroupBox('General Options') + # TODO: add remaining general options + self.genopt_dolimit = QCheckBox('Limit Results:') + self.genopt_dolimit.setTristate(False) + self.genopt_dolimit.setChecked(True) + self.genopt_limit = QSpinBox() + self.genopt_limit.setMinimum(1) + self.genopt_limit.setMaximum(1000) + self.genopt_limit.setValue(cfg['max_res']) + self.genopt_dolimit.toggled.connect(self.genopt_limit.setEnabled) + genopt_limit_layout = QHBoxLayout() + genopt_limit_layout.addWidget(self.genopt_dolimit) + genopt_limit_layout.addWidget(self.genopt_limit) + genopt_layout = QVBoxLayout() + genopt_layout.addLayout(genopt_limit_layout) + genopt_layout.addStretch() + genopt_group.setLayout(genopt_layout) + opt_layout = QHBoxLayout() + opt_layout.addWidget(japopt_group) + opt_layout.addWidget(engopt_group) + opt_layout.addWidget(genopt_group) # search area - search_group = QGroupBox('Enter expression:') + search_group = QGroupBox('Enter expression') self.search_box = QComboBox() self.search_box.setEditable(True) self.search_box.setMinimumWidth(400); @@ -102,13 +158,13 @@ class jpMainWindow(QMainWindow): clear_button = QPushButton('Clear') clear_button.clicked.connect(lambda: self.search_box.lineEdit().setText("")) search_layout = QHBoxLayout() - search_layout.addWidget(self.search_box) - search_layout.addWidget(search_button) - search_layout.addWidget(clear_button) + search_layout.addWidget(self.search_box, 100) + search_layout.addWidget(search_button, 5) + search_layout.addWidget(clear_button, 1) search_group.setLayout(search_layout) # result area - result_group = QGroupBox('Search results:') - self.matches_label = QLabel('Matches found:') + result_group = QGroupBox('Search results') + self.matches_label = QLabel(' ') self.result_pane = QTextEdit() self.result_pane.setReadOnly(True) self.result_pane.setText('') @@ -120,16 +176,60 @@ class jpMainWindow(QMainWindow): main_frame = QWidget() main_layout = QVBoxLayout(main_frame) main_layout.addWidget(menubar) - main_layout.addWidget(search_group) - main_layout.addWidget(result_group) + main_layout.addLayout(opt_layout, 1) + main_layout.addWidget(search_group, 20) + main_layout.addWidget(result_group, 100) self.setCentralWidget(main_frame) + self.search_box.setFocus() def search(self): term = self.search_box.lineEdit().text().strip() + self.search_box.lineEdit().setText(term) if len(term) < 1: return - result = dict_lookup(cfg['dict'], term, cfg['max_res']) - # result formatting + # apply search options + if contains_cjk(term): + print('apply japopt') + if self.japopt_exact.isChecked(): + if term[0] != '^': + term = '^' + term + if term[-1] != '$': + term = term + '$' + elif self.japopt_start.isChecked(): + if term[0] != '^': + term = '^' + term + if term[-1] == '$': + term = term[:-1] + elif self.japopt_end.isChecked(): + if term[0] == '^': + term = term[1:] + if term[-1] != '$': + term = term + '$' + elif self.japopt_any.isChecked(): + if term[0] == '^': + term = term[1:] + if term[-1] == '$': + term = term[:-1] + else: + print('apply engopt') + if self.engopt_expr.isChecked(): + term = '[^a-zA-Z] ' + term + if term[-1] != ';': + term = term + ';' + if self.engopt_word.isChecked(): + term = '[^a-zA-Z]' + term + '[^a-zA-Z]' + if self.engopt_any.isChecked(): + if term[-1] == ';': + term = term[:-1] + # result limiting + max_res = self.genopt_limit.value() if self.genopt_limit.isEnabled() else 0 + # perform lookup + result = dict_lookup(cfg['dict'], term, max_res) + if len(result) < 1: + self.matches_label.setText("No match found!") + self.result_pane.setHtml('') + return + # format result re_term = re.compile(term) nfmt = '
' % (cfg['font'], cfg['font_sz']) lfmt = '' % (cfg['lfont'], cfg['lfont_sz']) @@ -149,6 +249,13 @@ class jpMainWindow(QMainWindow): self.result_pane.setHtml(''.join(html)) self.matches_label.setText("Matches found: %d" % len(result)) + def kbd_copy(self): + self.clipboard.setText(self.result_pane.textCursor().selectedText()) + + def kbd_paste(self): + self.search_box.lineEdit().setText(self.clipboard.text()) + self.search_box.setFocus() + ############################################################ # dictionary lookup @@ -170,7 +277,7 @@ def dict_lookup(dict_fname, term, max_res = 0): p2 = p1[1].split(']', 1) kanji = p1[0].strip() kana = p2[0].strip() - trans = p2[1].strip('/ \t\r\n') + trans = ' ' + p2[1].lstrip('/ ').rstrip(' \t\r\n').replace('/', '; ') except: continue # for now promiscuously try to match anything anywhere