mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
UI to manage lookup sources
This commit is contained in:
parent
31118409ae
commit
2548babf59
@ -6,10 +6,12 @@ from __future__ import absolute_import, division, print_function, unicode_litera
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
import textwrap
|
||||||
|
|
||||||
from PyQt5.Qt import (
|
from PyQt5.Qt import (
|
||||||
QApplication, QComboBox, QDialog, QHBoxLayout, QIcon, QLabel, QPushButton, Qt,
|
QApplication, QComboBox, QDialog, QFormLayout, QHBoxLayout, QIcon, QLabel,
|
||||||
QTimer, QUrl, QVBoxLayout, QWidget
|
QLineEdit, QListWidget, QListWidgetItem, QPushButton, Qt, QTimer, QUrl,
|
||||||
|
QVBoxLayout, QWidget
|
||||||
)
|
)
|
||||||
from PyQt5.QtWebEngineWidgets import (
|
from PyQt5.QtWebEngineWidgets import (
|
||||||
QWebEnginePage, QWebEngineProfile, QWebEngineView
|
QWebEnginePage, QWebEngineProfile, QWebEngineView
|
||||||
@ -17,6 +19,7 @@ from PyQt5.QtWebEngineWidgets import (
|
|||||||
|
|
||||||
from calibre import prints, random_user_agent
|
from calibre import prints, random_user_agent
|
||||||
from calibre.constants import cache_dir
|
from calibre.constants import cache_dir
|
||||||
|
from calibre.gui2 import error_dialog
|
||||||
from calibre.gui2.viewer.web_view import vprefs
|
from calibre.gui2.viewer.web_view import vprefs
|
||||||
from calibre.gui2.webengine import create_script, insert_scripts, secure_webengine
|
from calibre.gui2.webengine import create_script, insert_scripts, secure_webengine
|
||||||
from calibre.gui2.widgets2 import Dialog
|
from calibre.gui2.widgets2 import Dialog
|
||||||
@ -43,13 +46,144 @@ vprefs.defaults['lookup_locations'] = [
|
|||||||
vprefs.defaults['lookup_location'] = 'Google dictionary'
|
vprefs.defaults['lookup_location'] = 'Google dictionary'
|
||||||
|
|
||||||
|
|
||||||
|
class SourceEditor(Dialog):
|
||||||
|
|
||||||
|
def __init__(self, parent, source_to_edit=None):
|
||||||
|
self.all_names = {x['name'] for x in parent.all_entries}
|
||||||
|
self.initial_name = self.initial_url = None
|
||||||
|
self.langs = []
|
||||||
|
if source_to_edit is not None:
|
||||||
|
self.langs = source_to_edit['langs']
|
||||||
|
self.initial_name = source_to_edit['name']
|
||||||
|
self.initial_url = source_to_edit['url']
|
||||||
|
Dialog.__init__(self, _('Edit lookup source'), 'viewer-edit-lookup-location', parent=parent)
|
||||||
|
|
||||||
|
def setup_ui(self):
|
||||||
|
self.l = l = QFormLayout(self)
|
||||||
|
self.name_edit = n = QLineEdit(self)
|
||||||
|
n.setPlaceholderText(_('The name of the source'))
|
||||||
|
n.setMinimumWidth(450)
|
||||||
|
l.addRow(_('&Name:'), n)
|
||||||
|
if self.initial_name:
|
||||||
|
n.setText(self.initial_name)
|
||||||
|
n.setReadOnly(True)
|
||||||
|
self.url_edit = u = QLineEdit(self)
|
||||||
|
u.setPlaceholderText(_('The URL template of the source'))
|
||||||
|
u.setMinimumWidth(n.minimumWidth())
|
||||||
|
u.setToolTip(textwrap.fill(_(
|
||||||
|
'The URL template must starts with https:// and have {word} in it which will be replaced by the actual query')))
|
||||||
|
l.addRow(_('&URL:'), u)
|
||||||
|
if self.initial_url:
|
||||||
|
u.setText(self.initial_url)
|
||||||
|
l.addRow(self.bb)
|
||||||
|
if self.initial_name:
|
||||||
|
u.setFocus(Qt.OtherFocusReason)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def source_name(self):
|
||||||
|
return self.name_edit.text().strip()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def url(self):
|
||||||
|
return self.url_edit.text().strip()
|
||||||
|
|
||||||
|
def accept(self):
|
||||||
|
q = self.source_name
|
||||||
|
if not q:
|
||||||
|
return error_dialog(self, _('No name'), _(
|
||||||
|
'You must specify a name'), show=True)
|
||||||
|
if not self.initial_name and q in self.all_names:
|
||||||
|
return error_dialog(self, _('Name already exists'), _(
|
||||||
|
'A look up source with the name {} already exists').format(q), show=True)
|
||||||
|
if not self.url:
|
||||||
|
return error_dialog(self, _('No name'), _(
|
||||||
|
'You must specify a URL'), show=True)
|
||||||
|
if not self.url.startswith('http://') and not self.url.startswith('https://'):
|
||||||
|
return error_dialog(self, _('Invalid URL'), _(
|
||||||
|
'The URL must start with https://'), show=True)
|
||||||
|
if '{word}' not in self.url:
|
||||||
|
return error_dialog(self, _('Invalid URL'), _(
|
||||||
|
'The URL must contain the placeholder {word}'), show=True)
|
||||||
|
return Dialog.accept(self)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def entry(self):
|
||||||
|
return {'name': self.source_name, 'url': self.url, 'langs': self.langs}
|
||||||
|
|
||||||
|
|
||||||
class SourcesEditor(Dialog):
|
class SourcesEditor(Dialog):
|
||||||
|
|
||||||
def __init__(self, parent):
|
def __init__(self, parent):
|
||||||
Dialog.__init__(self, _('Edit lookup sources'), 'viewer-edit-lookup-sources', parent=parent)
|
Dialog.__init__(self, _('Edit lookup sources'), 'viewer-edit-lookup-locations', parent=parent)
|
||||||
|
|
||||||
def setup_ui(self):
|
def setup_ui(self):
|
||||||
pass
|
self.l = l = QVBoxLayout(self)
|
||||||
|
self.la = la = QLabel(_('Double-click to edit an entry'))
|
||||||
|
la.setWordWrap(True)
|
||||||
|
l.addWidget(la)
|
||||||
|
self.entries = e = QListWidget(self)
|
||||||
|
e.setDragEnabled(True)
|
||||||
|
e.itemDoubleClicked.connect(self.edit_source)
|
||||||
|
e.viewport().setAcceptDrops(True)
|
||||||
|
e.setDropIndicatorShown(True)
|
||||||
|
e.setDragDropMode(e.InternalMove)
|
||||||
|
e.setDefaultDropAction(Qt.MoveAction)
|
||||||
|
l.addWidget(e)
|
||||||
|
l.addWidget(self.bb)
|
||||||
|
self.build_entries(vprefs['lookup_locations'])
|
||||||
|
|
||||||
|
self.add_button = b = self.bb.addButton(_('Add'), self.bb.ActionRole)
|
||||||
|
b.setIcon(QIcon(I('plus.png')))
|
||||||
|
b.clicked.connect(self.add_source)
|
||||||
|
self.remove_button = b = self.bb.addButton(_('Remove'), self.bb.ActionRole)
|
||||||
|
b.setIcon(QIcon(I('minus.png')))
|
||||||
|
b.clicked.connect(self.remove_source)
|
||||||
|
self.restore_defaults_button = b = self.bb.addButton(_('Restore defaults'), self.bb.ActionRole)
|
||||||
|
b.clicked.connect(self.restore_defaults)
|
||||||
|
|
||||||
|
def add_entry(self, entry, prepend=False):
|
||||||
|
i = QListWidgetItem(entry['name'])
|
||||||
|
i.setData(Qt.UserRole, entry.copy())
|
||||||
|
self.entries.insertItem(0, i) if prepend else self.entries.addItem(i)
|
||||||
|
|
||||||
|
def build_entries(self, entries):
|
||||||
|
self.entries.clear()
|
||||||
|
for entry in entries:
|
||||||
|
self.add_entry(entry)
|
||||||
|
|
||||||
|
def restore_defaults(self):
|
||||||
|
self.build_entries(vprefs.defaults['lookup_locations'])
|
||||||
|
|
||||||
|
def add_source(self):
|
||||||
|
d = SourceEditor(self)
|
||||||
|
if d.exec_() == QDialog.Accepted:
|
||||||
|
self.add_entry(d.entry, prepend=True)
|
||||||
|
|
||||||
|
def remove_source(self):
|
||||||
|
idx = self.entries.currentRow()
|
||||||
|
if idx > -1:
|
||||||
|
self.entries.takeItem(idx)
|
||||||
|
|
||||||
|
def edit_source(self, source_item):
|
||||||
|
d = SourceEditor(self, source_item.data(Qt.UserRole))
|
||||||
|
if d.exec_() == QDialog.Accepted:
|
||||||
|
source_item.setData(Qt.UserRole, d.entry)
|
||||||
|
source_item.setData(Qt.DisplayRole, d.name)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def all_entries(self):
|
||||||
|
return [self.entries.item(r).data(Qt.UserRole) for r in range(self.entries.count())]
|
||||||
|
|
||||||
|
def accept(self):
|
||||||
|
entries = self.all_entries
|
||||||
|
if not entries:
|
||||||
|
return error_dialog(self, _('No sources'), _(
|
||||||
|
'You ust specify at least one lookup source'), show=True)
|
||||||
|
if entries == vprefs.defaults['lookup_locations']:
|
||||||
|
del vprefs['lookup_locations']
|
||||||
|
else:
|
||||||
|
vprefs['lookup_locations'] = entries
|
||||||
|
return Dialog.accept(self)
|
||||||
|
|
||||||
|
|
||||||
def create_profile():
|
def create_profile():
|
||||||
@ -108,11 +242,14 @@ class Lookup(QWidget):
|
|||||||
def add_sources(self):
|
def add_sources(self):
|
||||||
if SourcesEditor(self).exec_() == QDialog.Accepted:
|
if SourcesEditor(self).exec_() == QDialog.Accepted:
|
||||||
self.populate_sources()
|
self.populate_sources()
|
||||||
|
self.source_box.setCurrentIndex(0)
|
||||||
self.update_query()
|
self.update_query()
|
||||||
|
|
||||||
def source_changed(self):
|
def source_changed(self):
|
||||||
vprefs['lookup_location'] = self.source['name']
|
s = self.source
|
||||||
self.update_query()
|
if s is not None:
|
||||||
|
vprefs['lookup_location'] = s['name']
|
||||||
|
self.update_query()
|
||||||
|
|
||||||
def populate_sources(self):
|
def populate_sources(self):
|
||||||
sb = self.source_box
|
sb = self.source_box
|
||||||
|
Loading…
x
Reference in New Issue
Block a user