mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-31 14:33:54 -04:00
Pull from trunk
This commit is contained in:
commit
74837333f3
BIN
resources/images/news/la_razon_bo.png
Normal file
BIN
resources/images/news/la_razon_bo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 356 B |
BIN
resources/images/news/los_tiempos_bo.png
Normal file
BIN
resources/images/news/los_tiempos_bo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 464 B |
64
resources/recipes/la_razon_bo.recipe
Normal file
64
resources/recipes/la_razon_bo.recipe
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
__license__ = 'GPL v3'
|
||||||
|
__copyright__ = '2010, Darko Miletic <darko.miletic at gmail.com>'
|
||||||
|
'''
|
||||||
|
www.la-razon.com
|
||||||
|
'''
|
||||||
|
|
||||||
|
from calibre import strftime
|
||||||
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
|
class LaRazon_Bol(BasicNewsRecipe):
|
||||||
|
title = 'La Razón - Bolivia'
|
||||||
|
__author__ = 'Darko Miletic'
|
||||||
|
description = 'El diario nacional de Bolivia'
|
||||||
|
publisher = 'Praxsis S.R.L.'
|
||||||
|
category = 'news, politics, Bolivia'
|
||||||
|
oldest_article = 1
|
||||||
|
max_articles_per_feed = 200
|
||||||
|
no_stylesheets = True
|
||||||
|
encoding = 'cp1252'
|
||||||
|
use_embedded_content = False
|
||||||
|
language = 'es'
|
||||||
|
publication_type = 'newspaper'
|
||||||
|
delay = 1
|
||||||
|
remove_empty_feeds = True
|
||||||
|
cover_url = strftime('http://www.la-razon.com/portadas/%Y%m%d_LaRazon.jpg')
|
||||||
|
masthead_url = 'http://www.la-razon.com/imagenes/logo.jpg'
|
||||||
|
extra_css = """ body{font-family: Arial,Helvetica,sans-serif }
|
||||||
|
img{margin-bottom: 0.4em}
|
||||||
|
.noticia-titulo{font-family: Georgia,"Times New Roman",Times,serif}
|
||||||
|
.lead{font-weight: bold; font-size: 0.8em}
|
||||||
|
"""
|
||||||
|
|
||||||
|
conversion_options = {
|
||||||
|
'comment' : description
|
||||||
|
, 'tags' : category
|
||||||
|
, 'publisher' : publisher
|
||||||
|
, 'language' : language
|
||||||
|
}
|
||||||
|
|
||||||
|
keep_only_tags = [dict(name='div', attrs={'class':['noticia-titulo','noticia-desarrollo']})]
|
||||||
|
remove_tags = [dict(name=['meta','link','form','iframe','embed','object'])]
|
||||||
|
remove_attributes = ['width','height']
|
||||||
|
|
||||||
|
feeds = [
|
||||||
|
(u'Editorial' , u'http://www.la-razon.com/rss_editorial.php' )
|
||||||
|
,(u'Opinión' , u'http://www.la-razon.com/rss_opinion.php' )
|
||||||
|
,(u'Nacional' , u'http://www.la-razon.com/rss_nacional.php' )
|
||||||
|
,(u'Economia' , u'http://www.la-razon.com/rss_economia.php' )
|
||||||
|
,(u'Ciudades' , u'http://www.la-razon.com/rss_ciudades.php' )
|
||||||
|
,(u'Sociedad' , u'http://www.la-razon.com/rss_sociedad.php' )
|
||||||
|
,(u'Mundo' , u'http://www.la-razon.com/rss_sociedad.php' )
|
||||||
|
,(u'La Revista' , u'http://www.la-razon.com/rss_larevista.php' )
|
||||||
|
,(u'Sociales' , u'http://www.la-razon.com/rss_sociales.php' )
|
||||||
|
,(u'Mia' , u'http://www.la-razon.com/rss_mia.php' )
|
||||||
|
,(u'Marcas' , u'http://www.la-razon.com/rss_marcas.php' )
|
||||||
|
,(u'Escape' , u'http://www.la-razon.com/rss_escape.php' )
|
||||||
|
,(u'El Financiero' , u'http://www.la-razon.com/rss_financiero.php')
|
||||||
|
,(u'Tendencias' , u'http://www.la-razon.com/rss_tendencias.php')
|
||||||
|
]
|
||||||
|
|
||||||
|
def preprocess_html(self, soup):
|
||||||
|
for item in soup.findAll(style=True):
|
||||||
|
del item['style']
|
||||||
|
return soup
|
63
resources/recipes/los_tiempos_bo.recipe
Normal file
63
resources/recipes/los_tiempos_bo.recipe
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
__license__ = 'GPL v3'
|
||||||
|
__copyright__ = '2010, Darko Miletic <darko.miletic at gmail.com>'
|
||||||
|
'''
|
||||||
|
www.lostiempos.com
|
||||||
|
'''
|
||||||
|
|
||||||
|
from calibre import strftime
|
||||||
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
|
class LosTiempos_Bol(BasicNewsRecipe):
|
||||||
|
title = 'Los Tiempos - Bolivia'
|
||||||
|
__author__ = 'Darko Miletic'
|
||||||
|
description = 'El periódico de mayor circulación en la ciudad de Cochabamba, Bolivia'
|
||||||
|
publisher = 'Los Tiempos'
|
||||||
|
category = 'news, politics, Bolivia'
|
||||||
|
oldest_article = 1
|
||||||
|
max_articles_per_feed = 200
|
||||||
|
no_stylesheets = True
|
||||||
|
encoding = 'cp1252'
|
||||||
|
use_embedded_content = False
|
||||||
|
language = 'es'
|
||||||
|
publication_type = 'newspaper'
|
||||||
|
delay = 1
|
||||||
|
remove_empty_feeds = True
|
||||||
|
cover_url = strftime('http://www.lostiempos.com/media_recortes/%Y/%m/%d/portada_md_1.jpg')
|
||||||
|
masthead_url = 'http://www.lostiempos.com/img_stat/logo_tiempos_sin_beta.jpg'
|
||||||
|
extra_css = """ body{font-family: Arial,Helvetica,sans-serif }
|
||||||
|
img{margin-bottom: 0.4em}
|
||||||
|
h1,.hora,.breadcum,.pie_foto{font-family: Georgia,"Times New Roman",Times,serif}
|
||||||
|
.hora,.breadcum,.pie_foto{font-size: small}
|
||||||
|
.en_gris,.pie_foto{color: #666666}
|
||||||
|
"""
|
||||||
|
|
||||||
|
conversion_options = {
|
||||||
|
'comment' : description
|
||||||
|
, 'tags' : category
|
||||||
|
, 'publisher' : publisher
|
||||||
|
, 'language' : language
|
||||||
|
}
|
||||||
|
|
||||||
|
keep_only_tags = [dict(name='div', attrs={'id':'articulo'})]
|
||||||
|
remove_tags = [
|
||||||
|
dict(name=['meta','link','form','iframe','embed','object','hr'])
|
||||||
|
,dict(attrs={'class':['caja_fonts sin_border_bot','pub']})
|
||||||
|
]
|
||||||
|
remove_attributes = ['width','height']
|
||||||
|
|
||||||
|
feeds = [
|
||||||
|
(u'Nacional' , u'http://www.lostiempos.com/rss/lostiempos-nacional.xml' )
|
||||||
|
,(u'Local' , u'http://www.lostiempos.com/rss/lostiempos-local.xml' )
|
||||||
|
,(u'Deportes' , u'http://www.lostiempos.com/rss/lostiempos-deportes.xml' )
|
||||||
|
,(u'Economía' , u'http://www.lostiempos.com/rss/lostiempos-economia.xml' )
|
||||||
|
,(u'Internacional' , u'http://www.lostiempos.com/rss/lostiempos-internacional.xml' )
|
||||||
|
,(u'Vida y Futuro' , u'http://www.lostiempos.com/rss/lostiempos-vida-y-futuro.xml' )
|
||||||
|
,(u'Tragaluz' , u'http://www.lostiempos.com/rss/lostiempos-tragaluz.xml' )
|
||||||
|
,(u'Opiniones' , u'http://www.lostiempos.com/rss/lostiempos-opiniones.xml' )
|
||||||
|
]
|
||||||
|
|
||||||
|
def preprocess_html(self, soup):
|
||||||
|
for item in soup.findAll(style=True):
|
||||||
|
del item['style']
|
||||||
|
return soup
|
||||||
|
|
34
resources/recipes/yahoo_news.recipe
Normal file
34
resources/recipes/yahoo_news.recipe
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
import re
|
||||||
|
|
||||||
|
class YahooNews(BasicNewsRecipe):
|
||||||
|
title = 'Yahoo News'
|
||||||
|
__author__ = 'Starson17'
|
||||||
|
description = 'Yahoo-Science'
|
||||||
|
language = 'en'
|
||||||
|
use_embedded_content= False
|
||||||
|
no_stylesheets = True
|
||||||
|
linearize_tables = True
|
||||||
|
oldest_article = 24
|
||||||
|
remove_javascript = True
|
||||||
|
remove_empty_feeds = True
|
||||||
|
max_articles_per_feed = 10
|
||||||
|
|
||||||
|
feeds = [#There are dozens of other feeds at http://news.yahoo.com/rss
|
||||||
|
(u'Top Stories', u'http://rss.news.yahoo.com/rss/topstories'),
|
||||||
|
(u'Science', u'http://rss.news.yahoo.com/rss/science')
|
||||||
|
]
|
||||||
|
|
||||||
|
keep_only_tags = [dict(name='div', attrs={'id':'yn-story'})]
|
||||||
|
|
||||||
|
remove_tags = [dict(name='div', attrs={'class':['hd', 'ft', 'yn-share-social']}),
|
||||||
|
dict(name='div', attrs={'id':['yn-story-minor-media']})]
|
||||||
|
|
||||||
|
preprocess_regexps = [(re.compile(r'<span>Play Video</span>', re.DOTALL),lambda match: '<span></span>')]
|
||||||
|
|
||||||
|
extra_css = '''
|
||||||
|
h1{font-family:Arial,Helvetica,sans-serif; font-weight:bold;font-size:large;}
|
||||||
|
h2{font-family:Arial,Helvetica,sans-serif; font-weight:normal;font-size:small;}
|
||||||
|
p{font-family:Arial,Helvetica,sans-serif;font-size:small;}
|
||||||
|
body{font-family:Helvetica,Arial,sans-serif;font-size:small;}
|
||||||
|
'''
|
@ -19,8 +19,8 @@ class ANDROID(USBMS):
|
|||||||
|
|
||||||
VENDOR_ID = {
|
VENDOR_ID = {
|
||||||
# HTC
|
# HTC
|
||||||
0x0bb4 : { 0x0c02 : [0x100, 0x227], 0x0c01 : [0x100, 0x227], 0x0ff9
|
0x0bb4 : { 0x0c02 : [0x100, 0x0227], 0x0c01 : [0x100, 0x0227], 0x0ff9
|
||||||
: [0x0100, 0x227]},
|
: [0x0100, 0x0227, 0x0226]},
|
||||||
|
|
||||||
# Motorola
|
# Motorola
|
||||||
0x22b8 : { 0x41d9 : [0x216], 0x2d67 : [0x100], 0x41db : [0x216],
|
0x22b8 : { 0x41d9 : [0x216], 0x2d67 : [0x100], 0x41db : [0x216],
|
||||||
|
@ -931,7 +931,7 @@ class SaveToDiskAction(object): # {{{
|
|||||||
lpath = self.library_view.model().db.library_path.replace('/', os.sep)
|
lpath = self.library_view.model().db.library_path.replace('/', os.sep)
|
||||||
if dpath.startswith(lpath):
|
if dpath.startswith(lpath):
|
||||||
return error_dialog(self, _('Not allowed'),
|
return error_dialog(self, _('Not allowed'),
|
||||||
_('You are tying to save files into the calibre '
|
_('You are trying to save files into the calibre '
|
||||||
'library. This can cause corruption of your '
|
'library. This can cause corruption of your '
|
||||||
'library. Save to disk is meant to export '
|
'library. Save to disk is meant to export '
|
||||||
'files from your calibre library elsewhere.'), show=True)
|
'files from your calibre library elsewhere.'), show=True)
|
||||||
|
@ -18,7 +18,7 @@ from calibre.gui2 import error_dialog, config, gprefs, \
|
|||||||
open_url, open_local_file, \
|
open_url, open_local_file, \
|
||||||
ALL_COLUMNS, NONE, info_dialog, choose_files, \
|
ALL_COLUMNS, NONE, info_dialog, choose_files, \
|
||||||
warning_dialog, ResizableDialog, question_dialog
|
warning_dialog, ResizableDialog, question_dialog
|
||||||
from calibre.utils.config import prefs
|
from calibre.utils.config import prefs, read_raw_tweaks, write_tweaks
|
||||||
from calibre.ebooks import BOOK_EXTENSIONS
|
from calibre.ebooks import BOOK_EXTENSIONS
|
||||||
from calibre.ebooks.oeb.iterator import is_supported
|
from calibre.ebooks.oeb.iterator import is_supported
|
||||||
from calibre.library.server import server_config
|
from calibre.library.server import server_config
|
||||||
@ -514,8 +514,18 @@ class ConfigDialog(ResizableDialog, Ui_Dialog):
|
|||||||
self.opt_toolbar_text.setCurrentIndex(idx)
|
self.opt_toolbar_text.setCurrentIndex(idx)
|
||||||
self.reset_confirmation_button.clicked.connect(self.reset_confirmation)
|
self.reset_confirmation_button.clicked.connect(self.reset_confirmation)
|
||||||
|
|
||||||
|
deft, curt = read_raw_tweaks()
|
||||||
|
self.current_tweaks.setPlainText(curt)
|
||||||
|
self.default_tweaks.setPlainText(deft)
|
||||||
|
self.restore_tweaks_to_default_button.clicked.connect(self.restore_tweaks_to_default)
|
||||||
|
|
||||||
self.category_view.setCurrentIndex(self.category_view.model().index_for_name(initial_category))
|
self.category_view.setCurrentIndex(self.category_view.model().index_for_name(initial_category))
|
||||||
|
|
||||||
|
def restore_tweaks_to_default(self, *args):
|
||||||
|
deft, curt = read_raw_tweaks()
|
||||||
|
self.current_tweaks.setPlainText(deft)
|
||||||
|
|
||||||
|
|
||||||
def reset_confirmation(self):
|
def reset_confirmation(self):
|
||||||
from calibre.gui2 import dynamic
|
from calibre.gui2 import dynamic
|
||||||
for key in dynamic.keys():
|
for key in dynamic.keys():
|
||||||
@ -687,6 +697,22 @@ class ConfigDialog(ResizableDialog, Ui_Dialog):
|
|||||||
self.input_order.insertItem(idx-1, self.input_order.takeItem(idx))
|
self.input_order.insertItem(idx-1, self.input_order.takeItem(idx))
|
||||||
self.input_order.setCurrentRow(idx-1)
|
self.input_order.setCurrentRow(idx-1)
|
||||||
|
|
||||||
|
def set_tweaks(self):
|
||||||
|
raw = unicode(self.current_tweaks.toPlainText())
|
||||||
|
raw = re.sub(r'(?m)^#.*fileencoding.*', '# ', raw)
|
||||||
|
try:
|
||||||
|
exec raw
|
||||||
|
except:
|
||||||
|
import traceback
|
||||||
|
error_dialog(self, _('Invalid tweaks'),
|
||||||
|
_('The tweaks you entered are invalid, try resetting the'
|
||||||
|
' tweaks to default and changing them one by one until'
|
||||||
|
' you find the invalid setting.'),
|
||||||
|
det_msg=traceback.format_exc(), show=True)
|
||||||
|
return False
|
||||||
|
write_tweaks(raw)
|
||||||
|
return True
|
||||||
|
|
||||||
def down_input(self):
|
def down_input(self):
|
||||||
idx = self.input_order.currentRow()
|
idx = self.input_order.currentRow()
|
||||||
if idx < self.input_order.count()-1:
|
if idx < self.input_order.count()-1:
|
||||||
@ -852,6 +878,8 @@ class ConfigDialog(ResizableDialog, Ui_Dialog):
|
|||||||
return
|
return
|
||||||
if not self.add_save.save_settings():
|
if not self.add_save.save_settings():
|
||||||
return
|
return
|
||||||
|
if not self.set_tweaks():
|
||||||
|
return
|
||||||
wl = self.opt_worker_limit.value()
|
wl = self.opt_worker_limit.value()
|
||||||
if wl%2 != 0:
|
if wl%2 != 0:
|
||||||
wl += 1
|
wl += 1
|
||||||
|
@ -718,6 +718,16 @@
|
|||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="page_2">
|
<widget class="QWidget" name="page_2">
|
||||||
<layout class="QGridLayout" name="gridLayout_3">
|
<layout class="QGridLayout" name="gridLayout_3">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QTabWidget" name="tabWidget">
|
||||||
|
<property name="currentIndex">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="tab">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>&Miscellaneous</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_9">
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QLabel" name="label_5">
|
<widget class="QLabel" name="label_5">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@ -741,27 +751,6 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0" colspan="2">
|
|
||||||
<widget class="QPushButton" name="compact_button">
|
|
||||||
<property name="text">
|
|
||||||
<string>&Check database integrity</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="0" colspan="2">
|
|
||||||
<widget class="QPushButton" name="button_osx_symlinks">
|
|
||||||
<property name="text">
|
|
||||||
<string>&Install command line tools</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="0" colspan="2">
|
|
||||||
<widget class="QPushButton" name="button_open_config_dir">
|
|
||||||
<property name="text">
|
|
||||||
<string>Open calibre &configuration directory</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QCheckBox" name="opt_enforce_cpu_limit">
|
<widget class="QCheckBox" name="opt_enforce_cpu_limit">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@ -769,13 +758,155 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0" colspan="2">
|
<item row="2" column="0">
|
||||||
|
<spacer name="verticalSpacer_4">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>79</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0" colspan="2">
|
||||||
<widget class="QPushButton" name="device_detection_button">
|
<widget class="QPushButton" name="device_detection_button">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Debug &device detection</string>
|
<string>Debug &device detection</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
|
<spacer name="verticalSpacer_6">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>80</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="0" colspan="2">
|
||||||
|
<widget class="QPushButton" name="compact_button">
|
||||||
|
<property name="text">
|
||||||
|
<string>&Check database integrity</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="0">
|
||||||
|
<spacer name="verticalSpacer_7">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>79</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="0" colspan="2">
|
||||||
|
<widget class="QPushButton" name="button_open_config_dir">
|
||||||
|
<property name="text">
|
||||||
|
<string>Open calibre &configuration directory</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="8" column="0">
|
||||||
|
<spacer name="verticalSpacer_8">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>80</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item row="9" column="0" colspan="2">
|
||||||
|
<widget class="QPushButton" name="button_osx_symlinks">
|
||||||
|
<property name="text">
|
||||||
|
<string>&Install command line tools</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="10" column="0">
|
||||||
|
<spacer name="verticalSpacer_9">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>79</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="tab_2">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>&Tweaks</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_18">
|
||||||
|
<property name="text">
|
||||||
|
<string>Values for the tweaks are shown below. Edit them to change the behavior of calibre</string>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox_6">
|
||||||
|
<property name="title">
|
||||||
|
<string>All available tweaks</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_11">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QPlainTextEdit" name="default_tweaks">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox_7">
|
||||||
|
<property name="title">
|
||||||
|
<string>&Current tweaks</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_10">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QPlainTextEdit" name="current_tweaks"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="restore_tweaks_to_default_button">
|
||||||
|
<property name="text">
|
||||||
|
<string>&Restore to defaults</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="page_4">
|
<widget class="QWidget" name="page_4">
|
||||||
|
@ -48,17 +48,42 @@ class EditAuthorsDialog(QDialog, Ui_EditAuthorsDialog):
|
|||||||
select_item = sort
|
select_item = sort
|
||||||
self.table.resizeColumnsToContents()
|
self.table.resizeColumnsToContents()
|
||||||
|
|
||||||
# set up the signal after the table is filled
|
# set up the cellChanged signal only after the table is filled
|
||||||
self.table.cellChanged.connect(self.cell_changed)
|
self.table.cellChanged.connect(self.cell_changed)
|
||||||
|
|
||||||
self.table.setSortingEnabled(True)
|
# set up sort buttons
|
||||||
|
self.sort_by_author.setCheckable(True)
|
||||||
|
self.sort_by_author.setChecked(False)
|
||||||
|
self.sort_by_author.clicked.connect(self.do_sort_by_author)
|
||||||
|
self.author_order = 1
|
||||||
|
|
||||||
self.table.sortByColumn(1, Qt.AscendingOrder)
|
self.table.sortByColumn(1, Qt.AscendingOrder)
|
||||||
|
self.sort_by_author_sort.clicked.connect(self.do_sort_by_author_sort)
|
||||||
|
self.sort_by_author_sort.setCheckable(True)
|
||||||
|
self.sort_by_author_sort.setChecked(True)
|
||||||
|
self.author_sort_order = 1
|
||||||
|
|
||||||
|
# set up author sort calc button
|
||||||
|
self.recalc_author_sort.clicked.connect(self.do_recalc_author_sort)
|
||||||
|
|
||||||
if select_item is not None:
|
if select_item is not None:
|
||||||
self.table.setCurrentItem(select_item)
|
self.table.setCurrentItem(select_item)
|
||||||
self.table.editItem(select_item)
|
self.table.editItem(select_item)
|
||||||
else:
|
else:
|
||||||
self.table.setCurrentCell(0, 0)
|
self.table.setCurrentCell(0, 0)
|
||||||
|
|
||||||
|
def do_sort_by_author(self):
|
||||||
|
self.author_order = 1 if self.author_order == 0 else 0
|
||||||
|
self.table.sortByColumn(0, self.author_order)
|
||||||
|
self.sort_by_author.setChecked(True)
|
||||||
|
self.sort_by_author_sort.setChecked(False)
|
||||||
|
|
||||||
|
def do_sort_by_author_sort(self):
|
||||||
|
self.author_sort_order = 1 if self.author_sort_order == 0 else 0
|
||||||
|
self.table.sortByColumn(1, self.author_sort_order)
|
||||||
|
self.sort_by_author.setChecked(False)
|
||||||
|
self.sort_by_author_sort.setChecked(True)
|
||||||
|
|
||||||
def accepted(self):
|
def accepted(self):
|
||||||
self.result = []
|
self.result = []
|
||||||
for row in range(0,self.table.rowCount()):
|
for row in range(0,self.table.rowCount()):
|
||||||
@ -69,6 +94,17 @@ class EditAuthorsDialog(QDialog, Ui_EditAuthorsDialog):
|
|||||||
if orig_aut != aut or orig_sort != sort:
|
if orig_aut != aut or orig_sort != sort:
|
||||||
self.result.append((id, orig_aut, aut, sort))
|
self.result.append((id, orig_aut, aut, sort))
|
||||||
|
|
||||||
|
def do_recalc_author_sort(self):
|
||||||
|
self.table.cellChanged.disconnect()
|
||||||
|
for row in range(0,self.table.rowCount()):
|
||||||
|
item = self.table.item(row, 0)
|
||||||
|
aut = unicode(item.text()).strip()
|
||||||
|
c = self.table.item(row, 1)
|
||||||
|
# Sometimes trailing commas are left by changing between copy algs
|
||||||
|
c.setText(author_to_author_sort(aut).rstrip(','))
|
||||||
|
self.table.setFocus(Qt.OtherFocusReason)
|
||||||
|
self.table.cellChanged.connect(self.cell_changed)
|
||||||
|
|
||||||
def cell_changed(self, row, col):
|
def cell_changed(self, row, col):
|
||||||
if col == 0:
|
if col == 0:
|
||||||
item = self.table.item(row, 0)
|
item = self.table.item(row, 0)
|
||||||
@ -79,8 +115,4 @@ class EditAuthorsDialog(QDialog, Ui_EditAuthorsDialog):
|
|||||||
else:
|
else:
|
||||||
item = self.table.item(row, 1)
|
item = self.table.item(row, 1)
|
||||||
self.table.setCurrentItem(item)
|
self.table.setCurrentItem(item)
|
||||||
# disable and reenable sorting to force the sort now, so we can scroll
|
|
||||||
# to the item after it moves
|
|
||||||
self.table.setSortingEnabled(False)
|
|
||||||
self.table.setSortingEnabled(True)
|
|
||||||
self.table.scrollToItem(item)
|
self.table.scrollToItem(item)
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>730</width>
|
<width>768</width>
|
||||||
<height>342</height>
|
<height>342</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
@ -33,8 +33,53 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="sort_by_author">
|
||||||
|
<property name="text">
|
||||||
|
<string>Sort by author</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="sort_by_author_sort">
|
||||||
|
<property name="text">
|
||||||
|
<string>Sort by author sort</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="recalc_author_sort">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Reset all the author sort values to a value automatically generated from the author. Exactly how this value is automatically generated can be controlled via Preferences->Advanced->Tweaks</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Recalculate all author sort values</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_3">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QDialogButtonBox" name="buttonBox">
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
@ -42,11 +87,13 @@
|
|||||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||||
</property>
|
</property>
|
||||||
<property name="centerButtons">
|
<property name="centerButtons">
|
||||||
<bool>true</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections>
|
<connections>
|
||||||
|
@ -675,9 +675,7 @@ class Wizard(QWizard):
|
|||||||
self.connect(self.library_page, SIGNAL('retranslate()'),
|
self.connect(self.library_page, SIGNAL('retranslate()'),
|
||||||
self.retranslate)
|
self.retranslate)
|
||||||
self.finish_page = FinishPage()
|
self.finish_page = FinishPage()
|
||||||
bt = unicode(self.buttonText(self.FinishButton)).replace('&', '')
|
self.set_finish_text()
|
||||||
t = unicode(self.finish_page.finish_text.text())
|
|
||||||
self.finish_page.finish_text.setText(t%bt)
|
|
||||||
self.kindle_page = KindlePage()
|
self.kindle_page = KindlePage()
|
||||||
self.stanza_page = StanzaPage()
|
self.stanza_page = StanzaPage()
|
||||||
self.word_player_page = WordPlayerPage()
|
self.word_player_page = WordPlayerPage()
|
||||||
@ -702,6 +700,7 @@ class Wizard(QWizard):
|
|||||||
for pid in self.pageIds():
|
for pid in self.pageIds():
|
||||||
page = self.page(pid)
|
page = self.page(pid)
|
||||||
page.retranslateUi(page)
|
page.retranslateUi(page)
|
||||||
|
self.set_finish_text()
|
||||||
|
|
||||||
def accept(self):
|
def accept(self):
|
||||||
pages = map(self.page, self.visitedPages())
|
pages = map(self.page, self.visitedPages())
|
||||||
@ -715,6 +714,13 @@ class Wizard(QWizard):
|
|||||||
def completed(self, newloc):
|
def completed(self, newloc):
|
||||||
return QWizard.accept(self)
|
return QWizard.accept(self)
|
||||||
|
|
||||||
|
def set_finish_text(self, *args):
|
||||||
|
bt = unicode(self.buttonText(self.FinishButton)).replace('&', '')
|
||||||
|
t = unicode(self.finish_page.finish_text.text())
|
||||||
|
if '%s' in t:
|
||||||
|
self.finish_page.finish_text.setText(t%bt)
|
||||||
|
|
||||||
|
|
||||||
def wizard(parent=None):
|
def wizard(parent=None):
|
||||||
w = Wizard(parent)
|
w = Wizard(parent)
|
||||||
return w
|
return w
|
||||||
|
@ -15,6 +15,7 @@ from calibre import prepare_string_for_xml
|
|||||||
# Hackish - ignoring sentences ending or beginning in numbers to avoid
|
# Hackish - ignoring sentences ending or beginning in numbers to avoid
|
||||||
# confusion with decimal points.
|
# confusion with decimal points.
|
||||||
lost_cr_pat = re.compile('([a-z])([\.\?!])([A-Z])')
|
lost_cr_pat = re.compile('([a-z])([\.\?!])([A-Z])')
|
||||||
|
lost_cr_exception_pat = re.compile(r'(Ph\.D)|(D\.Phil)|((Dr|Mr|Mrs|Ms)\.[A-Z])')
|
||||||
|
|
||||||
def comments_to_html(comments):
|
def comments_to_html(comments):
|
||||||
'''
|
'''
|
||||||
@ -51,6 +52,8 @@ def comments_to_html(comments):
|
|||||||
return '\n'.join(parts)
|
return '\n'.join(parts)
|
||||||
|
|
||||||
# Explode lost CRs to \n\n
|
# Explode lost CRs to \n\n
|
||||||
|
comments = lost_cr_exception_pat.sub(lambda m: m.group().replace('.',
|
||||||
|
'.\r'), comments)
|
||||||
for lost_cr in lost_cr_pat.finditer(comments):
|
for lost_cr in lost_cr_pat.finditer(comments):
|
||||||
comments = comments.replace(lost_cr.group(),
|
comments = comments.replace(lost_cr.group(),
|
||||||
'%s%s\n\n%s' % (lost_cr.group(1),
|
'%s%s\n\n%s' % (lost_cr.group(1),
|
||||||
|
@ -317,6 +317,8 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
|||||||
'title', 'timestamp', 'uuid', 'pubdate'):
|
'title', 'timestamp', 'uuid', 'pubdate'):
|
||||||
setattr(self, prop, functools.partial(get_property,
|
setattr(self, prop, functools.partial(get_property,
|
||||||
loc=self.FIELD_MAP['comments' if prop == 'comment' else prop]))
|
loc=self.FIELD_MAP['comments' if prop == 'comment' else prop]))
|
||||||
|
setattr(self, 'title_sort', functools.partial(get_property,
|
||||||
|
loc=self.FIELD_MAP['sort']))
|
||||||
|
|
||||||
def initialize_database(self):
|
def initialize_database(self):
|
||||||
metadata_sqlite = open(P('metadata_sqlite.sql'), 'rb').read()
|
metadata_sqlite = open(P('metadata_sqlite.sql'), 'rb').read()
|
||||||
@ -494,6 +496,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
|||||||
mi.timestamp = self.timestamp(idx, index_is_id=index_is_id)
|
mi.timestamp = self.timestamp(idx, index_is_id=index_is_id)
|
||||||
mi.pubdate = self.pubdate(idx, index_is_id=index_is_id)
|
mi.pubdate = self.pubdate(idx, index_is_id=index_is_id)
|
||||||
mi.uuid = self.uuid(idx, index_is_id=index_is_id)
|
mi.uuid = self.uuid(idx, index_is_id=index_is_id)
|
||||||
|
mi.title_sort = self.title_sort(idx, index_is_id=index_is_id)
|
||||||
tags = self.tags(idx, index_is_id=index_is_id)
|
tags = self.tags(idx, index_is_id=index_is_id)
|
||||||
if tags:
|
if tags:
|
||||||
mi.tags = [i.strip() for i in tags.split(',')]
|
mi.tags = [i.strip() for i in tags.split(',')]
|
||||||
|
@ -177,7 +177,7 @@ def extract(path, dir):
|
|||||||
try:
|
try:
|
||||||
if open_archive_data.OpenResult != 0:
|
if open_archive_data.OpenResult != 0:
|
||||||
raise UnRARException(_interpret_open_error(open_archive_data.OpenResult, path))
|
raise UnRARException(_interpret_open_error(open_archive_data.OpenResult, path))
|
||||||
prints('Archive:', path)
|
#prints('Archive:', path)
|
||||||
#print get_archive_info(open_archive_data.Flags)
|
#print get_archive_info(open_archive_data.Flags)
|
||||||
header_data = RARHeaderDataEx(CmtBuf=None)
|
header_data = RARHeaderDataEx(CmtBuf=None)
|
||||||
#_libunrar.RARSetCallback(arc_data, callback_func, mode)
|
#_libunrar.RARSetCallback(arc_data, callback_func, mode)
|
||||||
|
@ -277,7 +277,8 @@ In |app|, you would instead use tags to mark genre and read status and then just
|
|||||||
|
|
||||||
Why doesn't |app| have a column for foo?
|
Why doesn't |app| have a column for foo?
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|app| is designed to have columns for the most frequently and widely used fields. If it does not have a coulmn for your favorite field, you can always add a tag to the book for that piece of information. |app| also supports a general purpose "comments" fields for longer items.
|
|app| is designed to have columns for the most frequently and widely used fields. In addition, you can add any columns you like. Columns can be added via Preferences->Interface.
|
||||||
|
Watch the tutorial `UI Power tips <http://calibre-ebook.com/demo#tutorials>`_ to learn how to create your own columns.
|
||||||
|
|
||||||
How do I move my |app| library from one computer to another?
|
How do I move my |app| library from one computer to another?
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -703,16 +703,21 @@ if prefs['installation_uuid'] is None:
|
|||||||
prefs['installation_uuid'] = str(uuid.uuid4())
|
prefs['installation_uuid'] = str(uuid.uuid4())
|
||||||
|
|
||||||
# Read tweaks
|
# Read tweaks
|
||||||
def read_tweaks():
|
def read_raw_tweaks():
|
||||||
make_config_dir()
|
make_config_dir()
|
||||||
default_tweaks = P('default_tweaks.py', data=True)
|
default_tweaks = P('default_tweaks.py', data=True)
|
||||||
tweaks_file = os.path.join(config_dir, 'tweaks.py')
|
tweaks_file = os.path.join(config_dir, 'tweaks.py')
|
||||||
if not os.path.exists(tweaks_file):
|
if not os.path.exists(tweaks_file):
|
||||||
with open(tweaks_file, 'wb') as f:
|
with open(tweaks_file, 'wb') as f:
|
||||||
f.write(default_tweaks)
|
f.write(default_tweaks)
|
||||||
|
with open(tweaks_file, 'rb') as f:
|
||||||
|
return default_tweaks, f.read()
|
||||||
|
|
||||||
|
def read_tweaks():
|
||||||
|
default_tweaks, tweaks = read_raw_tweaks()
|
||||||
l, g = {}, {}
|
l, g = {}, {}
|
||||||
try:
|
try:
|
||||||
exec open(tweaks_file, 'rb') in g, l
|
exec tweaks in g, l
|
||||||
except:
|
except:
|
||||||
print 'Failed to load custom tweaks file'
|
print 'Failed to load custom tweaks file'
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
@ -721,6 +726,13 @@ def read_tweaks():
|
|||||||
dl.update(l)
|
dl.update(l)
|
||||||
return dl
|
return dl
|
||||||
|
|
||||||
|
def write_tweaks(raw):
|
||||||
|
make_config_dir()
|
||||||
|
tweaks_file = os.path.join(config_dir, 'tweaks.py')
|
||||||
|
with open(tweaks_file, 'wb') as f:
|
||||||
|
f.write(raw)
|
||||||
|
|
||||||
|
|
||||||
tweaks = read_tweaks()
|
tweaks = read_tweaks()
|
||||||
|
|
||||||
def migrate():
|
def migrate():
|
||||||
|
@ -194,7 +194,7 @@ class Image(_magick.Image): # {{{
|
|||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
def create_canvas(width, height, bgcolor):
|
def create_canvas(width, height, bgcolor='white'):
|
||||||
canvas = Image()
|
canvas = Image()
|
||||||
canvas.create_canvas(int(width), int(height), str(bgcolor))
|
canvas.create_canvas(int(width), int(height), str(bgcolor))
|
||||||
return canvas
|
return canvas
|
||||||
|
Loading…
x
Reference in New Issue
Block a user