mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Store previously used regular expressions for getting metadata from filenames. Fixes #8504 (Drop down regular expressions for import). Search and replace wizard: Cache the previously used input document.
This commit is contained in:
commit
186203c99b
@ -6,7 +6,7 @@ __docformat__ = 'restructuredtext en'
|
|||||||
|
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from PyQt4.QtCore import SIGNAL, Qt
|
from PyQt4.QtCore import SIGNAL, Qt, pyqtSignal
|
||||||
from PyQt4.QtGui import QDialog, QWidget, QDialogButtonBox, \
|
from PyQt4.QtGui import QDialog, QWidget, QDialogButtonBox, \
|
||||||
QBrush, QTextCursor, QTextEdit
|
QBrush, QTextCursor, QTextEdit
|
||||||
|
|
||||||
@ -19,8 +19,8 @@ from calibre.gui2.dialogs.choose_format import ChooseFormatDialog
|
|||||||
|
|
||||||
class RegexBuilder(QDialog, Ui_RegexBuilder):
|
class RegexBuilder(QDialog, Ui_RegexBuilder):
|
||||||
|
|
||||||
def __init__(self, db, book_id, regex, *args):
|
def __init__(self, db, book_id, regex, doc=None, parent=None):
|
||||||
QDialog.__init__(self, *args)
|
QDialog.__init__(self, parent)
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
|
|
||||||
self.regex.setText(regex)
|
self.regex.setText(regex)
|
||||||
@ -28,9 +28,13 @@ class RegexBuilder(QDialog, Ui_RegexBuilder):
|
|||||||
|
|
||||||
if not db or not book_id:
|
if not db or not book_id:
|
||||||
self.button_box.addButton(QDialogButtonBox.Open)
|
self.button_box.addButton(QDialogButtonBox.Open)
|
||||||
elif not self.select_format(db, book_id):
|
elif not doc and not self.select_format(db, book_id):
|
||||||
self.cancelled = True
|
self.cancelled = True
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if doc:
|
||||||
|
self.preview.setPlainText(doc)
|
||||||
|
|
||||||
self.cancelled = False
|
self.cancelled = False
|
||||||
self.connect(self.button_box, SIGNAL('clicked(QAbstractButton*)'), self.button_clicked)
|
self.connect(self.button_box, SIGNAL('clicked(QAbstractButton*)'), self.button_clicked)
|
||||||
self.connect(self.regex, SIGNAL('textChanged(QString)'), self.regex_valid)
|
self.connect(self.regex, SIGNAL('textChanged(QString)'), self.regex_valid)
|
||||||
@ -153,24 +157,36 @@ class RegexBuilder(QDialog, Ui_RegexBuilder):
|
|||||||
if button == self.button_box.button(QDialogButtonBox.Ok):
|
if button == self.button_box.button(QDialogButtonBox.Ok):
|
||||||
self.accept()
|
self.accept()
|
||||||
|
|
||||||
|
def doc(self):
|
||||||
|
return unicode(self.preview.toPlainText())
|
||||||
|
|
||||||
class RegexEdit(QWidget, Ui_Edit):
|
class RegexEdit(QWidget, Ui_Edit):
|
||||||
|
|
||||||
|
doc_update = pyqtSignal(unicode)
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
QWidget.__init__(self, parent)
|
QWidget.__init__(self, parent)
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
|
|
||||||
self.book_id = None
|
self.book_id = None
|
||||||
self.db = None
|
self.db = None
|
||||||
|
self.doc_cache = None
|
||||||
|
|
||||||
self.connect(self.button, SIGNAL('clicked()'), self.builder)
|
self.connect(self.button, SIGNAL('clicked()'), self.builder)
|
||||||
|
|
||||||
def builder(self):
|
def builder(self):
|
||||||
bld = RegexBuilder(self.db, self.book_id, self.edit.text(), self)
|
bld = RegexBuilder(self.db, self.book_id, self.edit.text(), self.doc_cache, self)
|
||||||
if bld.cancelled:
|
if bld.cancelled:
|
||||||
return
|
return
|
||||||
|
if not self.doc_cache:
|
||||||
|
self.doc_cache = bld.doc()
|
||||||
|
self.doc_update.emit(self.doc_cache)
|
||||||
if bld.exec_() == bld.Accepted:
|
if bld.exec_() == bld.Accepted:
|
||||||
self.edit.setText(bld.regex.text())
|
self.edit.setText(bld.regex.text())
|
||||||
|
|
||||||
|
def doc(self):
|
||||||
|
return self.doc_cache
|
||||||
|
|
||||||
def setObjectName(self, *args):
|
def setObjectName(self, *args):
|
||||||
QWidget.setObjectName(self, *args)
|
QWidget.setObjectName(self, *args)
|
||||||
if hasattr(self, 'edit'):
|
if hasattr(self, 'edit'):
|
||||||
@ -185,8 +201,11 @@ class RegexEdit(QWidget, Ui_Edit):
|
|||||||
def set_db(self, db):
|
def set_db(self, db):
|
||||||
self.db = db
|
self.db = db
|
||||||
|
|
||||||
|
def set_doc(self, doc):
|
||||||
|
self.doc_cache = doc
|
||||||
|
|
||||||
def break_cycles(self):
|
def break_cycles(self):
|
||||||
self.db = None
|
self.db = self.doc_cache = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def text(self):
|
def text(self):
|
||||||
|
@ -35,13 +35,26 @@ class SearchAndReplaceWidget(Widget, Ui_Form):
|
|||||||
self.opt_sr3_search.set_book_id(book_id)
|
self.opt_sr3_search.set_book_id(book_id)
|
||||||
self.opt_sr3_search.set_db(db)
|
self.opt_sr3_search.set_db(db)
|
||||||
|
|
||||||
|
self.opt_sr1_search.doc_update.connect(self.update_doc)
|
||||||
|
self.opt_sr2_search.doc_update.connect(self.update_doc)
|
||||||
|
self.opt_sr3_search.doc_update.connect(self.update_doc)
|
||||||
|
|
||||||
def break_cycles(self):
|
def break_cycles(self):
|
||||||
Widget.break_cycles(self)
|
Widget.break_cycles(self)
|
||||||
|
|
||||||
|
self.opt_sr1_search.doc_update.disconnect()
|
||||||
|
self.opt_sr2_search.doc_update.disconnect()
|
||||||
|
self.opt_sr3_search.doc_update.disconnect()
|
||||||
|
|
||||||
self.opt_sr1_search.break_cycles()
|
self.opt_sr1_search.break_cycles()
|
||||||
self.opt_sr2_search.break_cycles()
|
self.opt_sr2_search.break_cycles()
|
||||||
self.opt_sr3_search.break_cycles()
|
self.opt_sr3_search.break_cycles()
|
||||||
|
|
||||||
|
def update_doc(self, doc):
|
||||||
|
self.opt_sr1_search.set_doc(doc)
|
||||||
|
self.opt_sr2_search.set_doc(doc)
|
||||||
|
self.opt_sr3_search.set_doc(doc)
|
||||||
|
|
||||||
def pre_commit_check(self):
|
def pre_commit_check(self):
|
||||||
for x in ('sr1_search', 'sr2_search', 'sr3_search'):
|
for x in ('sr1_search', 'sr2_search', 'sr3_search'):
|
||||||
x = getattr(self, 'opt_'+x)
|
x = getattr(self, 'opt_'+x)
|
||||||
|
@ -43,7 +43,17 @@ p, li { white-space: pre-wrap; }
|
|||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout">
|
<layout class="QVBoxLayout">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLineEdit" name="re"/>
|
<widget class="QComboBox" name="re">
|
||||||
|
<property name="editable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="maxCount">
|
||||||
|
<number>10</number>
|
||||||
|
</property>
|
||||||
|
<property name="insertPolicy">
|
||||||
|
<enum>QComboBox::InsertAtTop</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
@ -94,8 +104,8 @@ p, li { white-space: pre-wrap; }
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>301</width>
|
<width>277</width>
|
||||||
<height>234</height>
|
<height>276</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout_2">
|
<layout class="QGridLayout" name="gridLayout_2">
|
||||||
|
@ -66,17 +66,31 @@ class FilenamePattern(QWidget, Ui_Form):
|
|||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
|
|
||||||
self.connect(self.test_button, SIGNAL('clicked()'), self.do_test)
|
self.connect(self.test_button, SIGNAL('clicked()'), self.do_test)
|
||||||
self.connect(self.re, SIGNAL('returnPressed()'), self.do_test)
|
self.connect(self.re.lineEdit(), SIGNAL('returnPressed()'), self.do_test)
|
||||||
self.initialize()
|
self.re.lineEdit().textChanged.connect(lambda x: self.changed_signal.emit())
|
||||||
self.re.textChanged.connect(lambda x: self.changed_signal.emit())
|
|
||||||
|
|
||||||
def initialize(self, defaults=False):
|
def initialize(self, defaults=False):
|
||||||
|
# Get all itmes in the combobox. If we are resting
|
||||||
|
# to defaults we don't want to lose what the user
|
||||||
|
# has added.
|
||||||
|
val_hist = [unicode(self.re.lineEdit().text())] + [unicode(self.re.itemText(i)) for i in xrange(self.re.count())]
|
||||||
|
self.re.clear()
|
||||||
|
|
||||||
if defaults:
|
if defaults:
|
||||||
val = prefs.defaults['filename_pattern']
|
val = prefs.defaults['filename_pattern']
|
||||||
else:
|
else:
|
||||||
val = prefs['filename_pattern']
|
val = prefs['filename_pattern']
|
||||||
self.re.setText(val)
|
self.re.lineEdit().setText(val)
|
||||||
|
|
||||||
|
val_hist += gprefs.get('filename_pattern_history', ['(?P<title>.+)', '(?P<author>[^_-]+) -?\s*(?P<series>[^_0-9-]*)(?P<series_index>[0-9]*)\s*-\s*(?P<title>[^_].+) ?'])
|
||||||
|
if val in val_hist:
|
||||||
|
del val_hist[val_hist.index(val)]
|
||||||
|
val_hist.insert(0, val)
|
||||||
|
for v in val_hist:
|
||||||
|
# Ensure we don't have duplicate items.
|
||||||
|
if v and self.re.findText(v) == -1:
|
||||||
|
self.re.addItem(v)
|
||||||
|
self.re.setCurrentIndex(0)
|
||||||
|
|
||||||
def do_test(self):
|
def do_test(self):
|
||||||
try:
|
try:
|
||||||
@ -109,12 +123,21 @@ class FilenamePattern(QWidget, Ui_Form):
|
|||||||
|
|
||||||
|
|
||||||
def pattern(self):
|
def pattern(self):
|
||||||
pat = unicode(self.re.text())
|
pat = unicode(self.re.lineEdit().text())
|
||||||
return re.compile(pat)
|
return re.compile(pat)
|
||||||
|
|
||||||
def commit(self):
|
def commit(self):
|
||||||
pat = self.pattern().pattern
|
pat = self.pattern().pattern
|
||||||
prefs['filename_pattern'] = pat
|
prefs['filename_pattern'] = pat
|
||||||
|
|
||||||
|
history = []
|
||||||
|
history_pats = [unicode(self.re.lineEdit().text())] + [unicode(self.re.itemText(i)) for i in xrange(self.re.count())]
|
||||||
|
for p in history_pats[:14]:
|
||||||
|
# Ensure we don't have duplicate items.
|
||||||
|
if p and p not in history:
|
||||||
|
history.append(p)
|
||||||
|
gprefs['filename_pattern_history'] = history
|
||||||
|
|
||||||
return pat
|
return pat
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user