KG updates

This commit is contained in:
GRiker 2010-06-23 02:14:30 -06:00
commit 7d86373781
18 changed files with 160 additions and 134 deletions

View File

@ -71,3 +71,5 @@ gui_pubdate_display_format = 'MMM yyyy'
# order until the title is edited. Double-clicking on a title and hitting return # order until the title is edited. Double-clicking on a title and hitting return
# without changing anything is sufficient to change the sort. # without changing anything is sufficient to change the sort.
title_series_sorting = 'library_order' title_series_sorting = 'library_order'

Binary file not shown.

View File

@ -0,0 +1,71 @@
from calibre.web.feeds.news import BasicNewsRecipe
class AdvancedUserRecipe1277228948(BasicNewsRecipe):
title = u'China Press USA'
oldest_article = 7
max_articles_per_feed = 100
__author__ = 'rty'
__version__ = '1.0'
language = 'zh_CN'
pubisher = 'www.chinapressusa.com'
description = 'Overseas Chinese Network Newspaper in the USA'
category = 'News in Chinese, USA'
remove_javascript = True
use_embedded_content = False
no_stylesheets = True
#encoding = 'GB2312'
encoding = 'UTF-8'
conversion_options = {'linearize_tables':True}
masthead_url ='http://www.chinapressusa.com/common/images/logo.gif'
extra_css = '''
@font-face { font-family: "DroidFont", serif, sans-serif; src: url(res:///system/fonts/DroidSansFallback.ttf); }\n
body {
margin-right: 8pt;
font-family: 'DroidFont', serif;}
h1 {font-family: 'DroidFont', serif, sans-serif}
.show {font-family: 'DroidFont', serif, sans-serif}
'''
feeds = [
(u'\u65b0\u95fb\u9891\u9053', u'http://news.uschinapress.com/news.xml'),
(u'\u534e\u4eba\u9891\u9053', u'http://chinese.uschinapress.com/chinese.xml'),
(u'\u8bc4\u8bba\u9891\u9053', u'http://review.uschinapress.com/review.xml'),
]
keep_only_tags = [
dict(name='div', attrs={'class':'show'}),
]
remove_tags = [
# dict(name='table', attrs={'class':'xle'}),
dict(name='div', attrs={'class':'time'}),
]
remove_tags_after = [
dict(name='div', attrs={'class':'bank17'}),
# dict(name='a', attrs={'class':'ab12'}),
]
def append_page(self, soup, appendtag, position):
pager = soup.find('div',attrs={'id':'displaypagenum'})
if pager:
nexturl = self.INDEX + pager.a['href']
soup2 = self.index_to_soup(nexturl)
texttag = soup2.find('div', attrs={'class':'show'})
for it in texttag.findAll(style=True):
del it['style']
newpos = len(texttag.contents)
self.append_page(soup2,texttag,newpos)
texttag.extract()
appendtag.insert(position,texttag)
def preprocess_html(self, soup):
mtag = '<meta http-equiv="Content-Language" content="zh-CN"/>\n<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>'
soup.head.insert(0,mtag)
for item in soup.findAll(style=True):
del item['style']
self.append_page(soup, soup.body, 3)
pager = soup.find('div',attrs={'id':'displaypagenum'})
if pager:
pager.extract()
return soup

View File

@ -17,7 +17,7 @@ class NYTimes(BasicNewsRecipe):
title = 'New York Times Top Stories' title = 'New York Times Top Stories'
__author__ = 'GRiker' __author__ = 'GRiker'
language = 'en' language = 'en'
requires_version = (0, 7, 3) requires_version = (0, 7, 5)
description = 'Top Stories from the New York Times' description = 'Top Stories from the New York Times'
# List of sections typically included in Top Stories. Use a keyword from the # List of sections typically included in Top Stories. Use a keyword from the

View File

@ -13,14 +13,14 @@ Story
import re, string, time import re, string, time
from calibre import strftime from calibre import strftime
from calibre.web.feeds.recipes import BasicNewsRecipe from calibre.web.feeds.recipes import BasicNewsRecipe
from calibre.ebooks.BeautifulSoup import BeautifulSoup, BeautifulStoneSoup, NavigableString, Tag from calibre.ebooks.BeautifulSoup import BeautifulStoneSoup, NavigableString, Tag
class NYTimes(BasicNewsRecipe): class NYTimes(BasicNewsRecipe):
title = 'The New York Times' title = 'The New York Times'
__author__ = 'GRiker' __author__ = 'GRiker'
language = 'en' language = 'en'
requires_version = (0, 7, 3) requires_version = (0, 7, 5)
description = 'Daily news from the New York Times (subscription version)' description = 'Daily news from the New York Times (subscription version)'
allSectionKeywords = ['The Front Page', 'International','National','Obituaries','Editorials', allSectionKeywords = ['The Front Page', 'International','National','Obituaries','Editorials',

View File

@ -36,7 +36,7 @@ class Plugin(_Plugin):
self.fnames = dict((name, sz) for name, _, sz in self.fsizes if name) self.fnames = dict((name, sz) for name, _, sz in self.fsizes if name)
self.fnums = dict((num, sz) for _, num, sz in self.fsizes if num) self.fnums = dict((num, sz) for _, num, sz in self.fsizes if num)
# Input profiles {{{
class InputProfile(Plugin): class InputProfile(Plugin):
author = 'Kovid Goyal' author = 'Kovid Goyal'
@ -218,6 +218,8 @@ input_profiles = [InputProfile, SonyReaderInput, SonyReader300Input,
input_profiles.sort(cmp=lambda x,y:cmp(x.name.lower(), y.name.lower())) input_profiles.sort(cmp=lambda x,y:cmp(x.name.lower(), y.name.lower()))
# }}}
class OutputProfile(Plugin): class OutputProfile(Plugin):
author = 'Kovid Goyal' author = 'Kovid Goyal'
@ -239,6 +241,10 @@ class OutputProfile(Plugin):
# If True output should be optimized for a touchscreen interface # If True output should be optimized for a touchscreen interface
touchscreen = False touchscreen = False
touchscreen_news_css = ''
# A list of extra (beyond CSS 2.1) modules supported by the device
# Format is a cssutils profile dictionary (see iPad for example)
extra_css_modules = []
@classmethod @classmethod
def tags_to_string(cls, tags): def tags_to_string(cls, tags):
@ -253,18 +259,21 @@ class iPadOutput(OutputProfile):
screen_size = (768, 1024) screen_size = (768, 1024)
comic_screen_size = (768, 1024) comic_screen_size = (768, 1024)
dpi = 132.0 dpi = 132.0
timefmt = '%A, %d %b %Y' extra_css_modules = [
cssutils_addProfile = { 'name':'webkit', {
'props': { 'name':'webkit',
'-webkit-border-bottom-left-radius':'{length}', 'props': { '-webkit-border-bottom-left-radius':'{length}',
'-webkit-border-bottom-right-radius':'{length}', '-webkit-border-bottom-right-radius':'{length}',
'-webkit-border-top-left-radius':'{length}', '-webkit-border-top-left-radius':'{length}',
'-webkit-border-top-right-radius':'{length}', '-webkit-border-top-right-radius':'{length}',
'-webkit-border-radius': r'{border-width}(\s+{border-width}){0,3}|inherit', '-webkit-border-radius': r'{border-width}(\s+{border-width}){0,3}|inherit',
}, },
'macros': {'border-width': '{length}|medium|thick|thin'}} 'macros': {'border-width': '{length}|medium|thick|thin'}
}
]
touchscreen = True touchscreen = True
touchscreen_css = u''' # touchscreen_news_css {{{
touchscreen_news_css = u'''
/* hr used in articles */ /* hr used in articles */
.caption_divider { .caption_divider {
border:#ccc 1px solid; border:#ccc 1px solid;
@ -328,6 +337,7 @@ class iPadOutput(OutputProfile):
} }
''' '''
# }}}
class SonyReaderOutput(OutputProfile): class SonyReaderOutput(OutputProfile):

View File

@ -45,8 +45,8 @@ class ANDROID(USBMS):
'GT-I5700', 'SAMSUNG'] 'GT-I5700', 'SAMSUNG']
WINDOWS_MAIN_MEM = ['ANDROID_PHONE', 'A855', 'A853', 'INC.NEXUS_ONE', WINDOWS_MAIN_MEM = ['ANDROID_PHONE', 'A855', 'A853', 'INC.NEXUS_ONE',
'__UMS_COMPOSITE', '_MB200', 'MASS_STORAGE', '_-_CARD', '__UMS_COMPOSITE', '_MB200', 'MASS_STORAGE', '_-_CARD',
'PROD_GT-I9000'] 'PR OD_GT-I9000']
WINDOWS_CARD_A_MEM = ['ANDROID_PHONE', 'PROD_GT-I9000_CARD'] WINDOWS_CARD_A_MEM = ['ANDROID_PHONE', 'PR OD_GT-I9000_CARD']
OSX_MAIN_MEM = 'HTC Android Phone Media' OSX_MAIN_MEM = 'HTC Android Phone Media'

View File

@ -16,7 +16,7 @@ from calibre.ebooks.BeautifulSoup import BeautifulSoup
from calibre.ebooks.metadata import MetaInformation from calibre.ebooks.metadata import MetaInformation
from calibre.ebooks.metadata.epub import set_metadata from calibre.ebooks.metadata.epub import set_metadata
from calibre.library.server.utils import strftime from calibre.library.server.utils import strftime
from calibre.utils.config import Config, ConfigProxy, config_dir from calibre.utils.config import config_dir
from calibre.utils.date import isoformat, now, parse_date from calibre.utils.date import isoformat, now, parse_date
from calibre.utils.logging import Log from calibre.utils.logging import Log
from calibre.utils.zipfile import ZipFile from calibre.utils.zipfile import ZipFile
@ -34,8 +34,15 @@ if isosx:
if iswindows: if iswindows:
import pythoncom, win32com.client import pythoncom, win32com.client
class DriverBase(DeviceConfig, DevicePlugin):
# Needed for config_widget to work
FORMATS = ['epub', 'pdf']
class ITUNES(DeviceConfig, DevicePlugin): @classmethod
def _config_base_name(cls):
return 'iTunes'
class ITUNES(DriverBase):
''' '''
Calling sequences: Calling sequences:
Initialization: Initialization:
@ -84,16 +91,6 @@ class ITUNES(DeviceConfig, DevicePlugin):
OPEN_FEEDBACK_MESSAGE = _( OPEN_FEEDBACK_MESSAGE = _(
'Apple device detected, launching iTunes, please wait ...') 'Apple device detected, launching iTunes, please wait ...')
FORMATS = ['epub','pdf']
# Configuration
HELP_MESSAGE = _('Configure Device')
EXTRA_CUSTOMIZATION_MESSAGE = None
EXTRA_CUSTOMIZATION_DEFAULT = None
MUST_READ_METADATA = False
SAVE_TEMPLATE = '{title}'
SUPPORTS_SUB_DIRS = False
SUPPORTS_USE_AUTHOR_SORT = False
# Product IDs: # Product IDs:
# 0x1292:iPhone 3G # 0x1292:iPhone 3G
@ -173,7 +170,6 @@ class ITUNES(DeviceConfig, DevicePlugin):
sources = None sources = None
update_msg = None update_msg = None
update_needed = False update_needed = False
use_series_as_category = False
# Public methods # Public methods
def add_books_to_metadata(self, locations, metadata, booklists): def add_books_to_metadata(self, locations, metadata, booklists):
@ -522,29 +518,19 @@ class ITUNES(DeviceConfig, DevicePlugin):
''' '''
return (None,None) return (None,None)
def config_widget(self): @classmethod
def config_widget(cls):
''' '''
Return a QWidget with settings for the device interface Return a QWidget with settings for the device interface
''' '''
if DEBUG: cw = DriverBase.config_widget()
self.log.info("ITUNES.config_widget()")
from calibre.gui2.device_drivers.configwidget import ConfigWidget
cw = ConfigWidget(self.settings(), self.FORMATS, self.SUPPORTS_SUB_DIRS,
self.MUST_READ_METADATA, self.SUPPORTS_USE_AUTHOR_SORT,
self.EXTRA_CUSTOMIZATION_MESSAGE)
# Turn off the Save template # Turn off the Save template
cw.opt_save_template.setVisible(False) cw.opt_save_template.setVisible(False)
cw.label.setVisible(False) cw.label.setVisible(False)
# Repurpose the checkbox # Repurpose the checkbox
cw.opt_read_metadata.setText("Use Series as Genre in iTunes/iBooks") cw.opt_read_metadata.setText(_("Use Series as Genre in iTunes/iBooks"))
return cw return cw
def customization_help(self,gui=False):
if DEBUG:
self.log.info("ITUNES.customization_help()")
return _('Configure Device')
def delete_books(self, paths, end_session=True): def delete_books(self, paths, end_session=True):
''' '''
Delete books at paths on device. Delete books at paths on device.
@ -774,46 +760,6 @@ class ITUNES(DeviceConfig, DevicePlugin):
''' '''
self.report_progress = report_progress self.report_progress = report_progress
def save_settings(self, settings_widget):
'''
Should save settings to disk. Takes the widget created in config_widget
and saves all settings to disk.
'''
if DEBUG:
self.log.info("ITUNES.save_settings()")
proxy = self._configProxy()
proxy['format_map'] = settings_widget.format_map()
if self.SUPPORTS_SUB_DIRS:
proxy['use_subdirs'] = settings_widget.use_subdirs()
if not self.MUST_READ_METADATA:
proxy['read_metadata'] = settings_widget.read_metadata()
if self.SUPPORTS_USE_AUTHOR_SORT:
proxy['use_author_sort'] = settings_widget.use_author_sort()
if self.EXTRA_CUSTOMIZATION_MESSAGE:
ec = unicode(settings_widget.opt_extra_customization.text()).strip()
if not ec:
ec = None
proxy['extra_customization'] = ec
st = unicode(settings_widget.opt_save_template.text())
proxy['save_template'] = st
# Snag the read_metadata check box contents on the way by
self.use_series_as_category = settings_widget.read_metadata()
def settings(self):
'''
Should return an opts object. The opts object should have one attribute
`format_map` which is an ordered list of formats for the device.
'''
if DEBUG:
self.log.info("ITUNES.settings()")
opts = self._config().parse()
# Repurpose the read_metadata check box
self.use_series_as_category = opts.read_metadata
return opts
def sync_booklists(self, booklists, end_session=True): def sync_booklists(self, booklists, end_session=True):
''' '''
Update metadata on device. Update metadata on device.
@ -1129,27 +1075,6 @@ class ITUNES(DeviceConfig, DevicePlugin):
return db_added, lb_added return db_added, lb_added
def _config(self):
klass = self if isinstance(self, type) else self.__class__
c = Config('device_drivers_%s' % klass.__name__, _('settings for device drivers'))
c.add_opt('format_map', default=self.FORMATS,
help=_('Ordered list of formats the device will accept'))
c.add_opt('use_subdirs', default=True,
help=_('Place files in sub directories if the device supports them'))
c.add_opt('read_metadata', default=True,
help=_('Use Series as Genre in iTunes/iBooks'))
c.add_opt('use_author_sort', default=False,
help=_('Use author sort instead of author'))
c.add_opt('save_template', default=self._default_save_template(),
help=_('Template to control how books are titled in iTunes/iBooks'))
c.add_opt('extra_customization',
default=self.EXTRA_CUSTOMIZATION_DEFAULT,
help=_('Extra customization'))
return c
def _configProxy(self):
return ConfigProxy(self._config())
def _cover_to_thumb(self, path, metadata, db_added, lb_added, format): def _cover_to_thumb(self, path, metadata, db_added, lb_added, format):
''' '''
assumes pythoncom wrapper for db_added assumes pythoncom wrapper for db_added
@ -1300,11 +1225,6 @@ class ITUNES(DeviceConfig, DevicePlugin):
return this_book return this_book
def _default_save_template(self):
from calibre.library.save_to_disk import config
return self.SAVE_TEMPLATE if self.SAVE_TEMPLATE else \
config().parse().send_template
def _delete_iTunesMetadata_plist(self,fpath): def _delete_iTunesMetadata_plist(self,fpath):
''' '''
Delete the plist file from the file to force recache Delete the plist file from the file to force recache
@ -1776,7 +1696,7 @@ class ITUNES(DeviceConfig, DevicePlugin):
im = im.resize((int(width),int(height)), PILImage.ANTIALIAS) im = im.resize((int(width),int(height)), PILImage.ANTIALIAS)
thumb = cStringIO.StringIO() thumb = cStringIO.StringIO()
im.convert('RGB').save(thumb,'JPEG') im.convert('RGB').save(thumb,'JPEG')
thumb_data = thmb.getvalue() thumb_data = thumb.getvalue()
os.remove(tmp_thumb) os.remove(tmp_thumb)
thumb.close() thumb.close()
@ -2510,7 +2430,7 @@ class ITUNES(DeviceConfig, DevicePlugin):
# Set genre from series if available, else first alpha tag # Set genre from series if available, else first alpha tag
# Otherwise iTunes grabs the first dc:subject from the opf metadata # Otherwise iTunes grabs the first dc:subject from the opf metadata
if self.use_series_as_category and metadata.series: if metadata.series and self.settings().read_metadata:
if DEBUG: if DEBUG:
self.log.info(" using Series name as Genre") self.log.info(" using Series name as Genre")
if lb_added: if lb_added:
@ -2581,7 +2501,7 @@ class ITUNES(DeviceConfig, DevicePlugin):
# Otherwise iBooks uses first <dc:subject> from opf # Otherwise iBooks uses first <dc:subject> from opf
# iTunes balks on setting EpisodeNumber, but it sticks (9.1.1.12) # iTunes balks on setting EpisodeNumber, but it sticks (9.1.1.12)
if self.use_series_as_category and metadata.series: if metadata.series and self.settings().read_metadata:
if DEBUG: if DEBUG:
self.log.info(" using Series name as Genre") self.log.info(" using Series name as Genre")
if lb_added: if lb_added:

View File

@ -59,7 +59,7 @@ class DevicePlugin(Plugin):
return cls.__name__ return cls.__name__
return cls.name return cls.name
# Device detection {{{
def test_bcd_windows(self, device_id, bcd): def test_bcd_windows(self, device_id, bcd):
if bcd is None or len(bcd) == 0: if bcd is None or len(bcd) == 0:
return True return True
@ -152,6 +152,7 @@ class DevicePlugin(Plugin):
return True, dev return True, dev
return False, None return False, None
# }}}
def reset(self, key='-1', log_packets=False, report_progress=None, def reset(self, key='-1', log_packets=False, report_progress=None,
detected_device=None) : detected_device=None) :
@ -372,14 +373,12 @@ class DevicePlugin(Plugin):
@classmethod @classmethod
def settings(cls): def settings(cls):
''' '''
Should return an opts object. The opts object should have one attribute Should return an opts object. The opts object should have at least one attribute
`format_map` which is an ordered list of formats for the device. `format_map` which is an ordered list of formats for the device.
''' '''
raise NotImplementedError() raise NotImplementedError()
class BookList(list): class BookList(list):
''' '''
A list of books. Each Book object must have the fields: A list of books. Each Book object must have the fields:

View File

@ -78,9 +78,6 @@ class Device(DeviceConfig, DevicePlugin):
STORAGE_CARD_VOLUME_LABEL = '' STORAGE_CARD_VOLUME_LABEL = ''
STORAGE_CARD2_VOLUME_LABEL = None STORAGE_CARD2_VOLUME_LABEL = None
SUPPORTS_SUB_DIRS = False
MUST_READ_METADATA = False
SUPPORTS_USE_AUTHOR_SORT = False
EBOOK_DIR_MAIN = '' EBOOK_DIR_MAIN = ''
EBOOK_DIR_CARD_A = '' EBOOK_DIR_CARD_A = ''

View File

@ -13,6 +13,10 @@ class DeviceConfig(object):
EXTRA_CUSTOMIZATION_MESSAGE = None EXTRA_CUSTOMIZATION_MESSAGE = None
EXTRA_CUSTOMIZATION_DEFAULT = None EXTRA_CUSTOMIZATION_DEFAULT = None
SUPPORTS_SUB_DIRS = False
MUST_READ_METADATA = False
SUPPORTS_USE_AUTHOR_SORT = False
#: If None the default is used #: If None the default is used
SAVE_TEMPLATE = None SAVE_TEMPLATE = None
@ -23,9 +27,14 @@ class DeviceConfig(object):
config().parse().send_template config().parse().send_template
@classmethod @classmethod
def _config(cls): def _config_base_name(cls):
klass = cls if isinstance(cls, type) else cls.__class__ klass = cls if isinstance(cls, type) else cls.__class__
c = Config('device_drivers_%s' % klass.__name__, _('settings for device drivers')) return klass.__name__
@classmethod
def _config(cls):
name = cls._config_base_name()
c = Config('device_drivers_%s' % name, _('settings for device drivers'))
c.add_opt('format_map', default=cls.FORMATS, c.add_opt('format_map', default=cls.FORMATS,
help=_('Ordered list of formats the device will accept')) help=_('Ordered list of formats the device will accept'))
c.add_opt('use_subdirs', default=True, c.add_opt('use_subdirs', default=True,

View File

@ -127,9 +127,8 @@ class Stylizer(object):
else: else:
head = [] head = []
# Add optional cssutils parsing profile from output_profile # Add cssutils parsing profiles from output_profile
if hasattr(self.opts.output_profile, 'cssutils_addProfile'): for profile in self.opts.output_profile.extra_css_modules:
profile = self.opts.output_profile.cssutils_addProfile
cssutils.profile.addProfile(profile['name'], cssutils.profile.addProfile(profile['name'],
profile['props'], profile['props'],
profile['macros']) profile['macros'])

View File

@ -43,6 +43,9 @@
<property name="wordWrap"> <property name="wordWrap">
<bool>true</bool> <bool>true</bool>
</property> </property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget> </widget>
</item> </item>
<item row="4" column="0"> <item row="4" column="0">

View File

@ -10,7 +10,7 @@ from functools import partial
from binascii import unhexlify from binascii import unhexlify
from PyQt4.Qt import QMenu, QAction, QActionGroup, QIcon, SIGNAL, QPixmap, \ from PyQt4.Qt import QMenu, QAction, QActionGroup, QIcon, SIGNAL, QPixmap, \
Qt, pyqtSignal, QColor, QPainter Qt, pyqtSignal, QColor, QPainter, QDialog
from PyQt4.QtSvg import QSvgRenderer from PyQt4.QtSvg import QSvgRenderer
from calibre.customize.ui import available_input_formats, available_output_formats, \ from calibre.customize.ui import available_input_formats, available_output_formats, \
@ -814,7 +814,8 @@ class DeviceMixin(object): # {{{
if specific: if specific:
d = ChooseFormatDialog(self, _('Choose format to send to device'), d = ChooseFormatDialog(self, _('Choose format to send to device'),
self.device_manager.device.settings().format_map) self.device_manager.device.settings().format_map)
d.exec_() if d.exec_() != QDialog.Accepted:
return
if d.format(): if d.format():
fmt = d.format().lower() fmt = d.format().lower()
dest, sub_dest = dest.split(':') dest, sub_dest = dest.split(':')

View File

@ -39,7 +39,7 @@
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
<property name="standardButtons" > <property name="standardButtons" >
<set>QDialogButtonBox::Ok</set> <set>QDialogButtonBox::Ok|QDialogButtonBox::Cancel</set>
</property> </property>
</widget> </widget>
</item> </item>

View File

@ -56,7 +56,8 @@ class SearchBox2(QComboBox):
To use this class: To use this class:
* Call initialize() * Call initialize()
* Connect to the search() and cleared() signals from this widget * Connect to the search() and cleared() signals from this widget.
* Connect to the cleared() signal to know when the box content changes
* Call search_done() after every search is complete * Call search_done() after every search is complete
* Use clear() to clear back to the help message * Use clear() to clear back to the help message
''' '''
@ -75,6 +76,7 @@ class SearchBox2(QComboBox):
type=Qt.DirectConnection) type=Qt.DirectConnection)
self.line_edit.mouse_released.connect(self.mouse_released, self.line_edit.mouse_released.connect(self.mouse_released,
type=Qt.DirectConnection) type=Qt.DirectConnection)
self.activated.connect(self.history_selected)
self.setEditable(True) self.setEditable(True)
self.help_state = False self.help_state = False
self.as_you_type = True self.as_you_type = True
@ -139,6 +141,9 @@ class SearchBox2(QComboBox):
def key_pressed(self, event): def key_pressed(self, event):
self.normalize_state() self.normalize_state()
if self._in_a_search:
self.emit(SIGNAL('changed()'))
self._in_a_search = False
if event.key() in (Qt.Key_Return, Qt.Key_Enter): if event.key() in (Qt.Key_Return, Qt.Key_Enter):
self.do_search() self.do_search()
self.timer = self.startTimer(self.__class__.INTERVAL) self.timer = self.startTimer(self.__class__.INTERVAL)
@ -154,6 +159,10 @@ class SearchBox2(QComboBox):
self.timer = None self.timer = None
self.do_search() self.do_search()
def history_selected(self, text):
self.emit(SIGNAL('changed()'))
self.do_search()
@property @property
def smart_text(self): def smart_text(self):
text = unicode(self.currentText()).strip() text = unicode(self.currentText()).strip()
@ -345,6 +354,7 @@ class SearchBoxMixin(object):
self.search.initialize('main_search_history', colorize=True, self.search.initialize('main_search_history', colorize=True,
help_text=_('Search (For Advanced Search click the button to the left)')) help_text=_('Search (For Advanced Search click the button to the left)'))
self.connect(self.search, SIGNAL('cleared()'), self.search_box_cleared) self.connect(self.search, SIGNAL('cleared()'), self.search_box_cleared)
self.connect(self.search, SIGNAL('changed()'), self.search_box_changed)
self.connect(self.clear_button, SIGNAL('clicked()'), self.search.clear) self.connect(self.clear_button, SIGNAL('clicked()'), self.search.clear)
QObject.connect(self.advanced_search_button, SIGNAL('clicked(bool)'), QObject.connect(self.advanced_search_button, SIGNAL('clicked(bool)'),
self.do_advanced_search) self.do_advanced_search)
@ -364,6 +374,9 @@ class SearchBoxMixin(object):
self.saved_search.clear_to_help() self.saved_search.clear_to_help()
self.set_number_of_books_shown() self.set_number_of_books_shown()
def search_box_changed(self):
self.tags_view.clear()
def do_advanced_search(self, *args): def do_advanced_search(self, *args):
d = SearchDialog(self) d = SearchDialog(self)
if d.exec_() == QDialog.Accepted: if d.exec_() == QDialog.Accepted:

View File

@ -957,16 +957,19 @@ class LayoutButton(QToolButton):
self.splitter = splitter self.splitter = splitter
splitter.state_changed.connect(self.update_state) splitter.state_changed.connect(self.update_state)
self.setCursor(Qt.PointingHandCursor)
def set_state_to_show(self, *args): def set_state_to_show(self, *args):
self.setChecked(False) self.setChecked(False)
label =_('Show') label =_('Show')
self.setText(label + ' ' + self.label) self.setText(label + ' ' + self.label)
self.setToolTip(self.text())
def set_state_to_hide(self, *args): def set_state_to_hide(self, *args):
self.setChecked(True) self.setChecked(True)
label = _('Hide') label = _('Hide')
self.setText(label + ' ' + self.label) self.setText(label + ' ' + self.label)
self.setToolTip(self.text())
def update_state(self, *args): def update_state(self, *args):
if self.splitter.is_side_index_hidden: if self.splitter.is_side_index_hidden:

View File

@ -585,8 +585,8 @@ class BasicNewsRecipe(Recipe):
self.lrf = options.lrf self.lrf = options.lrf
self.output_profile = options.output_profile self.output_profile = options.output_profile
self.touchscreen = getattr(self.output_profile, 'touchscreen', False) self.touchscreen = getattr(self.output_profile, 'touchscreen', False)
if self.touchscreen and getattr(self.output_profile, 'touchscreen_css',False): if self.touchscreen:
self.extra_css += self.output_profile.touchscreen_css self.template_css += self.output_profile.touchscreen_news_css
self.output_dir = os.path.abspath(self.output_dir) self.output_dir = os.path.abspath(self.output_dir)
if options.test: if options.test:
@ -664,7 +664,8 @@ class BasicNewsRecipe(Recipe):
templ = self.navbar.generate(False, f, a, feed_len, templ = self.navbar.generate(False, f, a, feed_len,
not self.has_single_feed, not self.has_single_feed,
url, __appname__, url, __appname__,
center=self.center_navbar) center=self.center_navbar,
extra_css=self.extra_css)
elem = BeautifulSoup(templ.render(doctype='xhtml').decode('utf-8')).find('div') elem = BeautifulSoup(templ.render(doctype='xhtml').decode('utf-8')).find('div')
body.insert(0, elem) body.insert(0, elem)
if self.remove_javascript: if self.remove_javascript:
@ -728,8 +729,6 @@ class BasicNewsRecipe(Recipe):
timefmt = self.timefmt timefmt = self.timefmt
if self.touchscreen: if self.touchscreen:
templ = templates.TouchscreenIndexTemplate() templ = templates.TouchscreenIndexTemplate()
if getattr(self.output_profile,'timefmt',False):
timefmt = self.output_profile.timefmt
return templ.generate(self.title, "mastheadImage.jpg", timefmt, feeds, return templ.generate(self.title, "mastheadImage.jpg", timefmt, feeds,
extra_css=css).render(doctype='xhtml') extra_css=css).render(doctype='xhtml')