diff --git a/resources/recipes/globes_co_il.recipe b/resources/recipes/globes_co_il.recipe new file mode 100644 index 0000000000..fdbf79f80d --- /dev/null +++ b/resources/recipes/globes_co_il.recipe @@ -0,0 +1,47 @@ +from calibre.web.feeds.news import BasicNewsRecipe +from calibre.ebooks.BeautifulSoup import re + +class AdvancedUserRecipe1283848012(BasicNewsRecipe): + description = 'This is Globes.co.il.' + cover_url = 'http://www.the7eye.org.il/SiteCollectionImages/BAKTANA/arye_avnery_010709_377.jpg' + title = u'Globes' + language = 'he' + __author__ = 'marbs' + extra_css='img {max-width:100%;} body{direction: rtl;max-width:100%;}title{direction: rtl; } article_description{direction: rtl; }, a.article{direction: rtl;max-width:100%;} calibre_feed_description{direction: rtl; }' + simultaneous_downloads = 5 + remove_javascript = True + timefmt = '[%a, %d %b, %Y]' + oldest_article = 1 + max_articles_per_feed = 100 + remove_attributes = ['width','style'] + + + feeds = [(u'שוק ההון', u'http://www.globes.co.il/webservice/rss/rssfeeder.asmx/FeederNode?iID=585'), + (u'נדל"ן', u'http://www.globes.co.il/webservice/rss/rssfeeder.asmx/FeederNode?iID=607'), + (u'וול סטריט ושווקי העולם', u'http://www.globes.co.il/webservice/rss/rssfeeder.asmx/FeederNode?iID=1225'), + (u'ניתוח טכני', u'http://www.globes.co.il/webservice/rss/rssfeeder.asmx/FeederNode?iID=1294'), + (u'היי טק', u'http://www.globes.co.il/webservice/rss/rssfeeder.asmx/FeederNode?iID=594'), + (u'נתח שוק וצרכנות', u'http://www.globes.co.il/webservice/rss/rssfeeder.asmx/FeederNode?iID=821'), + (u'דין וחשבון', u'http://www.globes.co.il/webservice/rss/rssfeeder.asmx/FeederNode?iID=829'), + (u'רכב', u'http://www.globes.co.il/webservice/rss/rssfeeder.asmx/FeederNode?iID=3220'), + (u'דעות', u'http://www.globes.co.il/webservice/rss/rssfeeder.asmx/FeederNode?iID=845'), + (u'קניון המניות - טור שבועי', u'http://www.globes.co.il/webservice/rss/rssfeeder.asmx/FeederNode?iID=3175'), + (u'סביבה', u'http://www.globes.co.il/webservice/rss/rssfeeder.asmx/FeederNode?iID=3221')] + + def print_version(self, url): + split1 = url.split("=") + print_url = 'http://www.globes.co.il/serve/globes/printwindow.asp?did=' + split1[1] + return print_url + + + def preprocess_html(self, soup): + soup.find('tr',attrs={'bgcolor':'black'}).findPrevious('tr').extract() + soup.find('tr',attrs={'bgcolor':'black'}).extract() + return soup + + def fixChars(self,string): + # Replace lsquo (\x91) + fixed = re.sub("■","■",string) + return fixed + + diff --git a/resources/recipes/hannoversche_zeitung.recipe b/resources/recipes/hannoversche_zeitung.recipe new file mode 100644 index 0000000000..8c0da596e5 --- /dev/null +++ b/resources/recipes/hannoversche_zeitung.recipe @@ -0,0 +1,38 @@ +from calibre.web.feeds.news import BasicNewsRecipe + +class AdvancedUserRecipe1287519083(BasicNewsRecipe): + title = u'Hannoversche Allgemeine Zeitung' + oldest_article = 1 + __author__ = 'Artemis' + max_articles_per_feed = 30 + language = 'de' + no_stylesheets = True + + feeds = [ + #(u'Schlagzeilen', u'http://www.haz.de/rss/feed/haz_schlagzeilen'), + (u'Politik', u'http://www.haz.de/rss/feed/haz_politik'), + (u'Wirtschaft', u'http://www.haz.de/rss/feed/haz_wirtschaft'), + (u'Panorama', u'http://www.haz.de/rss/feed/haz_panorama'), + (u'Wissen', u'http://www.haz.de/rss/feed/haz_wissen'), + (u'Kultur', u'http://www.haz.de/rss/feed/haz_kultur'), + (u'Sp\xe4tvorstellung', u'http://www.haz.de/rss/feed/haz_spaetvorstellung'), + (u'Hannover & Region', u'http://www.haz.de/rss/feed/haz_hannoverregion'), + (u'Netzgefl\xfcster', u'http://www.haz.de/rss/feed/haz_netzgefluester'), + (u'Meinung', u'http://www.haz.de/rss/feed/haz_meinung'), + (u'ZiSH', u'http://www.haz.de/rss/feed/haz_zish'), + (u'Medien', u'http://www.haz.de/rss/feed/haz_medien'), + #(u'Sport', u'http://www.haz.de/rss/feed/haz_sport'), + #(u'Hannover 96', u'http://www.haz.de/rss/feed/haz_hannover96') + ] + + remove_tags_before =dict(id='modul_artikel') + remove_tags_after =dict(id='articlecontent') + + remove_tags = dict(id='articlesidebar') + + remove_tags = [ + dict(name='div', attrs={'class':['articlecomment', + 'articlebookmark', 'teaser_anzeige', 'teaser_umfrage', + 'navigation', 'subnavigation']}) + ] + diff --git a/resources/recipes/rds.recipe b/resources/recipes/rds.recipe new file mode 100644 index 0000000000..b77e4804a1 --- /dev/null +++ b/resources/recipes/rds.recipe @@ -0,0 +1,18 @@ +from calibre.web.feeds.news import BasicNewsRecipe + +class AdvancedUserRecipe1290013720(BasicNewsRecipe): + title = u'RDS' + __author__ = 'Nexus' + language = 'en_CA' + description = 'Hockey News' + oldest_article = 7 + max_articles_per_feed = 25 + no_stylesheets = True + remove_tags = [dict(name='div', attrs={'id':'rdsWrap'}), + dict(name='table', attrs={'id':'aVoir'}), + dict(name='div', attrs={'id':'imageChronique'})] + keep_only_tags = [dict(name='div', attrs={'id':['enteteChronique']}), + dict(name='div', attrs={'id':['contenuChronique']})] + + + feeds = [(u'RDS', u'http://www.rds.ca/hockey/fildepresse_rds.xml')] diff --git a/resources/recipes/thn.recipe b/resources/recipes/thn.recipe new file mode 100644 index 0000000000..5e812fbbdf --- /dev/null +++ b/resources/recipes/thn.recipe @@ -0,0 +1,19 @@ +from calibre.web.feeds.news import BasicNewsRecipe + +class AdvancedUserRecipe1289990851(BasicNewsRecipe): + title = u'The Hockey News' + language = 'en_CA' + __author__ = 'Nexus' + oldest_article = 7 + max_articles_per_feed = 25 + no_stylesheets = True + remove_tags = [dict(name='div', attrs={'class':'article_info'}), + dict(name='div', attrs={'class':'photo_details'}), + dict(name='div', attrs={'class':'tool_menu'}), + dict(name='div', attrs={'id':'comments_container'}), + dict(name='div', attrs={'id':'wrapper'})] + keep_only_tags = [dict(name='h1', attrs={'class':['headline']}), + dict(name='div', attrs={'class':['box_container']})] + + feeds = [(u'THN', u'http://www.thehockeynews.com/rss/all_categories.xml')] + diff --git a/src/calibre/gui2/device.py b/src/calibre/gui2/device.py index 8d84f69249..048b6e6235 100644 --- a/src/calibre/gui2/device.py +++ b/src/calibre/gui2/device.py @@ -20,8 +20,7 @@ from calibre.gui2.dialogs.choose_format import ChooseFormatDialog from calibre.utils.ipc.job import BaseJob from calibre.devices.scanner import DeviceScanner from calibre.gui2 import config, error_dialog, Dispatcher, dynamic, \ - warning_dialog, \ - question_dialog, info_dialog, choose_dir + warning_dialog, info_dialog, choose_dir from calibre.ebooks.metadata import authors_to_string from calibre import preferred_encoding, prints, force_unicode from calibre.utils.filenames import ascii_filename @@ -665,6 +664,16 @@ class DeviceMixin(object): # {{{ if tweaks['auto_connect_to_folder']: self.connect_to_folder_named(tweaks['auto_connect_to_folder']) + def auto_convert_question(self, msg, autos): + autos = u'\n'.join(map(unicode, map(force_unicode, autos))) + return self.ask_a_yes_no_question( + _('No suitable formats'), msg, + buttons=QMessageBox.Yes|QMessageBox.Cancel, + ans_when_user_unavailable=True, + det_msg=autos, + show_copy_button=False + ) + def set_default_thumbnail(self, height): img = I('book.png', data=True) self.default_thumbnail = thumbnail(img, height, height) @@ -978,11 +987,9 @@ class DeviceMixin(object): # {{{ bad += auto else: autos = [self.library_view.model().db.title(id, index_is_id=True) for id in auto] - autos = '\n'.join('%s'%i for i in autos) - if question_dialog(self, _('No suitable formats'), + if self.auto_convert_question( _('Auto convert the following books before sending via ' - 'email?'), det_msg=autos, - buttons=QMessageBox.Yes|QMessageBox.Cancel): + 'email?'), autos): self.iactions['Convert Books'].auto_convert_mail(to, fmts, delete_from_library, auto, format) if bad: @@ -1085,11 +1092,9 @@ class DeviceMixin(object): # {{{ break if format is not None: autos = [self.library_view.model().db.title(id, index_is_id=True) for id in auto] - autos = '\n'.join('%s'%i for i in autos) - if question_dialog(self, _('No suitable formats'), + if self.auto_convert_question( _('Auto convert the following books before uploading to ' - 'the device?'), det_msg=autos, - buttons=QMessageBox.Yes|QMessageBox.Cancel): + 'the device?'), autos): self.iactions['Convert Books'].auto_convert_catalogs(auto, format) files = [f for f in files if f is not None] if not files: @@ -1170,11 +1175,9 @@ class DeviceMixin(object): # {{{ break if format is not None: autos = [self.library_view.model().db.title(id, index_is_id=True) for id in auto] - autos = '\n'.join('%s'%i for i in autos) - if question_dialog(self, _('No suitable formats'), + if self.auto_convert_question( _('Auto convert the following books before uploading to ' - 'the device?'), det_msg=autos, - buttons=QMessageBox.Yes|QMessageBox.Cancel): + 'the device?'), autos): self.iactions['Convert Books'].auto_convert_news(auto, format) files = [f for f in files if f is not None] for f in files: @@ -1289,11 +1292,9 @@ class DeviceMixin(object): # {{{ bad += auto else: autos = [self.library_view.model().db.title(id, index_is_id=True) for id in auto] - autos = '\n'.join('%s'%i for i in autos) - if question_dialog(self, _('No suitable formats'), + if self.auto_convert_question( _('Auto convert the following books before uploading to ' - 'the device?'), det_msg=autos, - buttons=QMessageBox.Yes|QMessageBox.Cancel): + 'the device?'), autos): self.iactions['Convert Books'].auto_convert(auto, on_card, format) if bad: diff --git a/src/calibre/gui2/ui.py b/src/calibre/gui2/ui.py index 0ae15b0caa..13bba4f27c 100644 --- a/src/calibre/gui2/ui.py +++ b/src/calibre/gui2/ui.py @@ -26,7 +26,8 @@ from calibre.utils.ipc.server import Server from calibre.library.database2 import LibraryDatabase2 from calibre.customize.ui import interface_actions from calibre.gui2 import error_dialog, GetMetadata, open_local_file, \ - gprefs, max_available_height, config, info_dialog, Dispatcher + gprefs, max_available_height, config, info_dialog, Dispatcher, \ + question_dialog from calibre.gui2.cover_flow import CoverFlowMixin from calibre.gui2.widgets import ProgressIndicator from calibre.gui2.update import UpdateMixin @@ -181,9 +182,8 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{ self.connect(self.donate_action, SIGNAL('triggered(bool)'), self.donate) self.connect(self.restore_action, SIGNAL('triggered()'), self.show_windows) - self.connect(self.system_tray_icon, - SIGNAL('activated(QSystemTrayIcon::ActivationReason)'), - self.system_tray_icon_activated) + self.system_tray_icon.activated.connect( + self.system_tray_icon_activated) ####################### Start spare job server ######################## @@ -250,7 +250,6 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{ self.keyboard_interrupt.connect(self.quit, type=Qt.QueuedConnection) - self.read_settings() self.finalize_layout() if self.tool_bar.showing_donate: @@ -301,6 +300,16 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{ else: self.show_windows() + @property + def is_minimized_to_tray(self): + return getattr(self, '__systray_minimized', False) + + def ask_a_yes_no_question(self, title, msg, **kwargs): + awu = kwargs.pop('ans_when_user_unavailable', True) + if self.is_minimized_to_tray: + return awu + return question_dialog(self, title, msg, **kwargs) + def hide_windows(self): for window in QApplication.topLevelWidgets(): if isinstance(window, (MainWindow, QDialog)) and \ @@ -428,31 +437,34 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{ def job_exception(self, job): if not hasattr(self, '_modeless_dialogs'): self._modeless_dialogs = [] + minz = self.is_minimized_to_tray if self.isVisible(): for x in list(self._modeless_dialogs): if not x.isVisible(): self._modeless_dialogs.remove(x) try: if 'calibre.ebooks.DRMError' in job.details: - d = error_dialog(self, _('Conversion Error'), - _('

Could not convert: %s

It is a ' - 'DRMed book. You must first remove the ' - 'DRM using third party tools.')%\ - (job.description.split(':')[-1], - 'http://bugs.calibre-ebook.com/wiki/DRM')) - d.setModal(False) - d.show() - self._modeless_dialogs.append(d) + if not minz: + d = error_dialog(self, _('Conversion Error'), + _('

Could not convert: %s

It is a ' + 'DRMed book. You must first remove the ' + 'DRM using third party tools.')%\ + (job.description.split(':')[-1], + 'http://bugs.calibre-ebook.com/wiki/DRM')) + d.setModal(False) + d.show() + self._modeless_dialogs.append(d) return if 'calibre.web.feeds.input.RecipeDisabled' in job.details: - msg = job.details - msg = msg[msg.find('calibre.web.feeds.input.RecipeDisabled:'):] - msg = msg.partition(':')[-1] - d = error_dialog(self, _('Recipe Disabled'), - '

%s

'%msg) - d.setModal(False) - d.show() - self._modeless_dialogs.append(d) + if not minz: + msg = job.details + msg = msg[msg.find('calibre.web.feeds.input.RecipeDisabled:'):] + msg = msg.partition(':')[-1] + d = error_dialog(self, _('Recipe Disabled'), + '

%s

'%msg) + d.setModal(False) + d.show() + self._modeless_dialogs.append(d) return except: pass @@ -462,12 +474,13 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{ prints(job.details, file=sys.stderr) except: pass - d = error_dialog(self, _('Conversion Error'), - _('Failed')+': '+unicode(job.description), - det_msg=job.details) - d.setModal(False) - d.show() - self._modeless_dialogs.append(d) + if not minz: + d = error_dialog(self, _('Conversion Error'), + _('Failed')+': '+unicode(job.description), + det_msg=job.details) + d.setModal(False) + d.show() + self._modeless_dialogs.append(d) def read_settings(self): geometry = config['main_window_geometry']