mirror of
https://github.com/JimmXinu/FanFicFare.git
synced 2025-12-24 01:33:39 +01:00
WIP - ini edit, error check and syntax highlighting.
This commit is contained in:
parent
4deeaa4cac
commit
f1e9081c8c
6 changed files with 457 additions and 221 deletions
64
calibre-plugin/basicinihighlighter.py
Normal file
64
calibre-plugin/basicinihighlighter.py
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
#!/usr/bin/env python
|
||||
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
|
||||
from __future__ import (unicode_literals, division,
|
||||
print_function)
|
||||
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2014, Jim Miller'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import re
|
||||
|
||||
try:
|
||||
from PyQt5.Qt import (Qt, QSyntaxHighlighter, QTextCharFormat, QBrush)
|
||||
except ImportError as e:
|
||||
from PyQt4.Qt import (Qt, QSyntaxHighlighter, QTextCharFormat, QBrush)
|
||||
|
||||
class BasicIniHighlighter(QSyntaxHighlighter):
|
||||
'''
|
||||
QSyntaxHighlighter class for use with QTextEdit for highlighting
|
||||
ini config files.
|
||||
|
||||
I looked high and low to find a high lighter for basic ini config
|
||||
format, so I'm leaving this in the project even though I'm not
|
||||
using.
|
||||
'''
|
||||
|
||||
def __init__( self, parent, theme ):
|
||||
QSyntaxHighlighter.__init__( self, parent )
|
||||
self.parent = parent
|
||||
|
||||
self.highlightingRules = []
|
||||
|
||||
# keyword
|
||||
self.highlightingRules.append( HighlightingRule( r"^[^:=\s][^:=]*[:=]",
|
||||
Qt.blue,
|
||||
Qt.SolidPattern ) )
|
||||
|
||||
# section
|
||||
self.highlightingRules.append( HighlightingRule( r"^\[[^\]]+\]",
|
||||
Qt.darkBlue,
|
||||
Qt.SolidPattern ) )
|
||||
|
||||
# comment
|
||||
self.highlightingRules.append( HighlightingRule( r"#[^\n]*" ,
|
||||
Qt.darkYellow,
|
||||
Qt.SolidPattern ) )
|
||||
|
||||
def highlightBlock( self, text ):
|
||||
for rule in self.highlightingRules:
|
||||
for match in rule.pattern.finditer(text):
|
||||
self.setFormat( match.start(), match.end()-match.start(), rule.highlight )
|
||||
self.setCurrentBlockState( 0 )
|
||||
|
||||
class HighlightingRule():
|
||||
def __init__( self, pattern, color, style ):
|
||||
if isinstance(pattern,basestring):
|
||||
self.pattern = re.compile(pattern)
|
||||
else:
|
||||
self.pattern=pattern
|
||||
charfmt = QTextCharFormat()
|
||||
brush = QBrush(color, style)
|
||||
charfmt.setForeground(brush)
|
||||
self.highlight = charfmt
|
||||
|
||||
|
|
@ -13,8 +13,6 @@ logger = logging.getLogger(__name__)
|
|||
import traceback, copy, threading
|
||||
from collections import OrderedDict
|
||||
|
||||
from ConfigParser import ParsingError
|
||||
|
||||
try:
|
||||
from PyQt5.Qt import (QDialog, QWidget, QVBoxLayout, QHBoxLayout, QLabel,
|
||||
QLineEdit, QFont, QWidget, QTextEdit, QComboBox,
|
||||
|
|
@ -75,7 +73,7 @@ no_trans = { 'pini':'personal.ini',
|
|||
from calibre_plugins.fanfictiondownloader_plugin.prefs import prefs, PREFS_NAMESPACE
|
||||
from calibre_plugins.fanfictiondownloader_plugin.dialogs \
|
||||
import (UPDATE, UPDATEALWAYS, collision_order, save_collisions, RejectListDialog,
|
||||
EditTextDialog, RejectUrlEntry, errors_dialog)
|
||||
EditTextDialog, IniTextDialog, RejectUrlEntry, errors_dialog)
|
||||
|
||||
from calibre_plugins.fanfictiondownloader_plugin.fanficdownloader.adapters \
|
||||
import getConfigSections
|
||||
|
|
@ -83,7 +81,8 @@ from calibre_plugins.fanfictiondownloader_plugin.fanficdownloader.adapters \
|
|||
from calibre_plugins.fanfictiondownloader_plugin.common_utils \
|
||||
import ( KeyboardConfigDialog, PrefsViewerDialog )
|
||||
|
||||
from calibre_plugins.fanfictiondownloader_plugin.ffdl_util import (get_ffdl_config)
|
||||
from calibre_plugins.fanfictiondownloader_plugin.ffdl_util \
|
||||
import (test_config)
|
||||
|
||||
from calibre.gui2.complete2 import EditWithComplete #MultiCompleteLineEdit
|
||||
|
||||
|
|
@ -566,8 +565,7 @@ class BasicTab(QWidget):
|
|||
title=_("Reject Reasons"),
|
||||
label=_("Customize Reject List Reasons"),
|
||||
tooltip=_("Customize the Reasons presented when Rejecting URLs"),
|
||||
save_size_name='ffdl:Reject List Reasons',
|
||||
use_find=True)
|
||||
save_size_name='ffdl:Reject List Reasons')
|
||||
d.exec_()
|
||||
if d.result() == d.Accepted:
|
||||
prefs['rejectreasons'] = d.get_plain_text()
|
||||
|
|
@ -632,7 +630,7 @@ class PersonalIniTab(QWidget):
|
|||
# let edit box fill the space.
|
||||
|
||||
def show_defaults(self):
|
||||
EditTextDialog(self,
|
||||
IniTextDialog(self,
|
||||
get_resources('plugin-defaults.ini'),
|
||||
icon=self.windowIcon(),
|
||||
title=_('Plugin Defaults'),
|
||||
|
|
@ -643,7 +641,7 @@ class PersonalIniTab(QWidget):
|
|||
save_size_name='ffdl:defaults.ini').exec_()
|
||||
|
||||
def add_ini_button(self):
|
||||
d = EditTextDialog(self,
|
||||
d = IniTextDialog(self,
|
||||
self.personalini,
|
||||
icon=self.windowIcon(),
|
||||
title=_("Edit personal.ini"),
|
||||
|
|
@ -658,13 +656,7 @@ class PersonalIniTab(QWidget):
|
|||
if d.result() == d.Accepted:
|
||||
self.personalini = unicode(d.get_plain_text())
|
||||
|
||||
try:
|
||||
configini = get_ffdl_config("test1.com?sid=555",
|
||||
personalini=self.personalini)
|
||||
|
||||
errors = configini.test_config()
|
||||
except ParsingError as pe:
|
||||
errors = pe.errors
|
||||
errors = test_config(self.personalini)
|
||||
|
||||
if errors:
|
||||
error = not errors_dialog(self.plugin_action.gui,
|
||||
|
|
|
|||
|
|
@ -7,9 +7,6 @@ __license__ = 'GPL v3'
|
|||
__copyright__ = '2014, Jim Miller'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
import traceback, re
|
||||
from functools import partial
|
||||
|
||||
|
|
@ -28,8 +25,7 @@ try:
|
|||
QPushButton, QFont, QLabel, QCheckBox, QIcon, QLineEdit,
|
||||
QComboBox, QProgressDialog, QTimer, QDialogButtonBox,
|
||||
QPixmap, Qt, QAbstractItemView, QTextEdit, pyqtSignal,
|
||||
QGroupBox, QFrame, QTextBrowser, QSize, QAction,
|
||||
QSyntaxHighlighter, QTextCharFormat, QBrush )
|
||||
QGroupBox, QFrame, QTextBrowser, QSize, QAction)
|
||||
except ImportError as e:
|
||||
from PyQt4 import QtGui
|
||||
from PyQt4 import QtCore
|
||||
|
|
@ -37,8 +33,7 @@ except ImportError as e:
|
|||
QPushButton, QFont, QLabel, QCheckBox, QIcon, QLineEdit,
|
||||
QComboBox, QProgressDialog, QTimer, QDialogButtonBox,
|
||||
QPixmap, Qt, QAbstractItemView, QTextEdit, pyqtSignal,
|
||||
QGroupBox, QFrame, QTextBrowser, QSize, QAction, QtCore,
|
||||
QSyntaxHighlighter, QTextCharFormat, QBrush )
|
||||
QGroupBox, QFrame, QTextBrowser, QSize, QAction)
|
||||
|
||||
try:
|
||||
from calibre.gui2 import QVariant
|
||||
|
|
@ -72,6 +67,12 @@ from calibre_plugins.fanfictiondownloader_plugin.common_utils \
|
|||
from calibre_plugins.fanfictiondownloader_plugin.fanficdownloader.geturls import get_urls_from_html, get_urls_from_text
|
||||
from calibre_plugins.fanfictiondownloader_plugin.fanficdownloader.adapters import getNormalStoryURL
|
||||
|
||||
from calibre_plugins.fanfictiondownloader_plugin.fanficdownloader.configurable \
|
||||
import (get_valid_sections, get_valid_entries,
|
||||
get_valid_keywords, get_valid_entry_keywords)
|
||||
|
||||
from inihighlighter import IniHighlighter
|
||||
|
||||
SKIP=_('Skip')
|
||||
ADDNEW=_('Add New Book')
|
||||
UPDATE=_('Update EPUB if New Chapters')
|
||||
|
|
@ -1120,15 +1121,73 @@ class EditTextDialog(SizePersistedDialog):
|
|||
def __init__(self, parent, text,
|
||||
icon=None, title=None, label=None, tooltip=None,
|
||||
rejectreasons=[],reasonslabel=None,
|
||||
save_size_name='ffdl:edit text dialog',
|
||||
):
|
||||
SizePersistedDialog.__init__(self, parent, save_size_name)
|
||||
|
||||
self.l = QVBoxLayout()
|
||||
self.setLayout(self.l)
|
||||
self.label = QLabel(label)
|
||||
if title:
|
||||
self.setWindowTitle(title)
|
||||
if icon:
|
||||
self.setWindowIcon(icon)
|
||||
self.l.addWidget(self.label)
|
||||
|
||||
self.textedit = QTextEdit(self)
|
||||
self.textedit.setLineWrapMode(QTextEdit.NoWrap)
|
||||
self.textedit.setText(text)
|
||||
self.l.addWidget(self.textedit)
|
||||
|
||||
if tooltip:
|
||||
self.label.setToolTip(tooltip)
|
||||
self.textedit.setToolTip(tooltip)
|
||||
|
||||
if rejectreasons or reasonslabel:
|
||||
self.reason_edit = EditWithComplete(self,sort_func=lambda x:1)
|
||||
|
||||
items = ['']+rejectreasons
|
||||
self.reason_edit.update_items_cache(items)
|
||||
self.reason_edit.show_initial_value('')
|
||||
self.reason_edit.set_separator(None)
|
||||
self.reason_edit.setToolTip(reasonslabel)
|
||||
|
||||
if reasonslabel:
|
||||
horz = QHBoxLayout()
|
||||
label = QLabel(reasonslabel)
|
||||
label.setToolTip(reasonslabel)
|
||||
horz.addWidget(label)
|
||||
horz.addWidget(self.reason_edit)
|
||||
self.l.addLayout(horz)
|
||||
else:
|
||||
self.l.addWidget(self.reason_edit)
|
||||
|
||||
button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
|
||||
button_box.accepted.connect(self.accept)
|
||||
button_box.rejected.connect(self.reject)
|
||||
self.l.addWidget(button_box)
|
||||
|
||||
# Cause our dialog size to be restored from prefs or created on first usage
|
||||
self.resize_dialog()
|
||||
|
||||
def get_plain_text(self):
|
||||
return unicode(self.textedit.toPlainText())
|
||||
|
||||
def get_reason_text(self):
|
||||
return unicode(self.reason_edit.currentText()).strip()
|
||||
|
||||
class IniTextDialog(SizePersistedDialog):
|
||||
|
||||
def __init__(self, parent, text,
|
||||
icon=None, title=None, label=None, tooltip=None,
|
||||
use_find=False,
|
||||
read_only=False,
|
||||
save_size_name='ffdl:edit text dialog',
|
||||
save_size_name='ffdl:ini text dialog',
|
||||
):
|
||||
SizePersistedDialog.__init__(self, parent, save_size_name)
|
||||
|
||||
self.keys=dict()
|
||||
|
||||
#self.resize(600, 500)
|
||||
self.l = QVBoxLayout()
|
||||
self.setLayout(self.l)
|
||||
self.label = QLabel(label)
|
||||
|
|
@ -1140,7 +1199,12 @@ class EditTextDialog(SizePersistedDialog):
|
|||
|
||||
self.textedit = QTextEdit(self)
|
||||
|
||||
highlighter = IniHighlighter(self.textedit, "Classic")
|
||||
highlighter = IniHighlighter(self.textedit,
|
||||
sections=get_valid_sections(),
|
||||
keywords=get_valid_keywords(),
|
||||
entries=get_valid_entries(),
|
||||
entry_keywords=get_valid_entry_keywords(),
|
||||
)
|
||||
|
||||
self.textedit.setLineWrapMode(QTextEdit.NoWrap)
|
||||
try:
|
||||
|
|
@ -1193,25 +1257,6 @@ class EditTextDialog(SizePersistedDialog):
|
|||
self.label.setToolTip(tooltip)
|
||||
self.textedit.setToolTip(tooltip)
|
||||
|
||||
if rejectreasons or reasonslabel:
|
||||
self.reason_edit = EditWithComplete(self,sort_func=lambda x:1)
|
||||
|
||||
items = ['']+rejectreasons
|
||||
self.reason_edit.update_items_cache(items)
|
||||
self.reason_edit.show_initial_value('')
|
||||
self.reason_edit.set_separator(None)
|
||||
self.reason_edit.setToolTip(reasonslabel)
|
||||
|
||||
if reasonslabel:
|
||||
horz = QHBoxLayout()
|
||||
label = QLabel(reasonslabel)
|
||||
label.setToolTip(reasonslabel)
|
||||
horz.addWidget(label)
|
||||
horz.addWidget(self.reason_edit)
|
||||
self.l.addLayout(horz)
|
||||
else:
|
||||
self.l.addWidget(self.reason_edit)
|
||||
|
||||
button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
|
||||
button_box.accepted.connect(self.accept)
|
||||
button_box.rejected.connect(self.reject)
|
||||
|
|
@ -1238,9 +1283,6 @@ class EditTextDialog(SizePersistedDialog):
|
|||
def get_plain_text(self):
|
||||
return unicode(self.textedit.toPlainText())
|
||||
|
||||
def get_reason_text(self):
|
||||
return unicode(self.reason_edit.currentText()).strip()
|
||||
|
||||
def findFocus(self):
|
||||
# print("findFocus called")
|
||||
self.findField.setFocus()
|
||||
|
|
@ -1248,7 +1290,7 @@ class EditTextDialog(SizePersistedDialog):
|
|||
|
||||
def find(self):
|
||||
|
||||
print("find self.lastStart:%s"%self.lastStart)
|
||||
#print("find self.lastStart:%s"%self.lastStart)
|
||||
|
||||
# Grab the parent's text
|
||||
text = self.textedit.toPlainText()
|
||||
|
|
@ -1328,117 +1370,3 @@ class ViewLog(QDialog):
|
|||
txt = self.tb.toPlainText()
|
||||
QApplication.clipboard().setText(txt)
|
||||
|
||||
class IniHighlighter(QSyntaxHighlighter):
|
||||
|
||||
def __init__( self, parent, theme ):
|
||||
QSyntaxHighlighter.__init__( self, parent )
|
||||
self.parent = parent
|
||||
keyword = QTextCharFormat()
|
||||
reservedClasses = QTextCharFormat()
|
||||
assignmentOperator = QTextCharFormat()
|
||||
delimiter = QTextCharFormat()
|
||||
specialConstant = QTextCharFormat()
|
||||
boolean = QTextCharFormat()
|
||||
number = QTextCharFormat()
|
||||
comment = QTextCharFormat()
|
||||
string = QTextCharFormat()
|
||||
singleQuotedString = QTextCharFormat()
|
||||
|
||||
self.highlightingRules = []
|
||||
|
||||
# # keyword
|
||||
# brush = QBrush( Qt.darkBlue, Qt.SolidPattern )
|
||||
# keyword.setForeground( brush )
|
||||
# keyword.setFontWeight( QFont.Bold )
|
||||
# keywords = [ "break", "else", "for", "if", "in",
|
||||
# "next", "repeat", "return", "switch",
|
||||
# "try", "while" ]
|
||||
# for word in keywords:
|
||||
# pattern = "\\b" + word + "\\b"
|
||||
# rule = HighlightingRule( pattern, keyword )
|
||||
# self.highlightingRules.append( rule )
|
||||
|
||||
# # reservedClasses
|
||||
# reservedClasses.setForeground( brush )
|
||||
# reservedClasses.setFontWeight( QFont.Bold )
|
||||
# keywords = [ "array", "character", "complex",
|
||||
# "data.frame", "double", "factor",
|
||||
# "function", "integer", "list",
|
||||
# "logical", "matrix", "numeric",
|
||||
# "vector" ]
|
||||
# for word in keywords:
|
||||
# pattern = "\\b" + word + "\\b"
|
||||
# rule = HighlightingRule( pattern, reservedClasses )
|
||||
# self.highlightingRules.append( rule )
|
||||
|
||||
# # assignmentOperator
|
||||
# brush = QBrush( Qt.yellow, Qt.SolidPattern )
|
||||
# pattern = "(<){1,2}-"
|
||||
# assignmentOperator.setForeground( brush )
|
||||
# assignmentOperator.setFontWeight( QFont.Bold )
|
||||
# rule = HighlightingRule( pattern, assignmentOperator )
|
||||
# self.highlightingRules.append( rule )
|
||||
|
||||
# section
|
||||
pattern = r"^\[[^\]]+\]"
|
||||
brush = QBrush( Qt.darkBlue, Qt.SolidPattern )
|
||||
delimiter.setForeground( brush )
|
||||
delimiter.setFontWeight( QFont.Bold )
|
||||
rule = HighlightingRule( pattern, delimiter )
|
||||
self.highlightingRules.append( rule )
|
||||
|
||||
# # specialConstant
|
||||
# brush = QBrush( Qt.green, Qt.SolidPattern )
|
||||
# specialConstant.setForeground( brush )
|
||||
# keywords = [ "Inf", "NA", "NaN", "NULL" ]
|
||||
# for word in keywords:
|
||||
# pattern = "\\b" + word + "\\b"
|
||||
# rule = HighlightingRule( pattern, specialConstant )
|
||||
# self.highlightingRules.append( rule )
|
||||
|
||||
# boolean, case insensitive
|
||||
boolean.setForeground( brush )
|
||||
pattern = r"\b(true|false)\b"
|
||||
rule = HighlightingRule( pattern, boolean )
|
||||
self.highlightingRules.append( rule )
|
||||
|
||||
# # number
|
||||
# pattern = "[-+]?[0-9]*\.?[0-9]+?([eE][-+]?[0-9]+?)?"
|
||||
# number.setForeground( brush )
|
||||
# rule = HighlightingRule( pattern, number )
|
||||
# self.highlightingRules.append( rule )
|
||||
|
||||
# comment
|
||||
brush = QBrush( Qt.darkGray, Qt.SolidPattern )
|
||||
pattern = "#[^\n]*"
|
||||
comment.setForeground( brush )
|
||||
rule = HighlightingRule( pattern, comment )
|
||||
self.highlightingRules.append( rule )
|
||||
|
||||
# string
|
||||
brush = QBrush( Qt.red, Qt.SolidPattern )
|
||||
pattern = "\".*?\""
|
||||
string.setForeground( brush )
|
||||
rule = HighlightingRule( pattern, string )
|
||||
self.highlightingRules.append( rule )
|
||||
|
||||
# singleQuotedString
|
||||
pattern = "\'.*?\'"
|
||||
singleQuotedString.setForeground( brush )
|
||||
rule = HighlightingRule( pattern, singleQuotedString )
|
||||
self.highlightingRules.append( rule )
|
||||
|
||||
def highlightBlock( self, text ):
|
||||
for rule in self.highlightingRules:
|
||||
for match in rule.pattern.finditer(text):
|
||||
self.setFormat( match.start(), match.end()-match.start(), rule.format )
|
||||
self.setCurrentBlockState( 0 )
|
||||
|
||||
class HighlightingRule():
|
||||
def __init__( self, pattern, format ):
|
||||
if isinstance(pattern,basestring):
|
||||
self.pattern = re.compile(pattern)
|
||||
else:
|
||||
self.pattern=pattern
|
||||
self.format = format
|
||||
|
||||
|
|
|
|||
|
|
@ -8,10 +8,11 @@ __copyright__ = '2013, Jim Miller'
|
|||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
from StringIO import StringIO
|
||||
from ConfigParser import ParsingError
|
||||
|
||||
from calibre_plugins.fanfictiondownloader_plugin.fanficdownloader import adapters, exceptions
|
||||
from calibre_plugins.fanfictiondownloader_plugin.fanficdownloader.configurable import Configuration
|
||||
from calibre_plugins.fanfictiondownloader_plugin.prefs import (prefs)
|
||||
from calibre_plugins.fanfictiondownloader_plugin.prefs import prefs
|
||||
|
||||
def get_ffdl_personalini():
|
||||
if prefs['includeimages']:
|
||||
|
|
@ -40,4 +41,15 @@ def get_ffdl_config(url,fileform="epub",personalini=None):
|
|||
|
||||
def get_ffdl_adapter(url,fileform="epub",personalini=None):
|
||||
return adapters.getAdapter(get_ffdl_config(url,fileform,personalini),url)
|
||||
|
||||
def test_config(initext):
|
||||
|
||||
configini = get_ffdl_config("test1.com?sid=555",
|
||||
personalini=initext)
|
||||
try:
|
||||
errors = configini.test_config()
|
||||
except ParsingError as pe:
|
||||
errors = pe.errors
|
||||
|
||||
return errors
|
||||
|
||||
|
|
|
|||
115
calibre-plugin/inihighlighter.py
Normal file
115
calibre-plugin/inihighlighter.py
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
#!/usr/bin/env python
|
||||
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
|
||||
from __future__ import (unicode_literals, division,
|
||||
print_function)
|
||||
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2014, Jim Miller'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import re
|
||||
|
||||
try:
|
||||
from PyQt5.Qt import (Qt, QSyntaxHighlighter, QTextCharFormat, QBrush, QFont)
|
||||
except ImportError as e:
|
||||
from PyQt4.Qt import (Qt, QSyntaxHighlighter, QTextCharFormat, QBrush, QFont)
|
||||
|
||||
# r'add_to_+key
|
||||
|
||||
|
||||
|
||||
class IniHighlighter(QSyntaxHighlighter):
|
||||
'''
|
||||
QSyntaxHighlighter class for use with QTextEdit for highlighting
|
||||
ini config files.
|
||||
'''
|
||||
|
||||
def __init__( self, parent, sections=[], keywords=[], entries=[], entry_keywords=[] ):
|
||||
QSyntaxHighlighter.__init__( self, parent )
|
||||
self.parent = parent
|
||||
|
||||
self.highlightingRules = []
|
||||
|
||||
# *all* keywords -- change known later.
|
||||
self.errorRule = HighlightingRule( r"^[^:=\s][^:=]*[:=]", Qt.red )
|
||||
self.highlightingRules.append( self.errorRule )
|
||||
|
||||
# *all* entry keywords -- change known later.
|
||||
reentrykeywords = r'('+(r'|'.join([ e % r'[a-zA-Z0-9_]+' for e in entry_keywords ]))+r')'
|
||||
self.highlightingRules.append( HighlightingRule( r"^(add_to_)?"+reentrykeywords+r"\s*[:=]", Qt.darkMagenta ) )
|
||||
|
||||
# true/false -- just to be nice.
|
||||
self.highlightingRules.append( HighlightingRule( r"\b(true|false)\b", Qt.darkGreen ) )
|
||||
|
||||
if entries:
|
||||
# *known* entries
|
||||
reentries = r'('+(r'|'.join(entries))+r')'
|
||||
self.highlightingRules.append( HighlightingRule( r"\b"+reentries+r"\b", Qt.darkGreen ) )
|
||||
|
||||
# *known* entry keywords
|
||||
reentrykeywords = r'('+(r'|'.join([ e % reentries for e in entry_keywords ]))+r')'
|
||||
self.highlightingRules.append( HighlightingRule( r"^(add_to_)?"+reentrykeywords+r"\s*[:=]", Qt.blue ) )
|
||||
|
||||
# *known* keywords
|
||||
rekeywords = r'('+(r'|'.join(keywords))+r')'
|
||||
self.highlightingRules.append( HighlightingRule( r"^(add_to_)?"+rekeywords+r"\s*[:=]", Qt.blue ) )
|
||||
|
||||
# *all* sections -- change known later.
|
||||
self.highlightingRules.append( HighlightingRule( r"^\[[^\]]+\].*?$", Qt.red, QFont.Bold, blocknum=1 ) )
|
||||
|
||||
if sections:
|
||||
# *known* sections
|
||||
resections = r'('+(r'|'.join(sections))+r')'
|
||||
resections = resections.replace('.','\.') #escape dots.
|
||||
self.highlightingRules.append( HighlightingRule( r"^\["+resections+r"\]\s*$", Qt.darkBlue, QFont.Bold, blocknum=2 ) )
|
||||
|
||||
# test story sections
|
||||
self.teststoryRule = HighlightingRule( r"^\[teststory:([0-9]+|defaults)\]", Qt.darkCyan, blocknum=3 )
|
||||
self.highlightingRules.append( self.teststoryRule )
|
||||
|
||||
# NOT comments -- but can be custom columns, so don't flag.
|
||||
#self.highlightingRules.append( HighlightingRule( r"(?<!^)#[^\n]*" , Qt.red ) )
|
||||
|
||||
# comments -- comments must start from column 0.
|
||||
self.commentRule = HighlightingRule( r"^#[^\n]*" , Qt.darkYellow )
|
||||
self.highlightingRules.append( self.commentRule )
|
||||
|
||||
def highlightBlock( self, text ):
|
||||
|
||||
is_comment = False
|
||||
blocknum = self.previousBlockState()
|
||||
for rule in self.highlightingRules:
|
||||
for match in rule.pattern.finditer(text):
|
||||
self.setFormat( match.start(), match.end()-match.start(), rule.highlight )
|
||||
if rule == self.commentRule:
|
||||
is_comment = True
|
||||
if rule.blocknum > 0:
|
||||
blocknum = rule.blocknum
|
||||
|
||||
if not is_comment:
|
||||
# unknown section, error all:
|
||||
if blocknum == 1 and blocknum == self.previousBlockState():
|
||||
self.setFormat( 0, len(text), self.errorRule.highlight )
|
||||
|
||||
# teststory section rules:
|
||||
if blocknum == 3:
|
||||
self.setFormat( 0, len(text), self.teststoryRule.highlight )
|
||||
|
||||
self.setCurrentBlockState( blocknum )
|
||||
|
||||
class HighlightingRule():
|
||||
def __init__( self, pattern, color,
|
||||
weight=QFont.Normal,
|
||||
style=Qt.SolidPattern,
|
||||
blocknum=0):
|
||||
if isinstance(pattern,basestring):
|
||||
self.pattern = re.compile(pattern)
|
||||
else:
|
||||
self.pattern=pattern
|
||||
charfmt = QTextCharFormat()
|
||||
brush = QBrush(color, style)
|
||||
charfmt.setForeground(brush)
|
||||
charfmt.setFontWeight(weight)
|
||||
self.highlight = charfmt
|
||||
self.blocknum=blocknum
|
||||
|
||||
|
|
@ -35,31 +35,30 @@ from ConfigParser import DEFAULTSECT, MissingSectionHeaderError, ParsingError
|
|||
|
||||
import adapters
|
||||
|
||||
class Configuration(ConfigParser.SafeConfigParser):
|
||||
|
||||
def __init__(self, site, fileform):
|
||||
ConfigParser.SafeConfigParser.__init__(self)
|
||||
|
||||
self.linenos=dict() # key by section or section,key -> lineno
|
||||
|
||||
self.sectionslist = ['defaults']
|
||||
|
||||
if site.startswith("www."):
|
||||
sitewith = site
|
||||
sitewithout = site.replace("www.","")
|
||||
def get_valid_sections():
|
||||
sites = adapters.getConfigSections()
|
||||
sitesections = ['defaults','overrides']
|
||||
for section in sites:
|
||||
sitesections.append(section)
|
||||
if section.startswith('www.'):
|
||||
# add w/o www if has www
|
||||
sitesections.append(section[4:])
|
||||
else:
|
||||
sitewith = "www."+site
|
||||
sitewithout = site
|
||||
|
||||
self.addConfigSection(sitewith)
|
||||
self.addConfigSection(sitewithout)
|
||||
if fileform:
|
||||
self.addConfigSection(fileform)
|
||||
self.addConfigSection(sitewith+":"+fileform)
|
||||
self.addConfigSection(sitewithout+":"+fileform)
|
||||
self.addConfigSection("overrides")
|
||||
|
||||
self.listTypeEntries = [
|
||||
# add w/ www if doesn't www
|
||||
sitesections.append('www.%s'%section)
|
||||
|
||||
allowedsections = []
|
||||
forms=['html','txt','epub','mobi']
|
||||
allowedsections.extend(forms)
|
||||
|
||||
for section in sitesections:
|
||||
allowedsections.append(section)
|
||||
for f in forms:
|
||||
allowedsections.append('%s:%s'%(section,f))
|
||||
return allowedsections
|
||||
|
||||
def get_valid_list_entries():
|
||||
return list([
|
||||
'category',
|
||||
'genre',
|
||||
'characters',
|
||||
|
|
@ -70,9 +69,10 @@ class Configuration(ConfigParser.SafeConfigParser):
|
|||
'authorId',
|
||||
'authorUrl',
|
||||
'lastupdate',
|
||||
]
|
||||
|
||||
self.validEntries = self.listTypeEntries + [
|
||||
])
|
||||
|
||||
def get_valid_scalar_entries():
|
||||
return list([
|
||||
'series',
|
||||
'seriesUrl',
|
||||
'language',
|
||||
|
|
@ -97,7 +97,151 @@ class Configuration(ConfigParser.SafeConfigParser):
|
|||
'seriesHTML',
|
||||
'langcode',
|
||||
'output_css',
|
||||
]
|
||||
])
|
||||
|
||||
def get_valid_entries():
|
||||
return get_valid_list_entries() + get_valid_scalar_entries()
|
||||
|
||||
def get_valid_keywords():
|
||||
return list(['add_chapter_numbers',
|
||||
'add_genre_when_multi_category',
|
||||
'allow_unsafe_filename',
|
||||
'always_overwrite',
|
||||
'anthology_tags',
|
||||
'anthology_title_pattern',
|
||||
'background_color',
|
||||
'bulk_load',
|
||||
'chapter_end',
|
||||
'chapter_start',
|
||||
'chapter_title_add_pattern',
|
||||
'chapter_title_strip_pattern',
|
||||
'check_next_chapter',
|
||||
'collect_series',
|
||||
'connect_timeout',
|
||||
'convert_images_to',
|
||||
'cover_content',
|
||||
'cover_exclusion_regexp',
|
||||
'custom_columns_settings',
|
||||
'dateCreated_format',
|
||||
'datePublished_format',
|
||||
'dateUpdated_format',
|
||||
'default_cover_image',
|
||||
'do_update_hook',
|
||||
'exclude_notes',
|
||||
'extra_logpage_entries',
|
||||
'extra_subject_tags',
|
||||
'extra_titlepage_entries',
|
||||
'extra_valid_entries',
|
||||
'extratags',
|
||||
'extracategories',
|
||||
'extragenres',
|
||||
'extracharacters',
|
||||
'extraships',
|
||||
'extrawarnings',
|
||||
'fail_on_password',
|
||||
'file_end',
|
||||
'file_start',
|
||||
'fileformat',
|
||||
'find_chapters',
|
||||
'fix_fimf_blockquotes',
|
||||
'force_login',
|
||||
'generate_cover_settings',
|
||||
'grayscale_images',
|
||||
'image_max_size',
|
||||
'include_images',
|
||||
'include_logpage',
|
||||
'include_subject_tags',
|
||||
'include_titlepage',
|
||||
'include_tocpage',
|
||||
'(in|ex)clude_metadata_(pre|post)',
|
||||
'is_adult',
|
||||
'join_string_authorHTML',
|
||||
'keep_style_attr',
|
||||
'keep_summary_html',
|
||||
'logpage_end',
|
||||
'logpage_entries',
|
||||
'logpage_entry',
|
||||
'logpage_start',
|
||||
'logpage_update_end',
|
||||
'logpage_update_start',
|
||||
'make_directories',
|
||||
'make_firstimage_cover',
|
||||
'make_linkhtml_entries',
|
||||
'max_fg_sleep',
|
||||
'max_fg_sleep_at_downloads',
|
||||
'min_fg_sleep',
|
||||
'never_make_cover',
|
||||
'no_image_processing',
|
||||
'non_breaking_spaces',
|
||||
'nook_img_fix',
|
||||
'output_css',
|
||||
'output_filename',
|
||||
'output_filename_safepattern',
|
||||
'password',
|
||||
'post_process_cmd',
|
||||
'remove_transparency',
|
||||
'replace_br_with_p',
|
||||
'replace_hr',
|
||||
'replace_metadata',
|
||||
'slow_down_sleep_time',
|
||||
'sort_ships',
|
||||
'strip_chapter_numbers',
|
||||
'strip_chapter_numeral',
|
||||
'strip_text_links',
|
||||
'titlepage_end',
|
||||
'titlepage_entries',
|
||||
'titlepage_entry',
|
||||
'titlepage_no_title_entry',
|
||||
'titlepage_start',
|
||||
'titlepage_use_table',
|
||||
'titlepage_wide_entry',
|
||||
'tocpage_end',
|
||||
'tocpage_entry',
|
||||
'tocpage_start',
|
||||
'tweak_fg_sleep',
|
||||
'universe_as_series',
|
||||
'user_agent',
|
||||
'username',
|
||||
'website_encodings',
|
||||
'wide_titlepage_entries',
|
||||
'windows_eol',
|
||||
'wrap_width',
|
||||
'zip_filename',
|
||||
'zip_output',
|
||||
])
|
||||
|
||||
# *known* entry keywords -- or rather regexps for them.
|
||||
def get_valid_entry_keywords():
|
||||
return list(['%s_label',
|
||||
'(default_value|include_in|join_string|keep_in_order)_%s',])
|
||||
|
||||
class Configuration(ConfigParser.SafeConfigParser):
|
||||
|
||||
def __init__(self, site, fileform):
|
||||
ConfigParser.SafeConfigParser.__init__(self)
|
||||
|
||||
self.linenos=dict() # key by section or section,key -> lineno
|
||||
|
||||
self.sectionslist = ['defaults']
|
||||
|
||||
if site.startswith("www."):
|
||||
sitewith = site
|
||||
sitewithout = site.replace("www.","")
|
||||
else:
|
||||
sitewith = "www."+site
|
||||
sitewithout = site
|
||||
|
||||
self.addConfigSection(sitewith)
|
||||
self.addConfigSection(sitewithout)
|
||||
if fileform:
|
||||
self.addConfigSection(fileform)
|
||||
self.addConfigSection(sitewith+":"+fileform)
|
||||
self.addConfigSection(sitewithout+":"+fileform)
|
||||
self.addConfigSection("overrides")
|
||||
|
||||
self.listTypeEntries = get_valid_list_entries()
|
||||
|
||||
self.validEntries = get_valid_entries()
|
||||
|
||||
def addConfigSection(self,section):
|
||||
self.sectionslist.insert(0,section)
|
||||
|
|
@ -169,35 +313,6 @@ class Configuration(ConfigParser.SafeConfigParser):
|
|||
return self.get_config_list(self.sectionslist, key)
|
||||
|
||||
|
||||
def test_config(self):
|
||||
errors=[]
|
||||
|
||||
sites = adapters.getConfigSections()
|
||||
sitesections = ['defaults','overrides']
|
||||
for section in sites:
|
||||
sitesections.append(section)
|
||||
if section.startswith('www.'):
|
||||
# add w/o www if has www
|
||||
sitesections.append(section[4:])
|
||||
else:
|
||||
# add w/ www if doesn't www
|
||||
sitesections.append('www.%s'%section)
|
||||
|
||||
allowedsections = []
|
||||
forms=['html','txt','epub','mobi']
|
||||
allowedsections.extend(forms)
|
||||
|
||||
for section in sitesections:
|
||||
allowedsections.append(section)
|
||||
for f in forms:
|
||||
allowedsections.append('%s:%s'%(section,f))
|
||||
|
||||
for section in self.sections():
|
||||
if section not in allowedsections and 'teststory:' not in section:
|
||||
errors.append((self.get_lineno(section),"Bad Section Name: %s"%section))
|
||||
|
||||
return errors
|
||||
|
||||
def get_lineno(self,section,key=None):
|
||||
if key:
|
||||
return self.linenos.get(section+','+key,None)
|
||||
|
|
@ -293,7 +408,17 @@ class Configuration(ConfigParser.SafeConfigParser):
|
|||
# if any parsing errors occurred, raise an exception
|
||||
if e:
|
||||
raise e
|
||||
|
||||
|
||||
def test_config(self):
|
||||
errors=[]
|
||||
|
||||
allowedsections = get_valid_sections()
|
||||
for section in self.sections():
|
||||
if section not in allowedsections and 'teststory:' not in section:
|
||||
errors.append((self.get_lineno(section),"Bad Section Name: %s"%section))
|
||||
|
||||
return errors
|
||||
|
||||
# extended by adapter, writer and story for ease of calling configuration.
|
||||
class Configurable(object):
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue