mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Merge from trunk
This commit is contained in:
commit
d70ff5471d
@ -111,5 +111,6 @@ grouped_search_terms = {}
|
||||
add_new_book_tags_when_importing_books = False
|
||||
|
||||
|
||||
# Set the maximum number of tags to show in the content server
|
||||
# Set the maximum number of tags to show per book in the content server
|
||||
max_content_server_tags_shown=5
|
||||
|
||||
|
69
resources/recipes/hoy.recipe
Normal file
69
resources/recipes/hoy.recipe
Normal file
@ -0,0 +1,69 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2010, Francisco Javier Nieto <frjanibo at gmail.com>'
|
||||
'''
|
||||
www.hoy.es
|
||||
'''
|
||||
|
||||
from calibre.web.feeds.news import BasicNewsRecipe
|
||||
from calibre.ebooks.BeautifulSoup import Tag
|
||||
|
||||
class Hoy(BasicNewsRecipe):
|
||||
title = 'HOY'
|
||||
__author__ = 'Fco Javier Nieto'
|
||||
description = u'Noticias desde Extremadura'
|
||||
publisher = 'HOY'
|
||||
category = 'news, politics, Spain, Extremadura'
|
||||
oldest_article = 2
|
||||
max_articles_per_feed = 100
|
||||
no_stylesheets = True
|
||||
use_embedded_content = False
|
||||
delay = 1
|
||||
encoding = 'cp1252'
|
||||
language = 'es'
|
||||
|
||||
feeds = [
|
||||
(u'Portada' , u'http://www.hoy.es/portada.xml' ),
|
||||
(u'Regional' , u'http://www.hoy.es/rss/feeds/regional.xml' ),
|
||||
(u'Prov de Badajoz' , u'http://www.hoy.es/rss/feeds/prov_badajoz.xml' ),
|
||||
(u'Prov de Caceres' , u'http://www.hoy.es/rss/feeds/prov_caceres.xml' ),
|
||||
(u'Badajoz' , u'http://www.hoy.es/rss/feeds/badajoz.xml' ),
|
||||
(u'Caceres' , u'http://www.hoy.es/rss/feeds/caceres.xml' ),
|
||||
(u'Merida' , u'http://www.hoy.es/rss/feeds/merida.xml' ),
|
||||
(u'Opinion' , u'http://www.hoy.es/rss/feeds/opinion.xml' ),
|
||||
(u'Nacional' , u'http://www.hoy.es/rss/feeds/nacional.xml' ),
|
||||
(u'Internacional' , u'http://www.hoy.es/rss/feeds/internacional.xml' ),
|
||||
(u'Economia' , u'http://www.hoy.es/rss/feeds/economia.xml' ),
|
||||
(u'Deportes' , u'http://www.hoy.es/rss/feeds/deportes.xml' ),
|
||||
(u'Sociedad' , u'http://www.hoy.es/rss/feeds/sociedad.xml' ),
|
||||
(u'Cultura' , u'http://www.hoy.es/rss/feeds/cultura.xml' ),
|
||||
(u'Television' , u'http://www.hoy.es/rss/feeds/television.xml' ),
|
||||
(u'contraportada' , u'http://www.hoy.es/rss/feeds/contraportada.xml' )
|
||||
]
|
||||
|
||||
|
||||
keep_only_tags = [
|
||||
dict(name='h1', attrs={'class':['headline']}),
|
||||
dict(name='h2', attrs={'class':['subhead']}),
|
||||
dict(name='div', attrs={'class':['text']})
|
||||
]
|
||||
|
||||
remove_tags = [
|
||||
dict(name=['object','link','script'])
|
||||
,dict(name='div', attrs={'class':['colC_articulo','peu']})
|
||||
]
|
||||
|
||||
remove_tags_after = [dict(name='div', attrs={'class':'text'})]
|
||||
|
||||
extra_css = '.headline {font: sans-serif 2em;}\n.subhead,h2{font: sans-serif 1.5em\n'
|
||||
|
||||
def preprocess_html(self, soup):
|
||||
soup.html['dir' ] = self.direction
|
||||
mcharset = Tag(soup,'meta',[("http-equiv","Content-Type"),("content","text/html; charset=utf-8")])
|
||||
soup.head.insert(0,mcharset)
|
||||
for item in soup.findAll(style=True):
|
||||
del item['style']
|
||||
return soup
|
||||
|
@ -685,7 +685,16 @@ class LookAndFeel(PreferencesPlugin):
|
||||
name_order = 1
|
||||
config_widget = 'calibre.gui2.preferences.look_feel'
|
||||
|
||||
plugins += [LookAndFeel]
|
||||
class Behavior(PreferencesPlugin):
|
||||
name = 'Behavior'
|
||||
gui_name = _('Behavior')
|
||||
category = 'Interface'
|
||||
gui_category = _('Interface')
|
||||
category_order = 1
|
||||
name_order = 2
|
||||
config_widget = 'calibre.gui2.preferences.behavior'
|
||||
|
||||
plugins += [LookAndFeel, Behavior]
|
||||
|
||||
#}}}
|
||||
|
||||
|
@ -17,6 +17,9 @@ class ConfigWidgetInterface(object):
|
||||
def genesis(self, gui):
|
||||
raise NotImplementedError()
|
||||
|
||||
def initialize(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
def restore_defaults(self):
|
||||
pass
|
||||
|
||||
@ -117,6 +120,21 @@ class Setting(object):
|
||||
val = unicode(self.gui_obj.itemData(idx).toString())
|
||||
return val
|
||||
|
||||
class CommaSeparatedList(Setting):
|
||||
|
||||
def set_gui_val(self, val):
|
||||
x = ''
|
||||
if val:
|
||||
x = u', '.join(val)
|
||||
self.gui_obj.setText(x)
|
||||
|
||||
def get_gui_val(self):
|
||||
val = unicode(self.gui_obj.text()).strip()
|
||||
ans = []
|
||||
if val:
|
||||
ans = [x.strip() for x in val.split(',')]
|
||||
ans = [x for x in ans if x]
|
||||
return ans
|
||||
|
||||
class ConfigWidgetBase(QWidget, ConfigWidgetInterface):
|
||||
|
||||
@ -169,6 +187,7 @@ def test_widget(category, name, gui=None): # {{{
|
||||
pl = get_plugin(category, name)
|
||||
d = QDialog()
|
||||
d.resize(750, 550)
|
||||
d.setWindowTitle(category + " - " + name)
|
||||
bb = QDialogButtonBox(d)
|
||||
bb.setStandardButtons(bb.Apply|bb.Cancel|bb.RestoreDefaults)
|
||||
bb.accepted.connect(d.accept)
|
||||
|
163
src/calibre/gui2/preferences/behavior.py
Normal file
163
src/calibre/gui2/preferences/behavior.py
Normal file
@ -0,0 +1,163 @@
|
||||
#!/usr/bin/env python
|
||||
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
|
||||
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import re
|
||||
|
||||
from PyQt4.Qt import Qt, QVariant, QListWidgetItem
|
||||
|
||||
from calibre.gui2.preferences import ConfigWidgetBase, test_widget, \
|
||||
CommaSeparatedList
|
||||
from calibre.gui2.preferences.behavior_ui import Ui_Form
|
||||
from calibre.gui2 import config, info_dialog, dynamic
|
||||
from calibre.utils.config import prefs
|
||||
from calibre.customize.ui import available_output_formats, all_input_formats
|
||||
from calibre.utils.search_query_parser import saved_searches
|
||||
from calibre.ebooks import BOOK_EXTENSIONS
|
||||
from calibre.ebooks.oeb.iterator import is_supported
|
||||
|
||||
class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
||||
|
||||
def genesis(self, gui):
|
||||
self.gui = gui
|
||||
db = gui.library_view.model().db
|
||||
|
||||
r = self.register
|
||||
|
||||
r('worker_process_priority', prefs, choices=
|
||||
[(_('Low'), 'low'), (_('Normal'), 'normal'), (_('High'), 'high')])
|
||||
|
||||
r('network_timeout', prefs)
|
||||
|
||||
|
||||
r('overwrite_author_title_metadata', config)
|
||||
r('get_social_metadata', config)
|
||||
r('new_version_notification', config)
|
||||
r('upload_news_to_device', config)
|
||||
r('delete_news_from_library_on_upload', config)
|
||||
|
||||
output_formats = list(sorted(available_output_formats()))
|
||||
output_formats.remove('oeb')
|
||||
choices = [(x.upper(), x) for x in output_formats]
|
||||
r('output_format', prefs, choices=choices)
|
||||
|
||||
restrictions = sorted(saved_searches().names(),
|
||||
cmp=lambda x,y: cmp(x.lower(), y.lower()))
|
||||
choices = [('', '')] + [(x, x) for x in restrictions]
|
||||
r('gui_restriction', db.prefs, choices=choices)
|
||||
r('new_book_tags', prefs, setting=CommaSeparatedList)
|
||||
self.reset_confirmation_button.clicked.connect(self.reset_confirmation_dialogs)
|
||||
|
||||
self.input_up_button.clicked.connect(self.up_input)
|
||||
self.input_down_button.clicked.connect(self.down_input)
|
||||
for signal in ('Activated', 'Changed', 'DoubleClicked', 'Clicked'):
|
||||
signal = getattr(self.opt_internally_viewed_formats, 'item'+signal)
|
||||
signal.connect(self.internally_viewed_formats_changed)
|
||||
|
||||
|
||||
def initialize(self):
|
||||
ConfigWidgetBase.initialize(self)
|
||||
self.init_input_order()
|
||||
self.init_internally_viewed_formats()
|
||||
|
||||
def restore_defaults(self):
|
||||
ConfigWidgetBase.restore_defaults(self)
|
||||
self.init_input_order(defaults=True)
|
||||
self.init_internally_viewed_formats(defaults=True)
|
||||
|
||||
def commit(self):
|
||||
input_map = prefs['input_format_order']
|
||||
input_cols = [unicode(self.input_order.item(i).data(Qt.UserRole).toString()) for i in range(self.input_order.count())]
|
||||
if input_map != input_cols:
|
||||
prefs['input_format_order'] = input_cols
|
||||
fmts = self.current_internally_viewed_formats
|
||||
old = config['internally_viewed_formats']
|
||||
if fmts != old:
|
||||
config['internally_viewed_formats'] = fmts
|
||||
return ConfigWidgetBase.commit(self)
|
||||
|
||||
# Internally viewed formats {{{
|
||||
def internally_viewed_formats_changed(self, *args):
|
||||
fmts = self.current_internally_viewed_formats
|
||||
old = config['internally_viewed_formats']
|
||||
if fmts != old:
|
||||
self.changed_signal.emit()
|
||||
|
||||
def init_internally_viewed_formats(self, defaults=False):
|
||||
if defaults:
|
||||
fmts = config.defaults['internally_viewed_formats']
|
||||
else:
|
||||
fmts = config['internally_viewed_formats']
|
||||
viewer = self.opt_internally_viewed_formats
|
||||
viewer.blockSignals(True)
|
||||
exts = set([])
|
||||
for ext in BOOK_EXTENSIONS:
|
||||
ext = ext.lower()
|
||||
ext = re.sub(r'(x{0,1})htm(l{0,1})', 'html', ext)
|
||||
if ext == 'lrf' or is_supported('book.'+ext):
|
||||
exts.add(ext)
|
||||
viewer.clear()
|
||||
for ext in sorted(exts):
|
||||
viewer.addItem(ext.upper())
|
||||
item = viewer.item(viewer.count()-1)
|
||||
item.setFlags(Qt.ItemIsEnabled|Qt.ItemIsUserCheckable)
|
||||
item.setCheckState(Qt.Checked if
|
||||
ext.upper() in fmts else Qt.Unchecked)
|
||||
viewer.blockSignals(False)
|
||||
|
||||
@property
|
||||
def current_internally_viewed_formats(self):
|
||||
fmts = []
|
||||
viewer = self.opt_internally_viewed_formats
|
||||
for i in range(viewer.count()):
|
||||
if viewer.item(i).checkState() == Qt.Checked:
|
||||
fmts.append(unicode(viewer.item(i).text()))
|
||||
return fmts
|
||||
# }}}
|
||||
|
||||
# Input format order {{{
|
||||
def init_input_order(self, defaults=False):
|
||||
if defaults:
|
||||
input_map = prefs.defaults['input_format_order']
|
||||
else:
|
||||
input_map = prefs['input_format_order']
|
||||
all_formats = set()
|
||||
self.opt_input_order.clear()
|
||||
for fmt in all_input_formats().union(set(['ZIP', 'RAR'])):
|
||||
all_formats.add(fmt.upper())
|
||||
for format in input_map + list(all_formats.difference(input_map)):
|
||||
item = QListWidgetItem(format, self.opt_input_order)
|
||||
item.setData(Qt.UserRole, QVariant(format))
|
||||
item.setFlags(Qt.ItemIsEnabled|Qt.ItemIsSelectable)
|
||||
|
||||
def up_input(self, *args):
|
||||
idx = self.opt_input_order.currentRow()
|
||||
if idx > 0:
|
||||
self.opt_input_order.insertItem(idx-1, self.opt_input_order.takeItem(idx))
|
||||
self.opt_input_order.setCurrentRow(idx-1)
|
||||
self.changed_signal.emit()
|
||||
|
||||
def down_input(self, *args):
|
||||
idx = self.opt_input_order.currentRow()
|
||||
if idx < self.opt_input_order.count()-1:
|
||||
self.opt_input_order.insertItem(idx+1, self.opt_input_order.takeItem(idx))
|
||||
self.opt_input_order.setCurrentRow(idx+1)
|
||||
self.changed_signal.emit()
|
||||
|
||||
# }}}
|
||||
|
||||
def reset_confirmation_dialogs(self, *args):
|
||||
for key in dynamic.keys():
|
||||
if key.endswith('_again') and dynamic[key] is False:
|
||||
dynamic[key] = True
|
||||
info_dialog(self, _('Done'),
|
||||
_('Confirmation dialogs have all been reset'), show=True)
|
||||
|
||||
if __name__ == '__main__':
|
||||
from PyQt4.Qt import QApplication
|
||||
app = QApplication([])
|
||||
test_widget('Interface', 'Behavior')
|
||||
|
@ -29,21 +29,21 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="new_version_notification">
|
||||
<widget class="QCheckBox" name="opt_new_version_notification">
|
||||
<property name="text">
|
||||
<string>Show notification when &new version is available</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="sync_news">
|
||||
<widget class="QCheckBox" name="opt_upload_news_to_device">
|
||||
<property name="text">
|
||||
<string>Automatically send downloaded &news to ebook reader</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="delete_news">
|
||||
<widget class="QCheckBox" name="opt_delete_news_from_library_on_upload">
|
||||
<property name="text">
|
||||
<string>&Delete news from library when it is automatically sent to reader</string>
|
||||
</property>
|
||||
@ -57,12 +57,12 @@
|
||||
<string>Default network &timeout:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>timeout</cstring>
|
||||
<cstring>opt_network_timeout</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="timeout">
|
||||
<widget class="QSpinBox" name="opt_network_timeout">
|
||||
<property name="toolTip">
|
||||
<string>Set the default timeout for network fetches (i.e. anytime we go out to the internet to get information)</string>
|
||||
</property>
|
||||
@ -81,7 +81,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="priority">
|
||||
<widget class="QComboBox" name="opt_worker_process_priority">
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToMinimumContentsLengthWithIcon</enum>
|
||||
</property>
|
||||
@ -111,7 +111,7 @@
|
||||
<string>Job &priority:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>priority</cstring>
|
||||
<cstring>opt_worker_process_priority</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -121,12 +121,12 @@
|
||||
<string>Preferred &output format:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>output_format</cstring>
|
||||
<cstring>opt_output_format</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="output_format">
|
||||
<widget class="QComboBox" name="opt_output_format">
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToMinimumContentsLengthWithIcon</enum>
|
||||
</property>
|
||||
@ -196,7 +196,7 @@
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_10">
|
||||
<item>
|
||||
<widget class="QListWidget" name="input_order">
|
||||
<widget class="QListWidget" name="opt_input_order">
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
@ -208,7 +208,7 @@
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_10">
|
||||
<item>
|
||||
<widget class="QToolButton" name="input_up">
|
||||
<widget class="QToolButton" name="input_up_button">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
@ -232,7 +232,7 @@
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="input_down">
|
||||
<widget class="QToolButton" name="input_down_button">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
@ -256,7 +256,7 @@
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="0" column="0">
|
||||
<widget class="QListWidget" name="viewer">
|
||||
<widget class="QListWidget" name="opt_internally_viewed_formats">
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
|
@ -233,7 +233,7 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{
|
||||
|
||||
######################### Search Restriction ##########################
|
||||
SearchRestrictionMixin.__init__(self)
|
||||
self.apply_named_search_restriction(db.prefs.get('gui_restriction', ''))
|
||||
self.apply_named_search_restriction(db.prefs['gui_restriction'])
|
||||
|
||||
########################### Cover Flow ################################
|
||||
|
||||
@ -378,7 +378,7 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{
|
||||
self.set_window_title()
|
||||
self.apply_named_search_restriction('') # reset restriction to null
|
||||
self.saved_searches_changed() # reload the search restrictions combo box
|
||||
self.apply_named_search_restriction(db.prefs.get('gui_restriction', ''))
|
||||
self.apply_named_search_restriction(db.prefs['gui_restriction'])
|
||||
|
||||
def set_window_title(self):
|
||||
self.setWindowTitle(__appname__ + u' - ||%s||'%self.iactions['Choose Library'].library_name())
|
||||
|
@ -145,6 +145,8 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
||||
|
||||
def initialize_dynamic(self):
|
||||
self.prefs = DBPrefs(self)
|
||||
defs = self.prefs.defaults
|
||||
defs['gui_restriction'] = defs['cs_restriction'] = ''
|
||||
|
||||
# Migrate saved search and user categories to db preference scheme
|
||||
def migrate_preference(key, default):
|
||||
|
@ -7,7 +7,7 @@ __docformat__ = 'restructuredtext en'
|
||||
|
||||
import os
|
||||
|
||||
from calibre.utils.config import Config, StringConfig, config_dir, tweaks
|
||||
from calibre.utils.config import Config, StringConfig, config_dir
|
||||
|
||||
|
||||
listen_on = '0.0.0.0'
|
||||
@ -49,15 +49,3 @@ def server_config(defaults=None):
|
||||
def main():
|
||||
from calibre.library.server.main import main
|
||||
return main()
|
||||
|
||||
def format_tag_string(tags, sep):
|
||||
MAX = tweaks['max_content_server_tags_shown']
|
||||
if tags:
|
||||
tlist = [t.strip() for t in tags.split(sep)]
|
||||
else:
|
||||
tlist = []
|
||||
tlist.sort(cmp=lambda x,y:cmp(x.lower(), y.lower()))
|
||||
if len(tlist) > MAX:
|
||||
tlist = tlist[:MAX]+['...']
|
||||
return u'%s'%(', '.join(tlist)) if tlist else ''
|
||||
|
||||
|
@ -13,12 +13,11 @@ from lxml import html
|
||||
from lxml.html.builder import HTML, HEAD, TITLE, LINK, DIV, IMG, BODY, \
|
||||
OPTION, SELECT, INPUT, FORM, SPAN, TABLE, TR, TD, A, HR
|
||||
|
||||
from calibre.library.server.utils import strftime
|
||||
from calibre.library.server.utils import strftime, format_tag_string
|
||||
from calibre.ebooks.metadata import fmt_sidx
|
||||
from calibre.constants import __appname__
|
||||
from calibre import human_readable
|
||||
from calibre.utils.date import utcfromtimestamp, format_date
|
||||
from . import format_tag_string
|
||||
|
||||
def CLASS(*args, **kwargs): # class is a reserved word in Python
|
||||
kwargs['class'] = ' '.join(args)
|
||||
|
@ -11,6 +11,7 @@ import cherrypy
|
||||
|
||||
from calibre import strftime as _strftime, prints
|
||||
from calibre.utils.date import now as nowf
|
||||
from calibre.utils.config import tweaks
|
||||
|
||||
|
||||
def expose(func):
|
||||
@ -43,4 +44,14 @@ def strftime(fmt='%Y/%m/%d %H:%M:%S', dt=None):
|
||||
except:
|
||||
return _strftime(fmt, nowf().timetuple())
|
||||
|
||||
def format_tag_string(tags, sep):
|
||||
MAX = tweaks['max_content_server_tags_shown']
|
||||
if tags:
|
||||
tlist = [t.strip() for t in tags.split(sep)]
|
||||
else:
|
||||
tlist = []
|
||||
tlist.sort(cmp=lambda x,y:cmp(x.lower(), y.lower()))
|
||||
if len(tlist) > MAX:
|
||||
tlist = tlist[:MAX]+['...']
|
||||
return u'%s'%(', '.join(tlist)) if tlist else ''
|
||||
|
||||
|
@ -11,12 +11,11 @@ import cherrypy
|
||||
from lxml.builder import ElementMaker
|
||||
from lxml import etree
|
||||
|
||||
from calibre.library.server.utils import strftime
|
||||
from calibre.library.server.utils import strftime, format_tag_string
|
||||
from calibre.ebooks.metadata import fmt_sidx
|
||||
from calibre.constants import preferred_encoding
|
||||
from calibre import isbytestring
|
||||
from calibre.utils.date import format_date
|
||||
from . import format_tag_string
|
||||
|
||||
E = ElementMaker()
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user