Merge from trunk

This commit is contained in:
Charles Haley 2011-01-24 20:21:07 +00:00
commit 5acaed2683
18 changed files with 228 additions and 51 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 635 B

View file

@ -0,0 +1,66 @@
__license__ = 'GPL v3'
__copyright__ = '2011, Darko Miletic <darko.miletic at gmail.com>'
'''
daily.tportal.hr
'''
from calibre.web.feeds.news import BasicNewsRecipe
class Pagina12(BasicNewsRecipe):
title = 'Daily tportal.h'
__author__ = 'Darko Miletic'
description = 'News from Croatia'
publisher = 'tportal.hr'
category = 'news, politics, Croatia'
oldest_article = 2
max_articles_per_feed = 200
no_stylesheets = True
encoding = 'utf-8'
use_embedded_content = False
language = 'en_HR'
remove_empty_feeds = True
publication_type = 'newsportal'
extra_css = """
body{font-family: Verdana,sans-serif }
img{margin-bottom: 0.4em; display:block}
h1,h2{color: #2D648A; font-family: Georgia,serif}
.artAbstract{font-size: 1.2em; font-family: Georgia,serif}
"""
conversion_options = {
'comment' : description
, 'tags' : category
, 'publisher' : publisher
, 'language' : language
}
remove_tags = [
dict(name=['meta','link','embed','object','iframe','base'])
,dict(name='div', attrs={'class':'artInfo'})
]
remove_attributes=['lang']
keep_only_tags=dict(attrs={'class':'articleDetails'})
feeds = [(u'News', u'http://daily.tportal.hr/rss/dailynaslovnicarss.xml')]
def preprocess_html(self, soup):
for item in soup.findAll(style=True):
del item['style']
for item in soup.findAll('a'):
limg = item.find('img')
if item.string is not None:
str = item.string
item.replaceWith(str)
else:
if limg:
item.name = 'div'
item.attrs = []
else:
str = self.tag_to_string(item)
item.replaceWith(str)
for item in soup.findAll('img'):
if not item.has_key('alt'):
item['alt'] = 'image'
return soup

View file

@ -52,6 +52,7 @@ class heiseDe(BasicNewsRecipe):
dict(id='navi_login'),
dict(id='navigation'),
dict(id='breadcrumb'),
dict(id='adblockerwarnung'),
dict(id=''),
dict(id='sitemap'),
dict(id='bannerzone'),
@ -67,3 +68,4 @@ class heiseDe(BasicNewsRecipe):

View file

@ -21,7 +21,7 @@ class hnaDe(BasicNewsRecipe):
max_articles_per_feed = 40
no_stylesheets = True
remove_javascript = True
encoding = 'iso-8859-1'
encoding = 'utf-8'
remove_tags = [dict(id='topnav'),
dict(id='nav_main'),
@ -60,3 +60,4 @@ class hnaDe(BasicNewsRecipe):
feeds = [ ('hna_soehre', 'http://feeds2.feedburner.com/hna/soehre'),
('hna_kassel', 'http://feeds2.feedburner.com/hna/kassel') ]

View file

@ -27,12 +27,34 @@ class cdnet(BasicNewsRecipe):
dict(id='header'),
dict(id='search'),
dict(id='nav'),
dict(id='blog-author-info'),
dict(id='post-tags'),
dict(id='bio-naraine'),
dict(id='bio-kennedy'),
dict(id='author-short-disclosure-kennedy'),
dict(id=''),
dict(name='div', attrs={'class':'banner'}),
dict(name='div', attrs={'class':'int'}),
dict(name='div', attrs={'class':'talkback clear space-2'}),
dict(name='div', attrs={'class':'content-1 clear'}),
dict(name='div', attrs={'class':'space-2'}),
dict(name='div', attrs={'class':'space-3'}),
dict(name='div', attrs={'class':'thumb-2 left'}),
dict(name='div', attrs={'class':'hotspot'}),
dict(name='div', attrs={'class':'hed hed-1 space-1'}),
dict(name='div', attrs={'class':'view-1 clear content-3 space-2'}),
dict(name='div', attrs={'class':'hed hed-1 space-1'}),
dict(name='div', attrs={'class':'hed hed-1'}),
dict(name='div', attrs={'class':'post-header'}),
dict(name='div', attrs={'class':'lvl-nav clear'}),
dict(name='div', attrs={'class':'t-share-overlay overlay-pop contain-overlay-4'}),
dict(name='p', attrs={'class':'tags'}),
dict(name='span', attrs={'class':'follow'}),
dict(name='span', attrs={'class':'int'}),
dict(name='h4', attrs={'class':'h s-4'}),
dict(name='a', attrs={'href':'http://www.twitter.com/ryanaraine'}),
dict(name='div', attrs={'class':'special1'})]
remove_tags_after = [dict(name='div', attrs={'class':'bloggerDesc clear'})]
remove_tags_after = [dict(name='div', attrs={'class':'clear'})]
feeds = [ ('zdnet', 'http://feeds.feedburner.com/zdnet/security') ]
@ -43,3 +65,4 @@ def preprocess_html(self, soup):
return soup

View file

@ -54,7 +54,7 @@ class ANDROID(USBMS):
0x1004 : { 0x61cc : [0x100] },
# Archos
0x0e79 : { 0x1419: [0x0216], 0x1420 : [0x0216]},
0x0e79 : { 0x1419: [0x0216], 0x1420 : [0x0216], 0x1422 : [0x0216]},
}
EBOOK_DIR_MAIN = ['eBooks/import', 'wordplayer/calibretransfer', 'Books']
@ -70,7 +70,7 @@ class ANDROID(USBMS):
'__UMS_COMPOSITE', '_MB200', 'MASS_STORAGE', '_-_CARD', 'SGH-I897',
'GT-I9000', 'FILE-STOR_GADGET', 'SGH-T959', 'SAMSUNG_ANDROID',
'SCH-I500_CARD', 'SPH-D700_CARD', 'MB810', 'GT-P1000', 'DESIRE',
'SGH-T849', '_MB300', 'A70S', 'S_ANDROID', 'A101IT']
'SGH-T849', '_MB300', 'A70S', 'S_ANDROID', 'A101IT', 'A70H']
WINDOWS_CARD_A_MEM = ['ANDROID_PHONE', 'GT-I9000_CARD', 'SGH-I897',
'FILE-STOR_GADGET', 'SGH-T959', 'SAMSUNG_ANDROID', 'GT-P1000_CARD',
'A70S', 'A101IT']

View file

@ -25,13 +25,15 @@ def __init__(self, extra_opts=None, log=None):
self.chapters_with_title = 0
self.blanks_deleted = False
self.linereg = re.compile('(?<=<p).*?(?=</p>)', re.IGNORECASE|re.DOTALL)
self.blankreg = re.compile(r'\s*(?P<openline><p(?!\sid=\"softbreak\")[^>]*>)\s*(?P<closeline></p>)', re.IGNORECASE)
self.blankreg = re.compile(r'\s*(?P<openline><p(?!\sclass=\"softbreak\")[^>]*>)\s*(?P<closeline></p>)', re.IGNORECASE)
self.softbreak = re.compile(r'\s*(?P<openline><p(?=\sclass=\"softbreak\")[^>]*>)\s*(?P<closeline></p>)', re.IGNORECASE)
self.multi_blank = re.compile(r'(\s*<p[^>]*>\s*</p>){2,}', re.IGNORECASE)
def is_pdftohtml(self, src):
return '<!-- created by calibre\'s pdftohtml -->' in src[:1000]
def chapter_head(self, match):
from calibre.utils.html2text import html2text
chap = match.group('chap')
title = match.group('title')
if not title:
@ -40,10 +42,12 @@ def chapter_head(self, match):
" chapters. - " + unicode(chap))
return '<h2>'+chap+'</h2>\n'
else:
txt_chap = html2text(chap)
txt_title = html2text(title)
self.html_preprocess_sections = self.html_preprocess_sections + 1
self.log.debug("marked " + unicode(self.html_preprocess_sections) +
" chapters & titles. - " + unicode(chap) + ", " + unicode(title))
return '<h2>'+chap+'</h2>\n<h3>'+title+'</h3>\n'
return '<h2 title="'+txt_chap+', '+txt_title+'">'+chap+'</h2>\n<h3 class="sigilNotInTOC">'+title+'</h3>\n'
def chapter_break(self, match):
chap = match.group('section')
@ -203,8 +207,8 @@ def markup_chapters(self, html, wordcount, blanks_between_paragraphs):
blank_lines = ""
opt_title_open = "("
opt_title_close = ")?"
n_lookahead_open = "\s+(?!"
n_lookahead_close = ")"
n_lookahead_open = "(?!\s*"
n_lookahead_close = ")\s*"
default_title = r"(<[ibu][^>]*>)?\s{0,3}(?!Chapter)([\w\:\'\"-]+\s{0,3}){1,5}?(</[ibu][^>]*>)?(?=<)"
simple_title = r"(<[ibu][^>]*>)?\s{0,3}(?!(Chapter|\s+<)).{0,65}?(</[ibu][^>]*>)?(?=<)"
@ -215,7 +219,7 @@ def markup_chapters(self, html, wordcount, blanks_between_paragraphs):
[r"[^'\"]?(Introduction|Synopsis|Acknowledgements|Epilogue|CHAPTER|Kapitel|Volume\b|Prologue|Book\b|Part\b|Dedication|Preface)\s*([\d\w-]+\:?\'?\s*){0,5}", True, True, True, False, "Searching for common section headings", 'common'],
[r"[^'\"]?(CHAPTER|Kapitel)\s*([\dA-Z\-\'\"\?!#,]+\s*){0,7}\s*", True, True, True, False, "Searching for most common chapter headings", 'chapter'], # Highest frequency headings which include titles
[r"<b[^>]*>\s*(<span[^>]*>)?\s*(?!([*#•=]+\s*)+)(\s*(?=[\d.\w#\-*\s]+<)([\d.\w#-*]+\s*){1,5}\s*)(?!\.)(</span>)?\s*</b>", True, True, True, False, "Searching for emphasized lines", 'emphasized'], # Emphasized lines
[r"[^'\"]?(\d+(\.|:))\s*([\dA-Z\-\'\"#,]+\s*){0,7}\s*", True, True, True, False, "Searching for numeric chapter headings", 'numeric'], # Numeric Chapters
[r"[^'\"]?(\d+(\.|:))\s*([\w\-\'\"#,]+\s*){0,7}\s*", True, True, True, False, "Searching for numeric chapter headings", 'numeric'], # Numeric Chapters
[r"([A-Z]\s+){3,}\s*([\d\w-]+\s*){0,3}\s*", True, True, True, False, "Searching for letter spaced headings", 'letter_spaced'], # Spaced Lettering
[r"[^'\"]?(\d+\.?\s+([\d\w-]+\:?\'?-?\s?){0,5})\s*", True, True, True, False, "Searching for numeric chapters with titles", 'numeric_title'], # Numeric Titles
[r"[^'\"]?(\d+)\s*([\dA-Z\-\'\"\?!#,]+\s*){0,7}\s*", True, True, True, False, "Searching for simple numeric headings", 'plain_number'], # Numeric Chapters, no dot or colon
@ -275,7 +279,7 @@ def recurse_patterns(html, analyze):
self.log.debug(unicode(type_name)+" had "+unicode(hits)+" hits - "+unicode(self.chapters_no_title)+" chapters with no title, "+unicode(self.chapters_with_title)+" chapters with titles, "+unicode(float(self.chapters_with_title) / float(hits))+" percent. ")
if type_name == 'common':
analysis_result.append([chapter_type, n_lookahead_req, strict_title, ignorecase, title_req, log_message, type_name])
elif self.min_chapters <= hits < max_chapters:
elif self.min_chapters <= hits < max_chapters or self.min_chapters < 3 > hits:
analysis_result.append([chapter_type, n_lookahead_req, strict_title, ignorecase, title_req, log_message, type_name])
break
else:
@ -367,6 +371,8 @@ def cleanup_markup(self, html):
html = re.sub(ur'\s*<o:p>\s*</o:p>', ' ', html)
# Delete microsoft 'smart' tags
html = re.sub('(?i)</?st1:\w+>', '', html)
# Delete self closing paragraph tags
html = re.sub('<p\s?/>', '', html)
# Get rid of empty span, bold, font, em, & italics tags
html = re.sub(r"\s*<span[^>]*>\s*(<span[^>]*>\s*</span>){0,2}\s*</span>\s*", " ", html)
html = re.sub(r"\s*<(font|[ibu]|em)[^>]*>\s*(<(font|[ibu]|em)[^>]*>\s*</(font|[ibu]|em)>\s*){0,2}\s*</(font|[ibu]|em)>", " ", html)
@ -467,7 +473,7 @@ def __call__(self, html):
if blanks_between_paragraphs and getattr(self.extra_opts, 'delete_blank_paragraphs', False):
self.log.debug("deleting blank lines")
self.blanks_deleted = True
html = self.multi_blank.sub('\n<p id="softbreak" style="margin-top:1.5em; margin-bottom:1.5em"> </p>', html)
html = self.multi_blank.sub('\n<p class="softbreak" style="margin-top:1.5em; margin-bottom:1.5em"> </p>', html)
html = self.blankreg.sub('', html)
# Determine line ending type
@ -522,11 +528,11 @@ def __call__(self, html):
# Center separator lines
html = re.sub(u'<(?P<outer>p|div)[^>]*>\s*(<(?P<inner1>font|span|[ibu])[^>]*>)?\s*(<(?P<inner2>font|span|[ibu])[^>]*>)?\s*(<(?P<inner3>font|span|[ibu])[^>]*>)?\s*(?P<break>([*#•=✦]+\s*)+)\s*(</(?P=inner3)>)?\s*(</(?P=inner2)>)?\s*(</(?P=inner1)>)?\s*</(?P=outer)>', '<p style="text-align:center; margin-top:1.25em; margin-bottom:1.25em">' + '\g<break>' + '</p>', html)
if not self.blanks_deleted:
html = self.multi_blank.sub('\n<p id="softbreak" style="margin-top:1.5em; margin-bottom:1.5em"> </p>', html)
html = re.sub('<p\s+id="softbreak"[^>]*>\s*</p>', '<div id="softbreak" style="margin-left: 45%; margin-right: 45%; margin-top:1.5em; margin-bottom:1.5em"><hr style="height: 3px; background:#505050" /></div>', html)
html = self.multi_blank.sub('\n<p class="softbreak" style="margin-top:1.5em; margin-bottom:1.5em"> </p>', html)
html = re.sub('<p\s+class="softbreak"[^>]*>\s*</p>', '<div id="softbreak" style="margin-left: 45%; margin-right: 45%; margin-top:1.5em; margin-bottom:1.5em"><hr style="height: 3px; background:#505050" /></div>', html)
if self.deleted_nbsps:
# put back non-breaking spaces in empty paragraphs to preserve original formatting
html = self.blankreg.sub('\n'+r'\g<openline>'+u'\u00a0'+r'\g<closeline>', html)
html = self.softbreak.sub('\n'+r'\g<openline>'+u'\u00a0'+r'\g<closeline>', html)
return html

View file

@ -411,7 +411,7 @@ def cleanup_title(s):
r.pubdate = pubdate
def fix_case(x):
if x and x.isupper():
if x:
x = titlecase(x)
return x

View file

@ -6,7 +6,7 @@
import re
from PyQt4.QtCore import SIGNAL, Qt
from PyQt4.QtCore import SIGNAL, Qt, pyqtSignal
from PyQt4.QtGui import QDialog, QWidget, QDialogButtonBox, \
QBrush, QTextCursor, QTextEdit
@ -19,8 +19,8 @@
class RegexBuilder(QDialog, Ui_RegexBuilder):
def __init__(self, db, book_id, regex, *args):
QDialog.__init__(self, *args)
def __init__(self, db, book_id, regex, doc=None, parent=None):
QDialog.__init__(self, parent)
self.setupUi(self)
self.regex.setText(regex)
@ -28,9 +28,13 @@ def __init__(self, db, book_id, regex, *args):
if not db or not book_id:
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
return
if doc:
self.preview.setPlainText(doc)
self.cancelled = False
self.connect(self.button_box, SIGNAL('clicked(QAbstractButton*)'), self.button_clicked)
self.connect(self.regex, SIGNAL('textChanged(QString)'), self.regex_valid)
@ -153,24 +157,36 @@ def button_clicked(self, button):
if button == self.button_box.button(QDialogButtonBox.Ok):
self.accept()
def doc(self):
return unicode(self.preview.toPlainText())
class RegexEdit(QWidget, Ui_Edit):
doc_update = pyqtSignal(unicode)
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.setupUi(self)
self.book_id = None
self.db = None
self.doc_cache = None
self.connect(self.button, SIGNAL('clicked()'), self.builder)
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:
return
if not self.doc_cache:
self.doc_cache = bld.doc()
self.doc_update.emit(self.doc_cache)
if bld.exec_() == bld.Accepted:
self.edit.setText(bld.regex.text())
def doc(self):
return self.doc_cache
def setObjectName(self, *args):
QWidget.setObjectName(self, *args)
if hasattr(self, 'edit'):
@ -185,8 +201,11 @@ def set_book_id(self, book_id):
def set_db(self, db):
self.db = db
def set_doc(self, doc):
self.doc_cache = doc
def break_cycles(self):
self.db = None
self.db = self.doc_cache = None
@property
def text(self):

View file

@ -35,13 +35,26 @@ def __init__(self, parent, get_option, get_help, db=None, book_id=None):
self.opt_sr3_search.set_book_id(book_id)
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):
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_sr2_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):
for x in ('sr1_search', 'sr2_search', 'sr3_search'):
x = getattr(self, 'opt_'+x)

View file

@ -7,7 +7,7 @@
from PyQt4.Qt import Qt, QDialog, QGridLayout, QVBoxLayout, QFont, QLabel, \
pyqtSignal, QDialogButtonBox, QInputDialog, QLineEdit, \
QMessageBox, QDate, QLineEdit
QMessageBox, QDate
from calibre.gui2.dialogs.metadata_bulk_ui import Ui_MetadataBulkDialog
from calibre.gui2.dialogs.tag_editor import TagEditor
@ -15,7 +15,7 @@
from calibre.ebooks.metadata.book.base import composite_formatter
from calibre.ebooks.metadata.meta import get_metadata
from calibre.gui2.custom_column_widgets import populate_metadata_page
from calibre.gui2 import error_dialog, ResizableDialog, UNDEFINED_QDATE
from calibre.gui2 import error_dialog, ResizableDialog, UNDEFINED_QDATE, gprefs
from calibre.gui2.progress_indicator import ProgressIndicator
from calibre.utils.config import dynamic, JSONConfig
from calibre.utils.titlecase import titlecase
@ -321,8 +321,15 @@ def __init__(self, window, rows, model, tab):
'This operation cannot be canceled or undone'))
self.do_again = False
self.central_widget.setCurrentIndex(tab)
geom = gprefs.get('bulk_metadata_window_geometry', None)
if geom is not None:
self.restoreGeometry(bytes(geom))
self.exec_()
def save_state(self, *args):
gprefs['bulk_metadata_window_geometry'] = \
bytearray(self.saveGeometry())
def do_apply_pubdate(self, *args):
self.apply_pubdate.setChecked(True)
@ -790,7 +797,12 @@ def auto_number_changed(self, state):
self.series_start_number.setEnabled(False)
self.series_start_number.setValue(1)
def reject(self):
self.save_state()
ResizableDialog.reject(self)
def accept(self):
self.save_state()
if len(self.ids) < 1:
return QDialog.accept(self)

View file

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>850</width>
<height>650</height>
<width>962</width>
<height>727</height>
</rect>
</property>
<property name="windowTitle">
@ -44,8 +44,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>832</width>
<height>574</height>
<width>954</width>
<height>666</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
@ -55,7 +55,7 @@
<item>
<widget class="QTabWidget" name="central_widget">
<property name="currentIndex">
<number>2</number>
<number>0</number>
</property>
<widget class="QWidget" name="tabWidgetPage1">
<attribute name="title">
@ -996,8 +996,8 @@ not multiple and the destination field is multiple</string>
<rect>
<x>0</x>
<y>0</y>
<width>810</width>
<height>264</height>
<width>197</width>
<height>60</height>
</rect>
</property>
<layout class="QGridLayout" name="testgrid">

View file

@ -16,7 +16,7 @@ def __init__(self, window, db, id_=None):
self.setupUi(self)
self.db = db
self.index = db.row(id_)
self.index = db.row(id_) if id_ is not None else None
if self.index is not None:
tags = self.db.tags(self.index)
else:

View file

@ -43,7 +43,17 @@ p, li { white-space: pre-wrap; }
</property>
<layout class="QVBoxLayout">
<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>
</layout>
</widget>
@ -94,8 +104,8 @@ p, li { white-space: pre-wrap; }
<rect>
<x>0</x>
<y>0</y>
<width>301</width>
<height>234</height>
<width>277</width>
<height>276</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_2">

View file

@ -16,7 +16,6 @@
QTimer, QRect
from calibre.gui2 import NONE, error_dialog, pixmap_to_data, gprefs
from calibre.constants import isosx
from calibre.gui2.filename_pattern_ui import Ui_Form
from calibre import fit_image
from calibre.ebooks import BOOK_EXTENSIONS
@ -67,17 +66,31 @@ def __init__(self, parent):
self.setupUi(self)
self.connect(self.test_button, SIGNAL('clicked()'), self.do_test)
self.connect(self.re, SIGNAL('returnPressed()'), self.do_test)
self.initialize()
self.re.textChanged.connect(lambda x: self.changed_signal.emit())
self.connect(self.re.lineEdit(), SIGNAL('returnPressed()'), self.do_test)
self.re.lineEdit().textChanged.connect(lambda x: self.changed_signal.emit())
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:
val = prefs.defaults['filename_pattern']
else:
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):
try:
@ -110,12 +123,21 @@ def do_test(self):
def pattern(self):
pat = unicode(self.re.text())
pat = unicode(self.re.lineEdit().text())
return re.compile(pat)
def commit(self):
pat = self.pattern().pattern
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
@ -304,8 +326,9 @@ def data(self, index, role):
return NONE
if role == Qt.DisplayRole:
return QVariant(family)
if not isosx and role == Qt.FontRole:
# Causes a Qt crash with some fonts on OS X
if False and role == Qt.FontRole:
# Causes a Qt crash with some fonts
# so disabled.
return QVariant(QFont(family))
return NONE

View file

@ -135,7 +135,7 @@ def _match(query, value, matchkind):
pass
return False
class CacheRow(list):
class CacheRow(list): # {{{
def __init__(self, db, composites, val):
self.db = db
@ -166,13 +166,14 @@ def __getitem__(self, col):
def __getslice__(self, i, j):
return self.__getitem__(slice(i, j))
# }}}
class ResultCache(SearchQueryParser): # {{{
'''
Stores sorted and filtered metadata in memory.
'''
def __init__(self, FIELD_MAP, field_metadata, db_prefs = None):
def __init__(self, FIELD_MAP, field_metadata, db_prefs=None):
self.FIELD_MAP = FIELD_MAP
self.db_prefs = db_prefs
self.composites = {}
@ -192,7 +193,7 @@ def __init__(self, FIELD_MAP, field_metadata, db_prefs = None):
def break_cycles(self):
self._data = self.field_metadata = self.FIELD_MAP = \
self.numeric_search_relops = self.date_search_relops = \
self.all_search_locations = None
self.all_search_locations = self.db_prefs = None
def __getitem__(self, row):
@ -410,7 +411,7 @@ def get_user_category_matches(self, location, query, candidates):
res = set([])
if self.db_prefs is None:
return res
user_cats = self.db_prefs['user_categories']
user_cats = self.db_prefs.get('user_categories', [])
if location not in user_cats:
return res
c = set(candidates)

View file

@ -587,11 +587,11 @@ TXT input supports a number of options to differentiate how paragraphs are detec
Assumes that every paragraph starts with an indent (either a tab or 2+ spaces). Paragraphs end when
the next line that starts with an indent is reached::
This is the
This is the
first.
This is the second.
This is the second.
This is the
This is the
third.
:guilabel:`Paragraph Style: Unformatted`
@ -603,7 +603,7 @@ TXT input supports a number of options to differentiate how paragraphs are detec
formatting will be applied.
:guilabel:`Formatting Style: Heuristic`
Analyses the document for common chapter headings, scene breaks, and italicized words and applies the
Analyzes the document for common chapter headings, scene breaks, and italicized words and applies the
appropriate html markup during conversion.
:guilabel:`Formatting Style: Markdown`

View file

@ -105,6 +105,7 @@ def set_translators():
'en_TH' : _('English (Thailand)'),
'en_CY' : _('English (Cyprus)'),
'en_PK' : _('English (Pakistan)'),
'en_HR' : _('English (Croatia)'),
'en_IL' : _('English (Israel)'),
'en_SG' : _('English (Singapore)'),
'en_YE' : _('English (Yemen)'),