home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2010 November / maximum-cd-2010-11.iso / DiscContents / calibre-0.7.13.msi / file_1272 (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2010-08-06  |  14.2 KB  |  345 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. from __future__ import with_statement
  5. __license__ = 'GPL v3'
  6. __copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
  7. __docformat__ = 'restructuredtext en'
  8. from datetime import timedelta
  9. from PyQt4.Qt import QDialog, SIGNAL, Qt, QTime, QObject, QMenu, QAction, QIcon, QMutex, QTimer, pyqtSignal
  10. from calibre.gui2.dialogs.scheduler_ui import Ui_Dialog
  11. from calibre.gui2.search_box import SearchBox2
  12. from calibre.gui2 import config as gconf, error_dialog
  13. from calibre.web.feeds.recipes.model import RecipeModel
  14. from calibre.ptempfile import PersistentTemporaryFile
  15. from calibre.utils.date import utcnow
  16. from calibre.utils.network import internet_connected
  17.  
  18. class SchedulerDialog(QDialog, Ui_Dialog):
  19.     
  20.     def __init__(self, recipe_model, parent = None):
  21.         QDialog.__init__(self, parent)
  22.         self.setupUi(self)
  23.         self.recipe_model = recipe_model
  24.         self.recipe_model.do_refresh()
  25.         self.search = SearchBox2(self)
  26.         self.search.setMinimumContentsLength(25)
  27.         self.search.initialize('scheduler_search_history')
  28.         self.recipe_box.layout().insertWidget(0, self.search)
  29.         self.search.search.connect(self.recipe_model.search)
  30.         self.connect(self.recipe_model, SIGNAL('searched(PyQt_PyObject)'), self.search.search_done)
  31.         self.connect(self.recipe_model, SIGNAL('searched(PyQt_PyObject)'), self.search_done)
  32.         self.search.setFocus(Qt.OtherFocusReason)
  33.         self.commit_on_change = True
  34.         self.recipes.setModel(self.recipe_model)
  35.         self.detail_box.setVisible(False)
  36.         self.download_button.setVisible(False)
  37.         self.recipes.currentChanged = self.current_changed
  38.         self.interval_button.setChecked(True)
  39.         self.connect(self.schedule, SIGNAL('stateChanged(int)'), self.toggle_schedule_info)
  40.         self.connect(self.show_password, (SIGNAL('stateChanged(int)'),), (lambda state: None(self.password.setEchoMode if state == Qt.Checked else self.password.Password)))
  41.         self.connect(self.download_button, SIGNAL('clicked()'), self.download_clicked)
  42.         self.connect(self.download_all_button, SIGNAL('clicked()'), self.download_all_clicked)
  43.         self.old_news.setValue(gconf['oldest_news'])
  44.  
  45.     
  46.     def break_cycles(self):
  47.         self.disconnect(self.recipe_model, SIGNAL('searched(PyQt_PyObject)'), self.search_done)
  48.         self.disconnect(self.recipe_model, SIGNAL('searched(PyQt_PyObject)'), self.search.search_done)
  49.         self.search.search.disconnect()
  50.         self.recipe_model = None
  51.  
  52.     
  53.     def search_done(self, *args):
  54.         if self.recipe_model.showing_count < 10:
  55.             self.recipes.expandAll()
  56.         
  57.  
  58.     
  59.     def toggle_schedule_info(self, *args):
  60.         enabled = self.schedule.isChecked()
  61.         for x in ('daily_button', 'day', 'time', 'interval_button', 'interval'):
  62.             getattr(self, x).setEnabled(enabled)
  63.         
  64.         self.last_downloaded.setVisible(enabled)
  65.  
  66.     
  67.     def current_changed(self, current, previous):
  68.         if self.commit_on_change:
  69.             if previous.isValid():
  70.                 if not self.commit(urn = getattr(previous.internalPointer(), 'urn', None)):
  71.                     self.commit_on_change = False
  72.                     self.recipes.setCurrentIndex(previous)
  73.                 
  74.             
  75.         else:
  76.             self.commit_on_change = True
  77.         urn = self.current_urn
  78.         if urn is not None:
  79.             self.initialize_detail_box(urn)
  80.         
  81.  
  82.     
  83.     def accept(self):
  84.         if not self.commit():
  85.             return False
  86.         return QDialog.accept(self)
  87.  
  88.     
  89.     def download_clicked(self):
  90.         self.commit()
  91.         if self.commit() and self.current_urn:
  92.             self.emit(SIGNAL('download(PyQt_PyObject)'), self.current_urn)
  93.         
  94.  
  95.     
  96.     def download_all_clicked(self):
  97.         if self.commit() and self.commit():
  98.             self.emit(SIGNAL('download(PyQt_PyObject)'), None)
  99.         
  100.  
  101.     
  102.     def current_urn(self):
  103.         current = self.recipes.currentIndex()
  104.         if current.isValid():
  105.             return getattr(current.internalPointer(), 'urn', None)
  106.  
  107.     current_urn = property(current_urn)
  108.     
  109.     def commit(self, urn = None):
  110.         urn = None if urn is None else urn
  111.         if not self.detail_box.isVisible() or urn is None:
  112.             return True
  113.         add_title_tag = self.add_title_tag.isChecked()
  114.         custom_tags = unicode(self.custom_tags.text()).strip()
  115.         custom_tags = [ x.strip() for x in custom_tags.split(',') ]
  116.         self.recipe_model.customize_recipe(urn, add_title_tag, custom_tags)
  117.         return True
  118.  
  119.     
  120.     def initialize_detail_box(self, urn):
  121.         self.detail_box.setVisible(True)
  122.         self.download_button.setVisible(True)
  123.         self.detail_box.setCurrentIndex(0)
  124.         recipe = self.recipe_model.recipe_from_urn(urn)
  125.         schedule_info = self.recipe_model.schedule_info_from_urn(urn)
  126.         account_info = self.recipe_model.account_info_from_urn(urn)
  127.         customize_info = self.recipe_model.get_customize_info(urn)
  128.         self.account.setVisible(recipe.get('needs_subscription', '') == 'yes')
  129.         un = pw = ''
  130.         if account_info is not None:
  131.             (un, pw) = account_info[:2]
  132.             if not un:
  133.                 un = ''
  134.             
  135.             if not pw:
  136.                 pw = ''
  137.             
  138.         
  139.         self.username.setText(un)
  140.         self.password.setText(pw)
  141.         self.show_password.setChecked(False)
  142.         self.blurb.setText('\n        <p>\n        <b>%(title)s</b><br>\n        %(cb)s %(author)s<br/>\n        %(description)s\n        </p>\n        ' % dict(title = recipe.get('title'), cb = _('Created by: '), author = recipe.get('author', _('Unknown')), description = recipe.get('description', '')))
  143.         scheduled = schedule_info is not None
  144.         self.schedule.setChecked(scheduled)
  145.         self.toggle_schedule_info()
  146.         self.last_downloaded.setText(_('Last downloaded: never'))
  147.         if scheduled:
  148.             (typ, sch, last_downloaded) = schedule_info
  149.             if typ == 'interval':
  150.                 self.interval_button.setChecked(True)
  151.                 self.interval.setValue(sch)
  152.             elif typ == 'day/time':
  153.                 self.daily_button.setChecked(True)
  154.                 (day, hour, minute) = sch
  155.                 self.day.setCurrentIndex(day + 1)
  156.                 self.time.setTime(QTime(hour, minute))
  157.             
  158.             d = utcnow() - last_downloaded
  159.             
  160.             def hm(x):
  161.                 return ((x - x % 3600) // 3600, (x % 3600 - x % 3600 % 60) // 60)
  162.  
  163.             (hours, minutes) = hm(d.seconds)
  164.             tm = _('%d days, %d hours and %d minutes ago') % (d.days, hours, minutes)
  165.             if d < timedelta(days = 366):
  166.                 self.last_downloaded.setText(_('Last downloaded') + ': ' + tm)
  167.             
  168.         
  169.         (add_title_tag, custom_tags) = customize_info
  170.         self.add_title_tag.setChecked(add_title_tag)
  171.         self.custom_tags.setText(u', '.join(custom_tags))
  172.  
  173.  
  174.  
  175. class Scheduler(QObject):
  176.     INTERVAL = 1
  177.     delete_old_news = pyqtSignal(object)
  178.     start_recipe_fetch = pyqtSignal(object)
  179.     
  180.     def __init__(self, parent, db):
  181.         QObject.__init__(self, parent)
  182.         self.internet_connection_failed = False
  183.         self._parent = parent
  184.         self.recipe_model = RecipeModel(db)
  185.         self.lock = QMutex(QMutex.Recursive)
  186.         self.download_queue = set([])
  187.         self.news_menu = QMenu()
  188.         self.news_icon = QIcon(I('news.svg'))
  189.         self.scheduler_action = QAction(QIcon(I('scheduler.svg')), _('Schedule news download'), self)
  190.         self.news_menu.addAction(self.scheduler_action)
  191.         self.connect(self.scheduler_action, SIGNAL('triggered(bool)'), self.show_dialog)
  192.         self.cac = QAction(QIcon(I('user_profile.svg')), _('Add a custom news source'), self)
  193.         self.connect(self.cac, SIGNAL('triggered(bool)'), self.customize_feeds)
  194.         self.news_menu.addAction(self.cac)
  195.         self.news_menu.addSeparator()
  196.         self.all_action = self.news_menu.addAction(_('Download all scheduled new sources'), self.download_all_scheduled)
  197.         self.timer = QTimer(self)
  198.         self.timer.start(int(self.INTERVAL * 60 * 1000))
  199.         self.oldest_timer = QTimer()
  200.         self.connect(self.oldest_timer, SIGNAL('timeout()'), self.oldest_check)
  201.         self.connect(self.timer, SIGNAL('timeout()'), self.check)
  202.         self.oldest = gconf['oldest_news']
  203.         self.oldest_timer.start(int(3600000))
  204.         QTimer.singleShot(5000, self.oldest_check)
  205.         self.database_changed = self.recipe_model.database_changed
  206.  
  207.     
  208.     def oldest_check(self):
  209.         if self.oldest > 0:
  210.             delta = timedelta(days = self.oldest)
  211.             ids = self.recipe_model.db.tags_older_than(_('News'), delta)
  212.             if ids:
  213.                 ids = list(ids)
  214.                 if ids:
  215.                     self.delete_old_news.emit(ids)
  216.                 
  217.             
  218.         
  219.  
  220.     
  221.     def show_dialog(self, *args):
  222.         self.lock.lock()
  223.         
  224.         try:
  225.             d = SchedulerDialog(self.recipe_model)
  226.             self.connect(d, SIGNAL('download(PyQt_PyObject)'), self.download_clicked)
  227.             d.exec_()
  228.             gconf['oldest_news'] = self.oldest = d.old_news.value()
  229.             d.break_cycles()
  230.         finally:
  231.             self.lock.unlock()
  232.  
  233.  
  234.     
  235.     def customize_feeds(self, *args):
  236.         UserProfiles = UserProfiles
  237.         import calibre.gui2.dialogs.user_profiles
  238.         d = UserProfiles(self._parent, self.recipe_model)
  239.         d.exec_()
  240.         d.break_cycles()
  241.  
  242.     
  243.     def do_download(self, urn):
  244.         self.lock.lock()
  245.         
  246.         try:
  247.             account_info = self.recipe_model.get_account_info(urn)
  248.             customize_info = self.recipe_model.get_customize_info(urn)
  249.             recipe = self.recipe_model.recipe_from_urn(urn)
  250.             un = None
  251.             pw = None
  252.             if account_info is not None:
  253.                 (un, pw) = account_info
  254.             
  255.             (add_title_tag, custom_tags) = customize_info
  256.             script = self.recipe_model.get_recipe(urn)
  257.             pt = PersistentTemporaryFile('_builtin.recipe')
  258.             pt.write(script)
  259.             pt.close()
  260.             arg = {
  261.                 'username': un,
  262.                 'password': pw,
  263.                 'add_title_tag': add_title_tag,
  264.                 'custom_tags': custom_tags,
  265.                 'recipe': pt.name,
  266.                 'title': recipe.get('title', ''),
  267.                 'urn': urn }
  268.             self.download_queue.add(urn)
  269.             self.start_recipe_fetch.emit(arg)
  270.         finally:
  271.             self.lock.unlock()
  272.  
  273.  
  274.     
  275.     def recipe_downloaded(self, arg):
  276.         self.lock.lock()
  277.         
  278.         try:
  279.             self.recipe_model.update_last_downloaded(arg['urn'])
  280.             self.download_queue.remove(arg['urn'])
  281.         finally:
  282.             self.lock.unlock()
  283.  
  284.  
  285.     
  286.     def recipe_download_failed(self, arg):
  287.         self.lock.lock()
  288.         
  289.         try:
  290.             self.recipe_model.update_last_downloaded(arg['urn'])
  291.             self.download_queue.remove(arg['urn'])
  292.         finally:
  293.             self.lock.unlock()
  294.  
  295.  
  296.     
  297.     def download_clicked(self, urn):
  298.         if urn is not None:
  299.             return self.download(urn)
  300.         for urn in self.recipe_model.scheduled_urns():
  301.             if not self.download(urn):
  302.                 break
  303.                 continue
  304.             urn is not None
  305.         
  306.  
  307.     
  308.     def download_all_scheduled(self):
  309.         self.download_clicked(None)
  310.  
  311.     
  312.     def download(self, urn):
  313.         self.lock.lock()
  314.         if not internet_connected():
  315.             if not self.internet_connection_failed:
  316.                 self.internet_connection_failed = True
  317.                 d = error_dialog(self._parent, _('No internet connection'), _('Cannot download news as no internet connection is active'))
  318.                 d.setModal(False)
  319.                 d.show()
  320.             
  321.             return False
  322.         self.internet_connection_failed = False
  323.         doit = urn not in self.download_queue
  324.         self.lock.unlock()
  325.         if doit:
  326.             self.do_download(urn)
  327.         
  328.         return True
  329.  
  330.     
  331.     def check(self):
  332.         recipes = self.recipe_model.get_to_be_downloaded_recipes()
  333.         for urn in recipes:
  334.             self.download(urn)
  335.         
  336.  
  337.  
  338. if __name__ == '__main__':
  339.     from calibre.gui2 import is_ok_to_use_qt
  340.     is_ok_to_use_qt()
  341.     from calibre.library.database2 import LibraryDatabase2
  342.     d = SchedulerDialog(RecipeModel(LibraryDatabase2('/home/kovid/documents/library')))
  343.     d.exec_()
  344.  
  345.