diff --git a/calibre-plugin/config.py b/calibre-plugin/config.py index ce30df12..3b7a50cd 100644 --- a/calibre-plugin/config.py +++ b/calibre-plugin/config.py @@ -19,7 +19,6 @@ from calibre.utils.config import JSONConfig prefs = JSONConfig('plugins/fanfictiondownloader_plugin') # Set defaults -prefs.defaults['hello_world_msg'] = 'Hello, World!' prefs.defaults['personal.ini'] = get_resources('example.ini') class ConfigWidget(QWidget): @@ -29,20 +28,20 @@ class ConfigWidget(QWidget): self.l = QVBoxLayout() self.setLayout(self.l) - self.label = QLabel('Hello world &message:') + self.label = QLabel('personal.ini:') self.l.addWidget(self.label) - self.msg = QLineEdit(self) - self.msg.setText(prefs['hello_world_msg']) - self.l.addWidget(self.msg) - self.label.setBuddy(self.msg) - self.ini = QTextEdit(self) self.ini.setLineWrapMode(QTextEdit.NoWrap) self.ini.setText(prefs['personal.ini']) self.l.addWidget(self.ini) def save_settings(self): - prefs['hello_world_msg'] = unicode(self.msg.text()) - prefs['personal.ini'] = unicode(self.ini.toPlainText()) + ini = unicode(self.ini.toPlainText()) + if ini: + prefs['personal.ini'] = ini + else: + # if they've removed everything, clear it so they get the + # default next time. + del prefs['personal.ini'] diff --git a/calibre-plugin/plugin.py b/calibre-plugin/plugin.py index 3ff5d0e7..8cfa984f 100644 --- a/calibre-plugin/plugin.py +++ b/calibre-plugin/plugin.py @@ -7,22 +7,15 @@ __license__ = 'GPL v3' __copyright__ = '2011, Fanficdownloader team' __docformat__ = 'restructuredtext en' -if False: - # This is here to keep my python error checker from complaining about - # the builtin functions that will be defined by the plugin loading system - # You do not need this code in your plugins - get_icons = get_resources = None - from StringIO import StringIO from PyQt4.Qt import (QDialog, QVBoxLayout, QGridLayout, QPushButton, QMessageBox, - QLabel, QLineEdit, QInputDialog ) -from calibre.ptempfile import PersistentTemporaryFile + QLabel, QLineEdit, QInputDialog, QComboBox ) -from calibre.ebooks.metadata.epub import get_metadata +from calibre.ptempfile import PersistentTemporaryFile +from calibre.ebooks.metadata import MetaInformation from calibre_plugins.fanfictiondownloader_plugin.config import prefs - from calibre_plugins.fanfictiondownloader_plugin.fanficdownloader import adapters,writers,exceptions import ConfigParser @@ -43,32 +36,21 @@ class DemoDialog(QDialog): self.l = QVBoxLayout() self.setLayout(self.l) - self.label = QLabel(prefs['hello_world_msg']) - self.l.addWidget(self.label) - self.setWindowTitle('FanFictionDownLoader') self.setWindowIcon(icon) - self.about_button = QPushButton('About', self) - self.about_button.clicked.connect(self.about) - self.l.addWidget(self.about_button) - - # self.marked_button = QPushButton( - # 'Show books with only one format in the calibre GUI', self) - # self.marked_button.clicked.connect(self.marked) - # self.l.addWidget(self.marked_button) - - # self.view_button = QPushButton( - # 'View the most recently added book', self) - # self.view_button.clicked.connect(self.view) - # self.l.addWidget(self.view_button) - - self.l.addWidget(QLabel('Story &URL:')) - + self.l.addWidget(QLabel('Story URL:')) self.url = QLineEdit(self) - #self.url.setText('http://test1.com?sid=668') + self.url.setText('http://test1.com?sid=12345') self.l.addWidget(self.url) - self.label.setBuddy(self.url) + + self.l.addWidget(QLabel('Output Format:')) + self.format = QComboBox(self) + self.format.addItem('epub') + self.format.addItem('mobi') + self.format.addItem('html') + self.format.addItem('txt') + self.l.addWidget(self.format) self.ffdl_button = QPushButton( 'Download Story', self) @@ -80,6 +62,10 @@ class DemoDialog(QDialog): self.conf_button.clicked.connect(self.config) self.l.addWidget(self.conf_button) + self.about_button = QPushButton('About', self) + self.about_button.clicked.connect(self.about) + self.l.addWidget(self.about_button) + self.resize(self.sizeHint()) def about(self): @@ -96,22 +82,6 @@ class DemoDialog(QDialog): QMessageBox.about(self, 'About the Interface Plugin Demo', text.decode('utf-8')) - # def marked(self): - # fmt_idx = self.db.FIELD_MAP['formats'] - # matched_ids = set() - # for record in self.db.data.iterall(): - # # Iterate over all records - # fmts = record[fmt_idx] - # # fmts is either None or a comma separated list of formats - # if fmts and ',' not in fmts: - # matched_ids.add(record[0]) - # # Mark the records with the matching ids - # self.db.set_marked_ids(matched_ids) - - # # Tell the GUI to search for all marked records - # self.gui.search.setEditText('marked:true') - # self.gui.search.do_search() - def ffdl(self): config = ConfigParser.SafeConfigParser() @@ -119,7 +89,6 @@ class DemoDialog(QDialog): config.readfp(StringIO(prefs['personal.ini'])) print("URL:"+unicode(self.url.text())) adapter = adapters.getAdapter(config,unicode(self.url.text())) - # "http://test1.com?sid=6646") # http://www.fanfiction.net/s/6439390/1/All_Hallows_Eve") # try: adapter.getStoryMetadataOnly() @@ -130,6 +99,9 @@ class DemoDialog(QDialog): if userpass.status: adapter.username = userpass.user.text() adapter.password = userpass.passwd.text() + else: + del adapter + return except exceptions.AdultCheckRequired: adult = QMessageBox.warning(self, 'Are You Adult?', "This story requires that you be an adult. Please confirm you are an adult in your locale:", @@ -138,43 +110,46 @@ class DemoDialog(QDialog): if adult == QMessageBox.Yes: adapter.is_adult=True + else: + del adapter + return +# except exceptions.StoryDoesNotExist - adapter.getStoryMetadataOnly() - - writer = writers.getWriter("epub",config,adapter) - tmp = PersistentTemporaryFile(".epub") + story = adapter.getStoryMetadataOnly() + fileform = unicode(self.format.currentText()) + writer = writers.getWriter(fileform,config,adapter) + tmp = PersistentTemporaryFile("."+fileform) print("tmp: "+tmp.name) writer.writeStory(tmp) - mi = get_metadata(tmp,extract_cover=False) - self.db.add_books([tmp],["EPUB"],[mi]) + + mi = MetaInformation(story.getMetadata("title"), + (story.getMetadata("author"),)) # author is a list. + mi.set_identifiers({'url':story.getMetadata("storyUrl")}) + mi.publisher = story.getMetadata("site") + + mi.tags = writer.getTags() + mi.languages = ['en'] + mi.pubdate = story.getMetadataRaw('datePublished').strftime("%Y-%m-%d") + mi.timestamp = story.getMetadataRaw('dateCreated').strftime("%Y-%m-%d") + mi.comments = story.getMetadata("description") + + self.db.add_books([tmp],[fileform],[mi]) self.hide() - QMessageBox.about(self, 'FFDL Metadata', - str(adapter.getStoryMetadataOnly()).decode('utf-8')) - # def view(self): - # most_recent = most_recent_id = None - # timestamp_idx = self.db.FIELD_MAP['timestamp'] + # Otherwise list of books doesn't update right away. + self.gui.library_view.model().books_added(1) + + # QMessageBox.about(self, 'FFDL Metadata', + # str(adapter.getStoryMetadataOnly()).decode('utf-8')) + del adapter + del writer - # for record in self.db.data: - # # Iterate over all currently showing records - # timestamp = record[timestamp_idx] - # if most_recent is None or timestamp > most_recent: - # most_recent = timestamp - # most_recent_id = record[0] - - # if most_recent_id is not None: - # # Get the row number of the id as shown in the GUI - # row_number = self.db.row(most_recent_id) - # # Get a reference to the View plugin - # view_plugin = self.gui.iactions['View'] - # # Ask the view plugin to launch the viewer for row_number - # view_plugin._view_books([row_number]) def config(self): self.do_user_config(parent=self) # Apply the changes - self.label.setText(prefs['hello_world_msg']) + #self.label.setText(prefs['hello_world_msg']) class UserPassDialog(QDialog): diff --git a/defaults.ini b/defaults.ini index 6da575a9..f791b514 100644 --- a/defaults.ini +++ b/defaults.ini @@ -105,6 +105,10 @@ zip_filename: ${title}-${siteabbrev}_${storyId}${formatext}.zip ## zip_filename. allow_unsafe_filename: false +## entries to make epub subjects and calibre tags +## lastupdate creates two tags: "Last Update Year/Month: %Y/%m" and "Last Update: %Y/%m/%d" +include_subject_tags: extratags, genre, category, characters, lastupdate, status + ## extra tags (comma separated) to include, primarily for epub. extratags: FanFiction @@ -137,10 +141,6 @@ windows_eol: true ## epub is already a zip file. zip_output: false -## entries to make epub subject tags -## lastupdate creates two tags: "Last Update Year/Month: %Y/%m" and "Last Update: %Y/%m/%d" -include_subject_tags: extratags, genre, category, characters, lastupdate, status - ## epub carries the TOC in metadata. ## mobi generated from epub will have a TOC at the end. include_tocpage: false diff --git a/fanficdownloader/writers/base_writer.py b/fanficdownloader/writers/base_writer.py index ad476ced..e01cadff 100644 --- a/fanficdownloader/writers/base_writer.py +++ b/fanficdownloader/writers/base_writer.py @@ -102,6 +102,9 @@ class BaseStoryWriter(Configurable): self.story.setMetadata('formatname',self.getFormatName()) self.story.setMetadata('formatext',self.getFormatExt()) + def getMetadata(self,key): + return stripHTML(self.story.getMetadata(key)) + def getOutputFileName(self): if self.getConfig('zip_output'): return self.getZipFileName() @@ -242,6 +245,22 @@ class BaseStoryWriter(Configurable): if close: outstream.close() + def getTags(self): + # set to avoid duplicates subject tags. + subjectset = set() + for entry in self.validEntries: + if entry in self.getConfigList("include_subject_tags") and \ + entry not in self.story.getLists() and \ + self.story.getMetadata(entry): + subjectset.add(self.getMetadata(entry)) + # listables all go into dc:subject tags, but only if they are configured. + for (name,lst) in self.story.getLists().iteritems(): + if name in self.getConfigList("include_subject_tags"): + for tag in lst: + subjectset.add(tag) + + return subjectset + def writeStoryImpl(self, out): "Must be overriden by sub classes." pass diff --git a/fanficdownloader/writers/writer_epub.py b/fanficdownloader/writers/writer_epub.py index 57424c15..bc163933 100644 --- a/fanficdownloader/writers/writer_epub.py +++ b/fanficdownloader/writers/writer_epub.py @@ -156,9 +156,6 @@ h6 { text-align: center; } ''') - def getMetadata(self,key): - return stripHTML(self.story.getMetadata(key)) - def writeStoryImpl(self, out): ## Python 2.5 ZipFile is rather more primative than later @@ -260,19 +257,7 @@ h6 { text-align: center; } metadata.appendChild(newTag(contentdom,"dc:description",text= self.getMetadata('description'))) - # set to avoid duplicates subject tags. - subjectset = set() - for entry in self.validEntries: - if entry in self.getConfigList("include_subject_tags") and \ - entry not in self.story.getLists() and \ - self.story.getMetadata(entry): - subjectset.add(self.getMetadata(entry)) - # listables all go into dc:subject tags, but only if they are configured. - for (name,lst) in self.story.getLists().iteritems(): - if name in self.getConfigList("include_subject_tags"): - for tag in lst: - subjectset.add(tag) - for subject in subjectset: + for subject in self.getTags(): metadata.appendChild(newTag(contentdom,"dc:subject",text=subject)) diff --git a/fanficdownloader/writers/writer_mobi.py b/fanficdownloader/writers/writer_mobi.py index 87dd30f2..bb141c65 100644 --- a/fanficdownloader/writers/writer_mobi.py +++ b/fanficdownloader/writers/writer_mobi.py @@ -124,9 +124,6 @@ class MobiWriter(BaseStoryWriter): ''') - def getMetadata(self,key): - return stripHTML(self.story.getMetadata(key)) - def writeStoryImpl(self, out): files = []