27 Commits
0.1 ... 0.2

Author SHA1 Message Date
BasioMeusPuga
a62e681223 Fix python-poppler-qt5 version check 2018-03-16 21:10:28 +05:30
BasioMeusPuga
efe52cd3cb Update README.md 2018-03-16 20:30:16 +05:30
BasioMeusPuga
23aff44412 Merge pull request #14 from BasioMeusPuga/pdf
Preliminary pdf support
2018-03-16 20:22:20 +05:30
BasioMeusPuga
e8e3b81871 Put cache refilling on separate thread
Lookout for memory leaks
2018-03-16 20:19:35 +05:30
BasioMeusPuga
03b683e05d Implement caching for QGraphicsView 2018-03-16 19:32:25 +05:30
BasioMeusPuga
5b3759afe6 Preliminary pdf support
Consolidate comicbook modules
Do not write to temp dir for comics any longer
2018-03-16 18:46:38 +05:30
BasioMeusPuga
fc2fcb5361 Add "Last Read" column
Start counting blocks for progress (Not implemented)
2018-03-16 14:46:47 +05:30
BasioMeusPuga
6ee135a52b Blank lines at the end of each chapter
Improve searching
2018-03-15 19:23:02 +05:30
BasioMeusPuga
55545f62e7 Update README.md 2018-03-15 11:55:43 +05:30
BasioMeusPuga
160226c6cd Launching with __main__.py 2018-03-15 11:24:28 +05:30
BasioMeusPuga
5d3ce17447 Fix mobi7 parsing 2018-03-14 20:29:08 +05:30
BasioMeusPuga
03afc6933f Splitting for ePubs with anchor navigation 2018-03-14 19:58:41 +05:30
BasioMeusPuga
c9559daaf6 Fix file duplication
Increase icon size for scan library icon
2018-03-14 11:53:47 +05:30
BasioMeusPuga
3c293a39d3 Embed icon theme 2018-03-14 08:26:34 +05:30
BasioMeusPuga
a87cd24c3d Update README.md 2018-03-13 19:21:59 +05:30
BasioMeusPuga
8564ede48b Small fixes 2018-03-13 19:20:47 +05:30
BasioMeusPuga
e0b20e36dd Merge pull request #11 from eclipseo/fix_for_python3
Convert KindleUnpack/mobiml2xhtml.py to Python 3 syntax
2018-03-13 19:03:42 +05:30
Robert-André Mauchin
c2db6c13b0 Convert KindleUnpack/mobiml2xhtml.py to Python 3 syntax 2018-03-13 03:08:42 +01:00
BasioMeusPuga
dbff4cbcca Update README.md 2018-03-13 00:36:48 +05:30
BasioMeusPuga
ce9ee4ccb2 Account for no images in an epub 2018-03-13 00:24:32 +05:30
BasioMeusPuga
ca3d747136 Revert to manual versioning in the setup.py 2018-03-12 20:36:49 +05:30
BasioMeusPuga
9e5559bbfa Scrollbar visibility when needed
Exception handling in ePub book year
2018-03-12 19:51:01 +05:30
BasioMeusPuga
9e9d7cca90 Update README.md 2018-03-12 19:41:18 +05:30
BasioMeusPuga
05e1655fd9 Fix bugs in setuptools packaging 2018-03-12 19:32:36 +05:30
BasioMeusPuga
f9bcc399e8 Merge pull request #1 from undu/wheel
Enable Python binary paclaging of the code
2018-03-11 01:40:35 +05:30
Pau Ruiz i Safont
1cd6ff6b58 maintenance: use modules properly 2018-03-10 19:21:18 +00:00
Pau Ruiz i Safont
79180885b5 feature: enable python packaging 2018-03-10 19:00:56 +00:00
90 changed files with 4566 additions and 540 deletions

6
.gitignore vendored Normal file
View File

@@ -0,0 +1,6 @@
__pycache__/
.gitignore
.vscode/
parsers/__pycache__/
books/
Examples/

View File

@@ -246,13 +246,13 @@ class MobiMLConverter(object):
# handle case of end tag with no beginning by injecting empty begin tag
taginfo = ('begin', tname, None)
htmlstr += self.processtag(taginfo)
print " - fixed by injecting empty start tag ", tname
print(" - fixed by injecting empty start tag ", tname)
self.path.append(tname)
elif len(self.path) > 1 and tname == self.path[-2]:
# handle case of dangling missing end
taginfo = ('end', self.path[-1], None)
htmlstr += self.processtag(taginfo)
print " - fixed by injecting end tag ", self.path[-1]
print(" - fixed by injecting end tag ", self.path[-1])
self.path.pop()
self.path.pop()
@@ -504,18 +504,18 @@ def main(argv=sys.argv):
infile = argv[1]
try:
print 'Converting Mobi Markup Language to XHTML'
print('Converting Mobi Markup Language to XHTML')
mlc = MobiMLConverter(infile)
print 'Processing ...'
print('Processing ...')
htmlstr, css, cssname = mlc.processml()
outname = infile.rsplit('.',1)[0] + '_converted.html'
file(outname, 'wb').write(htmlstr)
file(cssname, 'wb').write(css)
print 'Completed'
print 'XHTML version of book can be found at: ' + outname
print('Completed')
print('XHTML version of book can be found at: ', outname)
except ValueError, e:
print "Error: %s" % e
except ValueError as e:
print("Error: %s" % e)
return 1
return 0

View File

@@ -2,21 +2,45 @@
Qt based ebook reader
Currently supports:
* pdf
* epub
* mobi
* azw / azw3 / azw4
* cbr / cbz
Support for a bunch of other formats is coming. Please see the TODO for additional information.
## Requirements
* Qt5
* PyQt5
* python-requests
* python-beautifulsoup4
| Package | Version tested |
| --- | --- |
| Qt5 | 5.10.1 |
| Python | 3.6 |
| PyQt5 | 5.10.1 |
| python-requests | 2.18.4 |
| python-beautifulsoup4 | 4.6.0 |
| poppler-qt5 | 0.61.1 |
| python-poppler-qt5 | 0.24.2 |
poppler-qt5 and python-poppler-qt5 are optional.
## Installation
0. Install dependencies
### Manual
0. Install dependencies - I recommend using your package manager for this.
1. Clone repository
2. Launch with \_\_main\_\_.py
2. Type the following in the root directory:
$ python setup.py build
# python setup.py install
3. OR launch with `lector/__main__.py`
### Available packages
* [AUR](https://aur.archlinux.org/packages/lector-git/)
## Reporting issues
When reporting issues:
* If you're having trouble with a book while the rest of the application / other books work, please link to a copy of the book itself.
* If nothing is working, please make sure the requirements mentioned above are all installed, and are at least at the version mentioned.
## Screenshots
@@ -43,3 +67,8 @@ Currently supports:
### In program dictionary
![alt tag](https://i.imgur.com/Vh9xQUC.png)
## Attributions
* [KindleUnpack](https://github.com/kevinhendricks/KindleUnpack)
* [rarfile](https://github.com/markokr/rarfile)
* [Papirus icon theme](https://github.com/PapirusDevelopmentTeam/papirus-icon-theme)

11
TODO
View File

@@ -24,6 +24,7 @@ TODO
✓ Context menu: Cache, Read, Edit database, delete, Mark read/unread
✓ Information dialog widget
✓ Allow editing of database data through the UI + for Bookmarks
✓ Include (action) icons with the applications
Set focus to newly added file
Reading:
✓ Drop down for TOC
@@ -53,6 +54,8 @@ TODO
Search document using QTextCursor?
Comic view keyboard shortcuts
Filetypes:
✓ pdf support
Parse TOC
✓ epub support
✓ Homegrown solution please
✓ cbz, cbr support
@@ -65,7 +68,8 @@ TODO
Bugs:
If there are files open and the database is deleted, TypeErrors result
Cover culling does not occur if some other tab has initial focus
Exiting with Ctrl + Q does not save the cursor position INITIALLY
Slider position change might be acting up too
Take metadata from the database when opening the file
Secondary:
Annotations
@@ -76,7 +80,7 @@ TODO
Goodreads API: Ratings, Read, Recommendations
Get ISBN using python-isbnlib
Pagination
Use embedded fonts
Use embedded fonts + CSS
Scrolling: Smooth / By Line
Spacebar should not cut off lines at the top
Shift to logging instead of print statements
@@ -91,5 +95,4 @@ TODO
Ignore a / the / numbers for sorting purposes
? Add only one file type if multiple are present
? Plugin system for parsers
? pdf support
? Create emblem per filetype
? Create emblem per filetype

View File

@@ -17,7 +17,6 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
import sys
import zipfile
from urllib.parse import unquote
@@ -29,6 +28,7 @@ class EPUB:
self.filename = filename
self.zip_file = None
self.book = {}
self.book['split_chapters'] = {}
def read_epub(self):
# This is the function that should error out in
@@ -57,7 +57,8 @@ class EPUB:
try:
this_xml = self.zip_file.read(filename).decode()
except KeyError:
print(str(filename) + ' not found in zip')
short_filename = os.path.basename(self.filename)
print(f'{str(filename)} not found in {short_filename}')
return
root = BeautifulSoup(this_xml, parser)
@@ -127,7 +128,7 @@ class EPUB:
try:
self.book['year'] = int(self.book['year'][:4])
except (TypeError, KeyError, IndexError):
except (TypeError, KeyError, IndexError, ValueError):
self.book['year'] = 9999
# Get identifier
@@ -170,7 +171,7 @@ class EPUB:
self.get_file_path(cover_href))
if not self.book['cover']:
# If no cover is located the conventioanl way,
# If no cover is located the conventional way,
# we go looking for the largest image in the book
biggest_image_size = 0
biggest_image = None
@@ -215,33 +216,32 @@ class EPUB:
for i in navpoints:
chapter_title = i.find('text').text
chapter_source = i.find('content').get('src')
chapter_source = unquote(chapter_source.split('#')[0])
self.book['navpoint_dict'][chapter_source] = chapter_title
chapter_source_file = unquote(chapter_source.split('#')[0])
if '#' in chapter_source:
try:
self.book['split_chapters'][chapter_source_file].append(
(chapter_source.split('#')[1], chapter_title))
except KeyError:
self.book['split_chapters'][chapter_source_file] = []
self.book['split_chapters'][chapter_source_file].append(
(chapter_source.split('#')[1], chapter_title))
self.book['navpoint_dict'][chapter_source_file] = chapter_title
def parse_chapters(self, temp_dir=None, split_large_xml=False):
no_title_chapter = 0
self.book['book_list'] = []
for i in self.book['chapters_in_order']:
chapter_data = self.read_from_zip(i).decode()
if not split_large_xml:
try:
self.book['book_list'].append(
(self.book['navpoint_dict'][i], chapter_data))
except KeyError:
fallback_title = str(no_title_chapter)
self.book['book_list'].append(
(fallback_title, chapter_data))
no_title_chapter += 1
if i in self.book['split_chapters'] and not split_large_xml:
split_chapters = get_split_content(
chapter_data, self.book['split_chapters'][i])
self.book['book_list'].extend(split_chapters)
cover_path = os.path.join(temp_dir, os.path.basename(self.filename)) + '- cover'
with open(cover_path, 'wb') as cover_temp:
cover_temp.write(self.book['cover'])
self.book['book_list'][0] = (
'Cover', f'<center><img src="{cover_path}" alt="Cover"></center>')
else:
elif split_large_xml:
# https://stackoverflow.com/questions/14444732/how-to-split-a-html-page-to-multiple-pages-using-python-and-beautiful-soup
markup = BeautifulSoup(chapter_data, 'xml')
chapters = []
@@ -264,13 +264,54 @@ class EPUB:
for this_chapter in chapters:
fallback_title = str(no_title_chapter)
self.book['book_list'].append(
(fallback_title, this_chapter))
(fallback_title, this_chapter + ('<br/>' * 8)))
no_title_chapter += 1
else:
try:
self.book['book_list'].append(
(self.book['navpoint_dict'][i], chapter_data + ('<br/>' * 8)))
except KeyError:
fallback_title = str(no_title_chapter)
self.book['book_list'].append(
(fallback_title, chapter_data))
no_title_chapter += 1
def main():
book = EPUB(sys.argv[1])
book.read_epub()
book.parse_chapters()
cover_path = os.path.join(temp_dir, os.path.basename(self.filename)) + '- cover'
if self.book['cover']:
with open(cover_path, 'wb') as cover_temp:
cover_temp.write(self.book['cover'])
if __name__ == '__main__':
main()
self.book['book_list'][0] = (
'Cover', f'<center><img src="{cover_path}" alt="Cover"></center>')
def get_split_content(chapter_data, split_by):
split_anchors = [i[0] for i in split_by]
chapter_titles = [i[1] for i in split_by]
return_list = []
xml = BeautifulSoup(chapter_data, 'lxml')
xml_string = xml.body.prettify()
for count, i in enumerate(split_anchors):
this_split = xml_string.split(i)
current_chapter = this_split[0]
bs_obj = BeautifulSoup(current_chapter, 'lxml')
# Since tags correspond to data following them, the first
# chunk will be ignored
# As will all empty chapters
if bs_obj.text == '\n' or bs_obj.text == '' or count == 0:
continue
bs_obj_string = str(bs_obj).replace('"&gt;', '', 1) + ('<br/>' * 8)
return_list.append(
(chapter_titles[count - 1], bs_obj_string))
xml_string = this_split[1]
bs_obj = BeautifulSoup(xml_string, 'lxml')
bs_obj_string = str(bs_obj).replace('"&gt;', '', 1) + ('<br/>' * 8)
return_list.append(
(chapter_titles[-1], bs_obj_string))
return return_list

0
lector/__init__.py Normal file
View File

View File

@@ -19,22 +19,30 @@
import os
import sys
import hashlib
import pathlib
from PyQt5 import QtWidgets, QtGui, QtCore
import sorter
import database
# This allows for the program to be launched from the
# dir where it's been copied instead of needing to be
# installed
install_dir = os.path.realpath(__file__)
install_dir = pathlib.Path(install_dir).parents[1]
sys.path.append(str(install_dir))
from lector import database
from lector import sorter
from lector.toolbars import LibraryToolBar, BookToolBar
from lector.widgets import Tab
from lector.delegates import LibraryDelegate
from lector.threaded import BackGroundTabUpdate, BackGroundBookAddition, BackGroundBookDeletion
from lector.library import Library
from lector.guifunctions import QImageFactory
from lector.settings import Settings
from lector.settingsdialog import SettingsUI
from lector.metadatadialog import MetadataUI
from lector.definitionsdialog import DefinitionsUI
from resources import mainwindow, resources
from toolbars import LibraryToolBar, BookToolBar
from widgets import Tab
from delegates import LibraryDelegate
from threaded import BackGroundTabUpdate, BackGroundBookAddition, BackGroundBookDeletion
from library import Library
from settings import Settings
from settingsdialog import SettingsUI
from metadatadialog import MetadataUI
from definitionsdialog import DefinitionsUI
class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
@@ -52,6 +60,13 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
self.database_path = None
self.active_library_filters = []
# Initialize application
Settings(self).read_settings() # This should populate all variables that need
# to be remembered across sessions
# Initialize icon factory
self.QImageFactory = QImageFactory(self)
# Initialize toolbars
self.libraryToolBar = LibraryToolBar(self)
self.bookToolBar = BookToolBar(self)
@@ -62,10 +77,6 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
self.toolbarToggle = QtWidgets.QToolButton()
self.reloadLibrary = QtWidgets.QToolButton()
# Initialize application
Settings(self).read_settings() # This should populate all variables that need
# to be remembered across sessions
# Create the database in case it doesn't exist
database.DatabaseInit(self.database_path)
@@ -90,22 +101,13 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
self.sorterProgress.setVisible(False)
# Statusbar - Toolbar Visibility
self.toolbarToggle.setIcon(QtGui.QIcon.fromTheme('visibility'))
self.toolbarToggle.setIcon(self.QImageFactory.get_image('visibility'))
self.toolbarToggle.setObjectName('toolbarToggle')
self.toolbarToggle.setToolTip('Toggle toolbar')
self.toolbarToggle.setAutoRaise(True)
self.toolbarToggle.clicked.connect(self.toggle_toolbars)
self.statusBar.addPermanentWidget(self.toolbarToggle)
# THIS IS TEMPORARY
self.guiTest = QtWidgets.QToolButton()
self.guiTest.setIcon(QtGui.QIcon.fromTheme('mail-thread-watch'))
self.guiTest.setObjectName('guiTest')
self.guiTest.setToolTip('Test Function')
self.guiTest.setAutoRaise(True)
self.guiTest.clicked.connect(self.test_function)
self.statusBar.addPermanentWidget(self.guiTest)
# Application wide temporary directory
self.temp_dir = QtCore.QTemporaryDir()
@@ -194,8 +196,9 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
print('Available parsers: ' + self.available_parsers)
# The library refresh button on the Library tab
self.reloadLibrary.setIcon(QtGui.QIcon.fromTheme('reload'))
self.reloadLibrary.setIcon(self.QImageFactory.get_image('reload'))
self.reloadLibrary.setObjectName('reloadLibrary')
self.reloadLibrary.setToolTip('Scan library')
self.reloadLibrary.setAutoRaise(True)
self.reloadLibrary.clicked.connect(self.settingsDialog.start_library_scan)
@@ -243,7 +246,7 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
if self.settings['main_window_headers']:
for count, i in enumerate(self.settings['main_window_headers']):
self.tableView.horizontalHeader().resizeSection(count, int(i))
self.tableView.horizontalHeader().resizeSection(4, 1)
self.tableView.horizontalHeader().resizeSection(5, 1)
self.tableView.horizontalHeader().setStretchLastSection(True)
self.tableView.horizontalHeader().sectionClicked.connect(
self.lib_ref.table_proxy_model.sort_table_columns)
@@ -292,6 +295,9 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
self.temp_dir.path())
parsed_books = books.initiate_threads()
if not parsed_books:
return
database.DatabaseFunctions(self.database_path).add_to_database(parsed_books)
self.lib_ref.generate_model('addition', parsed_books, True)
@@ -365,6 +371,9 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
{'Hash': ''},
'LIKE')
if not all_covers_db:
return
all_covers = {
i[0]: i[1] for i in all_covers_db}
@@ -990,19 +999,19 @@ class MainUI(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
context_menu = QtWidgets.QMenu()
openAction = context_menu.addAction(
QtGui.QIcon.fromTheme('view-readermode'), 'Start reading')
self.QImageFactory.get_image('view-readermode'), 'Start reading')
editAction = None
if len(selected_indexes) == 1:
editAction = context_menu.addAction(
QtGui.QIcon.fromTheme('edit-rename'), 'Edit')
self.QImageFactory.get_image('edit-rename'), 'Edit')
deleteAction = context_menu.addAction(
QtGui.QIcon.fromTheme('trash-empty'), 'Delete')
self.QImageFactory.get_image('trash-empty'), 'Delete')
readAction = context_menu.addAction(
QtGui.QIcon.fromTheme('vcs-normal'), 'Mark read')
QtGui.QIcon(':/images/checkmark.svg'), 'Mark read')
unreadAction = context_menu.addAction(
QtGui.QIcon.fromTheme('emblem-unavailable'), 'Mark unread')
QtGui.QIcon(':/images/xmark.svg'), 'Mark unread')
action = context_menu.exec_(self.sender().mapToGlobal(position))

32
lector/guifunctions.py Normal file
View File

@@ -0,0 +1,32 @@
#!usr/bin/env python3
# This file is a part of Lector, a Qt based ebook reader
# Copyright (C) 2018 BasioMeusPuga
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from PyQt5 import QtGui
from resources import resources
class QImageFactory:
def __init__(self, parent):
self.parent = parent
def get_image(self, image_name):
icon_theme = self.parent.settings['icon_theme']
icon_path = f':/images/{icon_theme}/{image_name}.svg'
this_qicon = QtGui.QIcon(icon_path)
return this_qicon

View File

@@ -21,8 +21,8 @@ import pickle
import pathlib
from PyQt5 import QtGui, QtCore
import database
from models import TableProxyModel, ItemProxyModel
from lector import database
from lector.models import TableProxyModel, ItemProxyModel
class Library:

View File

@@ -18,10 +18,10 @@
from PyQt5 import QtWidgets, QtCore, QtGui
import database
from lector import database
from resources import metadata
from widgets import PliantQGraphicsScene
from lector.widgets import PliantQGraphicsScene
class MetadataUI(QtWidgets.QDialog, metadata.Ui_Dialog):

View File

@@ -16,6 +16,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import pickle
import pathlib
from PyQt5 import QtCore, QtWidgets
@@ -68,7 +69,7 @@ class TableProxyModel(QtCore.QSortFilterProxyModel):
def __init__(self, temp_dir, parent=None):
super(TableProxyModel, self).__init__(parent)
self.header_data = [
None, 'Title', 'Author', 'Year', '%', 'Tags']
None, 'Title', 'Author', 'Year', 'Last Read', '%', 'Tags']
self.temp_dir = temp_dir
self.filter_text = None
self.active_library_filters = None
@@ -77,12 +78,13 @@ class TableProxyModel(QtCore.QSortFilterProxyModel):
1: QtCore.Qt.UserRole, # Title
2: QtCore.Qt.UserRole + 1, # Author
3: QtCore.Qt.UserRole + 2, # Year
4: QtCore.Qt.UserRole + 7, # Position percentage
5: QtCore.Qt.UserRole + 4} # Tags
4: QtCore.Qt.UserRole + 12, # Last read
5: QtCore.Qt.UserRole + 7, # Position percentage
6: QtCore.Qt.UserRole + 4} # Tags
self.common_functions = ProxyModelsCommonFunctions(self)
def columnCount(self, parent):
return 6
return 7
def headerData(self, column, orientation, role):
if role == QtCore.Qt.DisplayRole:
@@ -97,11 +99,12 @@ class TableProxyModel(QtCore.QSortFilterProxyModel):
source_index = self.mapToSource(index)
item = self.sourceModel().item(source_index.row(), 0)
if role == QtCore.Qt.TextAlignmentRole and index.column() == 3:
return QtCore.Qt.AlignHCenter
if role == QtCore.Qt.TextAlignmentRole:
if index.column() in (3, 4):
return QtCore.Qt.AlignHCenter
if role == QtCore.Qt.DecorationRole:
if index.column() == 4:
if index.column() == 5:
return_pixmap = None
file_exists = item.data(QtCore.Qt.UserRole + 5)
@@ -136,11 +139,20 @@ class TableProxyModel(QtCore.QSortFilterProxyModel):
return return_pixmap
elif role == QtCore.Qt.DisplayRole or role == QtCore.Qt.EditRole:
if index.column() in (0, 4): # Cover and Status
if index.column() in (0, 5): # Cover and Status
return QtCore.QVariant()
return item.data(self.role_dictionary[index.column()])
if index.column() == 4:
last_accessed_time = item.data(self.role_dictionary[index.column()])
if last_accessed_time:
last_accessed = last_accessed_time
if not isinstance(last_accessed_time, QtCore.QDateTime):
last_accessed = pickle.loads(last_accessed_time)
right_now = QtCore.QDateTime().currentDateTime()
time_diff = last_accessed.msecsTo(right_now)
return self.time_convert(time_diff // 1000)
return item.data(self.role_dictionary[index.column()])
else:
return QtCore.QVariant()
@@ -157,6 +169,20 @@ class TableProxyModel(QtCore.QSortFilterProxyModel):
self.sort(0, sorting_order)
self.setSortRole(self.role_dictionary[column])
def time_convert(self, seconds):
seconds = int(seconds)
m, s = divmod(seconds, 60)
h, m = divmod(m, 60)
d, h = divmod(h, 24)
if d > 0:
return f'{d}d'
if h > 0:
return f'{h}h'
if m > 0:
return f'{m}m'
else:
return '<1m'
class ProxyModelsCommonFunctions:
def __init__(self, parent_model):

View File

@@ -54,6 +54,7 @@ class Settings:
self.parent.settings['main_window_headers'] = self.settings.value('tableHeaders', None)
self.parent.settings['listview_background'] = self.settings.value(
'listViewBackground', QtGui.QColor().fromRgb(76, 76, 76))
self.parent.settings['icon_theme'] = self.settings.value('iconTheme', 'DarkIcons')
self.settings.endGroup()
self.settings.beginGroup('runtimeVariables')
@@ -113,11 +114,12 @@ class Settings:
self.settings.setValue('windowSize', self.parent.size())
self.settings.setValue('windowPosition', self.parent.pos())
self.settings.setValue('currentView', self.parent.stackedWidget.currentIndex())
self.settings.setValue('iconTheme', self.parent.settings['icon_theme'])
self.settings.setValue(
'listViewBackground', self.parent.settings['listview_background'])
table_headers = []
for i in range(3):
for i in range(7):
table_headers.append(self.parent.tableView.horizontalHeader().sectionSize(i))
self.settings.setValue('tableHeaders', table_headers)
self.settings.endGroup()

View File

@@ -23,10 +23,11 @@ import os
import copy
from PyQt5 import QtWidgets, QtCore
import database
from lector import database
from lector.models import MostExcellentFileSystemModel
from lector.threaded import BackGroundBookSearch, BackGroundBookAddition
from resources import settingswindow
from models import MostExcellentFileSystemModel, FileSystemProxyModel
from threaded import BackGroundBookSearch, BackGroundBookAddition
class SettingsUI(QtWidgets.QDialog, settingswindow.Ui_Dialog):
@@ -41,7 +42,9 @@ class SettingsUI(QtWidgets.QDialog, settingswindow.Ui_Dialog):
self.move(self.parent.settings['settings_dialog_position'])
self.aboutBox.setVisible(False)
aboutfile_path = os.path.join('resources', 'about.html')
application_root = os.sep.join(
os.path.realpath(__file__).rsplit('/')[:-2])
aboutfile_path = os.path.join(application_root, 'resources', 'about.html')
with open(aboutfile_path) as about_html:
self.aboutBox.setHtml(about_html.read())
@@ -66,6 +69,14 @@ class SettingsUI(QtWidgets.QDialog, settingswindow.Ui_Dialog):
self.cancelButton.clicked.connect(self.cancel_pressed)
self.aboutButton.clicked.connect(self.about_pressed)
# Radio buttons
if self.parent.settings['icon_theme'] == 'DarkIcons':
self.darkIconsRadio.setChecked(True)
else:
self.lightIconsRadio.setChecked(True)
self.darkIconsRadio.clicked.connect(self.change_icon_theme)
self.lightIconsRadio.clicked.connect(self.change_icon_theme)
# Check boxes
self.autoTags.setChecked(self.parent.settings['auto_tags'])
self.coverShadows.setChecked(self.parent.settings['cover_shadows'])
@@ -79,6 +90,9 @@ class SettingsUI(QtWidgets.QDialog, settingswindow.Ui_Dialog):
self.fileRemember.clicked.connect(self.manage_checkboxes)
self.performCulling.clicked.connect(self.manage_checkboxes)
self.comicsRemain.setEnabled(False)
self.comicsRemain.setToolTip('Not implemented yet')
# Generate the filesystem treeView
self.generate_tree()
@@ -243,6 +257,12 @@ class SettingsUI(QtWidgets.QDialog, settingswindow.Ui_Dialog):
table_headers.append(self.treeView.columnWidth(i))
self.parent.settings['settings_dialog_headers'] = table_headers
def change_icon_theme(self):
if self.sender() == self.darkIconsRadio:
self.parent.settings['icon_theme'] = 'DarkIcons'
else:
self.parent.settings['icon_theme'] = 'LightIcons'
def change_dictionary_language(self, event):
language_dict = {
0: 'en',

View File

@@ -42,22 +42,23 @@ import threading
from multiprocessing import Pool, Manager
from PyQt5 import QtCore, QtGui
import database
from lector import database
from parsers.cbz import ParseCBZ
from parsers.cbr import ParseCBR
from parsers.pdf import ParsePDF
from parsers.epub import ParseEPUB
from parsers.mobi import ParseMOBI
from parsers.comicbooks import ParseCOMIC
sorter = {
'pdf': ParsePDF,
'epub': ParseEPUB,
'mobi': ParseMOBI,
'azw': ParseMOBI,
'azw3': ParseMOBI,
'azw4': ParseMOBI,
'prc': ParseMOBI,
'cbz': ParseCBZ,
'cbr': ParseCBR,}
'cbz': ParseCOMIC,
'cbr': ParseCOMIC}
available_parsers = [i for i in sorter]
progressbar = None # This is populated by __main__
@@ -149,7 +150,9 @@ class BookSorter:
# Do not allow addition in case the file
# is already in the database and it remains at its original path
if self.mode == 'addition' and file_md5 in self.hashes_and_paths:
if self.hashes_and_paths[file_md5] == filename:
if (self.hashes_and_paths[file_md5] == filename
and os.path.exists(self.hashes_and_paths[file_md5])):
print(f'{os.path.basename(filename)} is already in database')
return
file_extension = os.path.splitext(filename)[1][1:]
@@ -247,6 +250,9 @@ class BookSorter:
break
def initiate_threads(self):
if not self.file_list:
return None
def pool_creator():
_pool = Pool(5)
self.processed_books = _pool.map(

View File

@@ -19,10 +19,10 @@
import os
import pathlib
from multiprocessing.dummy import Pool
from PyQt5 import QtCore
from PyQt5 import QtCore, QtGui
import sorter
import database
from lector import sorter
from lector import database
class BackGroundTabUpdate(QtCore.QThread):
@@ -58,7 +58,11 @@ class BackGroundBookAddition(QtCore.QThread):
self.database_path,
self.parent.settings['auto_tags'],
self.parent.temp_dir.path())
parsed_books = books.initiate_threads()
if not parsed_books:
return
self.parent.lib_ref.generate_model('addition', parsed_books, False)
if self.prune_required:
self.parent.lib_ref.prune_models(self.file_list)
@@ -115,3 +119,47 @@ class BackGroundBookSearch(QtCore.QThread):
initiate_threads()
print(len(self.valid_files), 'books found')
class BackGroundCacheRefill(QtCore.QThread):
def __init__(self, image_cache, remove_value, filetype, book, all_pages, parent=None):
super(BackGroundCacheRefill, self).__init__(parent)
self.image_cache = image_cache
self.remove_value = remove_value
self.filetype = filetype
self.book = book
self.all_pages = all_pages
def run(self):
def load_page(current_page):
image_pixmap = QtGui.QPixmap()
if self.filetype in ('cbz', 'cbr'):
page_data = self.book.read(current_page)
image_pixmap.loadFromData(page_data)
elif self.filetype == 'pdf':
page_data = self.book.page(current_page)
page_qimage = page_data.renderToImage(350, 350)
image_pixmap.convertFromImage(page_qimage)
return image_pixmap
remove_index = self.image_cache.index(self.remove_value)
if remove_index == 1:
first_path = self.image_cache[0][0]
self.image_cache.pop(3)
previous_page = self.all_pages[self.all_pages.index(first_path) - 1]
refill_pixmap = load_page(previous_page)
self.image_cache.insert(0, (previous_page, refill_pixmap))
else:
self.image_cache[0] = self.image_cache[1]
self.image_cache.pop(1)
try:
last_page = self.image_cache[2][0]
next_page = self.all_pages[self.all_pages.index(last_page) + 1]
refill_pixmap = load_page(next_page)
self.image_cache.append((next_page, refill_pixmap))
except (IndexError, TypeError):
self.image_cache.append(None)

View File

@@ -38,22 +38,24 @@ class BookToolBar(QtWidgets.QToolBar):
self.setContextMenuPolicy(QtCore.Qt.PreventContextMenu)
self.setObjectName("LibraryToolBar")
image_factory = self.window().QImageFactory
# Buttons
self.fontButton = QtWidgets.QAction(
QtGui.QIcon.fromTheme('gtk-select-font'),
image_factory.get_image('gtk-select-font'),
'View settings', self)
self.fullscreenButton = QtWidgets.QAction(
QtGui.QIcon.fromTheme('view-fullscreen'),
image_factory.get_image('view-fullscreen'),
'Fullscreen', self)
self.addBookmarkButton = QtWidgets.QAction(
QtGui.QIcon.fromTheme('bookmark-new'),
image_factory.get_image('bookmark-new'),
'Add bookmark', self)
self.bookmarkButton = QtWidgets.QAction(
QtGui.QIcon.fromTheme('bookmarks'),
image_factory.get_image('bookmarks'),
'Bookmarks', self)
self.bookmarkButton.setObjectName('bookmarkButton')
self.resetProfile = QtWidgets.QAction(
QtGui.QIcon.fromTheme('view-refresh'),
image_factory.get_image('reload'),
'Reset profile', self)
# Add buttons
@@ -77,43 +79,43 @@ class BookToolBar(QtWidgets.QToolBar):
self.fontSizeBox.setEditable(True)
self.paddingUp = QtWidgets.QAction(
QtGui.QIcon.fromTheme('format-indent-less'),
image_factory.get_image('format-indent-less'),
'Increase padding', self)
self.paddingUp.setObjectName('paddingUp')
self.paddingDown = QtWidgets.QAction(
QtGui.QIcon.fromTheme('format-indent-more'),
image_factory.get_image('format-indent-more'),
'Decrease padding', self)
self.paddingDown.setObjectName('paddingDown')
self.lineSpacingUp = QtWidgets.QAction(
QtGui.QIcon.fromTheme('format-line-spacing-triple'),
image_factory.get_image('format-line-spacing-triple'),
'Increase line spacing', self)
self.lineSpacingUp.setObjectName('lineSpacingUp')
self.lineSpacingDown = QtWidgets.QAction(
QtGui.QIcon.fromTheme('format-line-spacing-double'),
image_factory.get_image('format-line-spacing-double'),
'Decrease line spacing', self)
self.lineSpacingDown.setObjectName('lineSpacingDown')
self.alignLeft = QtWidgets.QAction(
QtGui.QIcon.fromTheme('format-justify-left'),
image_factory.get_image('format-justify-left'),
'Left align text', self)
self.alignLeft.setObjectName('alignLeft')
self.alignLeft.setCheckable(True)
self.alignRight = QtWidgets.QAction(
QtGui.QIcon.fromTheme('format-justify-right'),
image_factory.get_image('format-justify-right'),
'Right align text', self)
self.alignRight.setObjectName('alignRight')
self.alignRight.setCheckable(True)
self.alignCenter = QtWidgets.QAction(
QtGui.QIcon.fromTheme('format-justify-center'),
image_factory.get_image('format-justify-center'),
'Center align text', self)
self.alignCenter.setObjectName('alignCenter')
self.alignCenter.setCheckable(True)
self.alignJustify = QtWidgets.QAction(
QtGui.QIcon.fromTheme('format-justify-fill'),
image_factory.get_image('format-justify-fill'),
'Justify text', self)
self.alignJustify.setObjectName('alignJustify')
self.alignJustify.setCheckable(True)
@@ -184,26 +186,26 @@ class BookToolBar(QtWidgets.QToolBar):
# Comic view modification
self.zoomIn = QtWidgets.QAction(
QtGui.QIcon.fromTheme('zoom-in'),
image_factory.get_image('zoom-in'),
'Zoom in', self)
self.zoomIn.setObjectName('zoomIn')
self.zoomOut = QtWidgets.QAction(
QtGui.QIcon.fromTheme('zoom-out'),
image_factory.get_image('zoom-out'),
'Zoom Out', self)
self.zoomOut.setObjectName('zoomOut')
self.fitWidth = QtWidgets.QAction(
QtGui.QIcon.fromTheme('zoom-fit-width'),
image_factory.get_image('zoom-fit-width'),
'Fit Width', self)
self.fitWidth.setObjectName('fitWidth')
self.fitWidth.setCheckable(True)
self.bestFit = QtWidgets.QAction(
QtGui.QIcon.fromTheme('zoom-fit-best'),
image_factory.get_image('zoom-fit-best'),
'Best Fit', self)
self.bestFit.setObjectName('bestFit')
self.bestFit.setCheckable(True)
self.originalSize = QtWidgets.QAction(
QtGui.QIcon.fromTheme('zoom-original'),
image_factory.get_image('zoom-original'),
'Original size', self)
self.originalSize.setObjectName('originalSize')
self.originalSize.setCheckable(True)
@@ -320,27 +322,29 @@ class LibraryToolBar(QtWidgets.QToolBar):
self.setContextMenuPolicy(QtCore.Qt.PreventContextMenu)
self.setObjectName("LibraryToolBar")
image_factory = self.window().QImageFactory
# Buttons
self.addButton = QtWidgets.QAction(
QtGui.QIcon.fromTheme('add'), 'Add book', self)
image_factory.get_image('add'), 'Add book', self)
self.deleteButton = QtWidgets.QAction(
QtGui.QIcon.fromTheme('remove'), 'Delete book', self)
image_factory.get_image('remove'), 'Delete book', self)
self.colorButton = QtWidgets.QAction(
QtGui.QIcon.fromTheme('color-picker'), 'Library background color', self)
image_factory.get_image('color-picker'), 'Library background color', self)
self.colorButton.setObjectName('libraryBackground')
self.settingsButton = QtWidgets.QAction(
QtGui.QIcon.fromTheme('settings'), 'Settings', self)
image_factory.get_image('settings'), 'Settings', self)
self.settingsButton.setCheckable(True)
self.coverViewButton = QtWidgets.QAction(
QtGui.QIcon.fromTheme('view-grid'), 'View as covers', self)
image_factory.get_image('view-grid'), 'View as covers', self)
self.coverViewButton.setCheckable(True)
self.tableViewButton = QtWidgets.QAction(
QtGui.QIcon.fromTheme('table'), 'View as table', self)
image_factory.get_image('table'), 'View as table', self)
self.tableViewButton.setCheckable(True)
self.libraryFilterButton = QtWidgets.QToolButton(self)
self.libraryFilterButton.setIcon(QtGui.QIcon.fromTheme('view-readermode'))
self.libraryFilterButton.setIcon(image_factory.get_image('view-readermode'))
self.libraryFilterButton.setText('Filter library')
self.libraryFilterButton.setToolTip('Filter library')

View File

@@ -24,12 +24,16 @@
import os
import uuid
import zipfile
from PyQt5 import QtWidgets, QtGui, QtCore
from resources import pie_chart
from models import BookmarkProxyModel
from sorter import resize_image
from delegates import BookmarkDelegate
import popplerqt5
from rarfile import rarfile
from lector.models import BookmarkProxyModel
from lector.delegates import BookmarkDelegate
from lector.threaded import BackGroundCacheRefill
from lector.sorter import resize_image
class Tab(QtWidgets.QWidget):
@@ -37,6 +41,7 @@ class Tab(QtWidgets.QWidget):
super(Tab, self).__init__(parent)
self.parent = parent
self.metadata = metadata # Save progress data into this dictionary
self.are_we_doing_images_only = self.metadata['images_only']
self.masterLayout = QtWidgets.QHBoxLayout(self)
self.horzLayout = QtWidgets.QSplitter(self)
@@ -60,10 +65,9 @@ class Tab(QtWidgets.QWidget):
# such as in the case of comic book files,
# we want a QGraphicsView widget doing all the heavy lifting
# instead of a QTextBrowser
self.are_we_doing_images_only = self.metadata['images_only']
if self.are_we_doing_images_only: # Boolean
self.contentView = PliantQGraphicsView(self.window(), self)
self.contentView = PliantQGraphicsView(
self.metadata['path'], self.window(), self)
self.contentView.loadImage(chapter_content)
else:
self.contentView = PliantQTextBrowser(self.window(), self)
@@ -101,7 +105,7 @@ class Tab(QtWidgets.QWidget):
self.contentView.setObjectName('contentView')
self.contentView.verticalScrollBar().setSingleStep(7)
self.contentView.setHorizontalScrollBarPolicy(
QtCore.Qt.ScrollBarAlwaysOff)
QtCore.Qt.ScrollBarAsNeeded)
# See bookmark availability
if not self.metadata['bookmarks']:
@@ -134,6 +138,8 @@ class Tab(QtWidgets.QWidget):
self.horzLayout.addWidget(self.contentView)
self.horzLayout.addWidget(self.dockWidget)
title = self.metadata['title']
if self.are_we_doing_images_only:
title = os.path.basename(title)
self.parent.addTab(self, title)
# Hide mouse cursor timer
@@ -153,8 +159,11 @@ class Tab(QtWidgets.QWidget):
self.metadata['hash'],
1, QtCore.Qt.MatchExactly)
self.window().lib_ref.view_model.setData(
matching_item[0], self.metadata['last_accessed'], QtCore.Qt.UserRole + 12)
try:
self.window().lib_ref.view_model.setData(
matching_item[0], self.metadata['last_accessed'], QtCore.Qt.UserRole + 12)
except IndexError: # The file has been deleted
pass
def set_scroll_value(self, switch_widgets=True, search_data=None):
# TODO
@@ -177,7 +186,7 @@ class Tab(QtWidgets.QWidget):
# This avoids confusion with potentially duplicate phrases
# And the found result is at the top of the window
scroll_position = scroll_value * self.contentView.verticalScrollBar().maximum()
self.contentView.verticalScrollBar().setValue(scroll_position * 1.1)
self.contentView.verticalScrollBar().setValue(scroll_position * 1.02)
try:
search_text = self.metadata['position']['last_visible_text']
@@ -185,7 +194,17 @@ class Tab(QtWidgets.QWidget):
search_text = search_data[1]
if search_text:
self.contentView.find(search_text)
find_backward = False
find_forward = self.contentView.find(search_text)
if not find_forward:
find_backward = self.contentView.find(
search_text, QtGui.QTextDocument.FindBackward)
if find_backward:
current_scroll_position = self.contentView.verticalScrollBar().value()
new_scroll_position = current_scroll_position * .98
self.contentView.verticalScrollBar().setValue(new_scroll_position)
text_cursor = self.contentView.textCursor()
text_cursor.clearSelection()
@@ -197,9 +216,6 @@ class Tab(QtWidgets.QWidget):
self.window().tabWidget.setCurrentWidget(previous_widget)
def generate_position(self, is_read=False):
# TODO
# Calculate lines to incorporate into progress
total_chapters = len(self.metadata['content'])
current_chapter = 1
@@ -208,9 +224,30 @@ class Tab(QtWidgets.QWidget):
current_chapter = total_chapters
scroll_value = 1
# TODO
# Use this to generate position
# Generate block count @ time of first read
# Blocks are indexed from 0 up
blocks_per_chapter = []
total_blocks = 0
if not self.are_we_doing_images_only:
for i in self.metadata['content']:
chapter_html = i[1]
textDocument = QtGui.QTextDocument(None)
textDocument.setHtml(chapter_html)
block_count = textDocument.blockCount()
blocks_per_chapter.append(block_count)
total_blocks += block_count
self.metadata['position'] = {
'current_chapter': current_chapter,
'total_chapters': total_chapters,
'blocks_per_chapter': blocks_per_chapter,
'total_blocks': total_blocks,
'scroll_value': scroll_value,
'last_visible_text': None,
'is_read': is_read}
@@ -235,14 +272,6 @@ class Tab(QtWidgets.QWidget):
self.exit_fs.setContext(QtCore.Qt.ApplicationShortcut)
self.exit_fs.activated.connect(self.exit_fullscreen)
# TODO
# See why Ctrl + Q won't work on a non fullscreened contentView
# widget in case the following is in code
# self.exit_all = QtWidgets.QShortcut(
# QtGui.QKeySequence('Ctrl+Q'), self.contentView)
# self.exit_all.activated.connect(self.sneaky_exit)
def go_fullscreen(self):
if self.contentView.windowState() == QtCore.Qt.WindowFullScreen:
self.exit_fullscreen()
@@ -411,11 +440,12 @@ class Tab(QtWidgets.QWidget):
bookmark_menu = QtWidgets.QMenu()
editAction = bookmark_menu.addAction(
QtGui.QIcon.fromTheme('edit-rename'), 'Edit')
self.window().QImageFactory.get_image('edit-rename'), 'Edit')
deleteAction = bookmark_menu.addAction(
QtGui.QIcon.fromTheme('trash-empty'), 'Delete')
self.window().QImageFactory.get_image('trash-empty'), 'Delete')
action = bookmark_menu.exec_(self.dockListView.mapToGlobal(position))
action = bookmark_menu.exec_(
self.dockListView.mapToGlobal(position))
if action == editAction:
self.dockListView.edit(index)
@@ -444,76 +474,100 @@ class Tab(QtWidgets.QWidget):
class PliantQGraphicsView(QtWidgets.QGraphicsView):
def __init__(self, main_window, parent=None):
def __init__(self, filepath, main_window, parent=None):
super(PliantQGraphicsView, self).__init__(parent)
self.main_window = main_window
self.parent = parent
self.qimage = None # Will be needed to resize pdf
self.image_pixmap = None
self.ignore_wheel_event = False
self.ignore_wheel_event_number = 0
self.setDragMode(QtWidgets.QGraphicsView.ScrollHandDrag)
self.viewport().setCursor(QtCore.Qt.ArrowCursor)
self.common_functions = PliantWidgetsCommonFunctions(
self, self.main_window)
self.setMouseTracking(True)
self.image_cache = [None for _ in range(4)]
def loadImage(self, current_image):
self.thread = None
self.filepath = filepath
self.filetype = os.path.splitext(self.filepath)[1][1:]
if self.filetype == 'cbz':
self.book = zipfile.ZipFile(self.filepath)
elif self.filetype == 'cbr':
self.book = rarfile.RarFile(self.filepath)
elif self.filetype == 'pdf':
self.book = popplerqt5.Poppler.Document.load(self.filepath)
self.book.setRenderHint(
popplerqt5.Poppler.Document.Antialiasing
and popplerqt5.Poppler.Document.TextAntialiasing)
self.common_functions = PliantWidgetsCommonFunctions(
self, self.main_window)
# TODO
# For double page view: 1 before, 1 after
# Image panning with mouse
self.ignore_wheel_event = False
self.ignore_wheel_event_number = 0
self.setMouseTracking(True)
self.setDragMode(QtWidgets.QGraphicsView.ScrollHandDrag)
self.viewport().setCursor(QtCore.Qt.ArrowCursor)
content = self.parent.metadata['content']
image_paths = [i[1] for i in content]
def loadImage(self, current_page):
# TODO
# Threaded caching will still work here
# Look at a commit where it's not been deleted
# For double page view: 1 before, 1 after
all_pages = [i[1] for i in self.parent.metadata['content']]
def generate_image_cache(current_image):
def load_page(current_page):
image_pixmap = QtGui.QPixmap()
if self.filetype in ('cbz', 'cbr'):
page_data = self.book.read(current_page)
image_pixmap.loadFromData(page_data)
elif self.filetype == 'pdf':
page_data = self.book.page(current_page)
page_qimage = page_data.renderToImage(350, 350)
image_pixmap.convertFromImage(page_qimage)
return image_pixmap
def generate_image_cache(current_page):
print('Building image cache')
current_image_index = image_paths.index(current_image)
current_page_index = all_pages.index(current_page)
for i in (-1, 0, 1, 2):
try:
this_path = image_paths[current_image_index + i]
this_pixmap = QtGui.QPixmap()
this_pixmap.load(this_path)
self.image_cache[i + 1] = (this_path, this_pixmap)
this_page = all_pages[current_page_index + i]
this_pixmap = load_page(this_page)
self.image_cache[i + 1] = (this_page, this_pixmap)
except IndexError:
self.image_cache[i + 1] = None
def refill_cache(remove_value):
remove_index = self.image_cache.index(remove_value)
refill_pixmap = QtGui.QPixmap()
# Do NOT put a parent in here or the mother of all
# memory leaks will result
self.thread = BackGroundCacheRefill(
self.image_cache, remove_value,
self.filetype, self.book, all_pages)
self.thread.finished.connect(overwrite_cache)
self.thread.start()
if remove_index == 1:
first_path = self.image_cache[0][0]
self.image_cache.pop(3)
previous_path = image_paths[image_paths.index(first_path) - 1]
refill_pixmap.load(previous_path)
self.image_cache.insert(0, (previous_path, refill_pixmap))
else:
self.image_cache[0] = self.image_cache[1]
self.image_cache.pop(1)
try:
last_path = self.image_cache[2][0]
next_path = image_paths[image_paths.index(last_path) + 1]
refill_pixmap.load(next_path)
self.image_cache.append((next_path, refill_pixmap))
except (IndexError, TypeError):
self.image_cache.append(None)
def overwrite_cache():
self.image_cache = self.thread.image_cache
def check_cache(current_image):
def check_cache(current_page):
for i in self.image_cache:
if i:
if i[0] == current_image:
if i[0] == current_page:
return_pixmap = i[1]
refill_cache(i)
return return_pixmap
# No return happened so the image isn't in the cache
generate_image_cache(current_image)
generate_image_cache(current_page)
return_pixmap = None
while not return_pixmap:
return_pixmap = check_cache(current_image)
return_pixmap = check_cache(current_page)
self.image_pixmap = return_pixmap
self.resizeEvent()
@@ -655,10 +709,12 @@ class PliantQTextBrowser(QtWidgets.QTextBrowser):
if selected_word and selected_word != '':
selected_word = selected_word.split()[0]
defineAction = context_menu.addAction(
QtGui.QIcon.fromTheme('view-readermode'), f'Define "{selected_word}"')
self.window().QImageFactory.get_image('view-readermode'),
f'Define "{selected_word}"')
searchAction = context_menu.addAction(
QtGui.QIcon.fromTheme('search'), 'Search')
self.window().QImageFactory.get_image('search'),
'Search')
action = context_menu.exec_(self.sender().mapToGlobal(position))

View File

@@ -1,106 +0,0 @@
#!/usr/bin/env python3
# This file is a part of Lector, a Qt based ebook reader
# Copyright (C) 2017 BasioMeusPuga
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# TODO
# Account for files with passwords
import os
import time
import collections
from rarfile import rarfile
class ParseCBR:
def __init__(self, filename, temp_dir, file_md5):
self.filename = filename
self.book = None
self.temp_dir = temp_dir
self.file_md5 = file_md5
def read_book(self):
try:
self.book = rarfile.RarFile(self.filename)
except: # Specifying no exception types might be warranted here
print('Cannot parse ' + self.filename)
return
def get_title(self):
filename = os.path.basename(self.filename)
filename_proper = os.path.splitext(filename)[0]
return filename_proper
def get_author(self):
return None
def get_year(self):
creation_time = time.ctime(os.path.getctime(self.filename))
creation_year = creation_time.split()[-1]
return creation_year
def get_cover_image(self):
# The first image in the archive may not be the cover
# It is implied, however, that the first image in order
# will be the cover
image_list = [i.filename for i in self.book.infolist() if not i.isdir()]
image_list.sort()
cover_image_filename = image_list[0]
for i in self.book.infolist():
if not i.isdir():
if i.filename == cover_image_filename:
cover_image = self.book.read(i)
return cover_image
def get_isbn(self):
return
def get_tags(self):
return
def get_contents(self):
file_settings = {
'images_only': True}
extract_path = os.path.join(self.temp_dir, self.file_md5)
contents = []
# I'm currently choosing not to keep multiple files in memory
self.book.extractall(extract_path)
found_images = []
for i in os.walk(extract_path):
if i[2]: # Implies files were found
image_dir = i[0]
add_path_to_file = [
os.path.join(image_dir, j) for j in i[2]]
found_images.extend(add_path_to_file)
if not found_images:
print('Found nothing in ' + self.filename)
return None, file_settings
found_images.sort()
for count, i in enumerate(found_images):
page_name = 'Page ' + str(count + 1)
image_path = os.path.join(extract_path, i)
contents.append((page_name, image_path))
return contents, file_settings

View File

@@ -1,109 +0,0 @@
#!/usr/bin/env python3
# This file is a part of Lector, a Qt based ebook reader
# Copyright (C) 2017 BasioMeusPuga
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# TODO
# Account for files with passwords
import os
import time
import zipfile
import collections
class ParseCBZ:
def __init__(self, filename, temp_dir, file_md5):
self.filename = filename
self.book = None
self.temp_dir = temp_dir
self.file_md5 = file_md5
def read_book(self):
try:
self.book = zipfile.ZipFile(self.filename, mode='r', allowZip64=True)
except FileNotFoundError:
print('Invalid path for ' + self.filename)
return
except (KeyError, AttributeError, zipfile.BadZipFile):
print('Cannot parse ' + self.filename)
return
def get_title(self):
filename = os.path.basename(self.book.filename)
filename_proper = os.path.splitext(filename)[0]
return filename_proper
def get_author(self):
return None
def get_year(self):
creation_time = time.ctime(os.path.getctime(self.filename))
creation_year = creation_time.split()[-1]
return creation_year
def get_cover_image(self):
# The first image in the archive may not be the cover
# It is implied, however, that the first image in order
# will be the cover
image_list = [i.filename for i in self.book.infolist() if not i.is_dir()]
image_list.sort()
cover_image_filename = image_list[0]
for i in self.book.infolist():
if not i.is_dir():
if i.filename == cover_image_filename:
cover_image = self.book.read(i)
return cover_image
def get_isbn(self):
return
def get_tags(self):
return
def get_contents(self):
file_settings = {
'images_only': True}
extract_path = os.path.join(self.temp_dir, self.file_md5)
contents = []
# I'm currently choosing not to keep multiple files in memory
self.book.extractall(extract_path)
found_images = []
for i in os.walk(extract_path):
if i[2]: # Implies files were found
image_dir = i[0]
add_path_to_file = [
os.path.join(image_dir, j) for j in i[2]]
found_images.extend(add_path_to_file)
if not found_images:
print('Found nothing in ' + self.filename)
return None, file_settings
found_images.sort()
for count, i in enumerate(found_images):
page_name = 'Page ' + str(count + 1)
image_path = os.path.join(extract_path, i)
contents.append((page_name, image_path))
return contents, file_settings

78
parsers/comicbooks.py Normal file
View File

@@ -0,0 +1,78 @@
#!/usr/bin/env python3
# This file is a part of Lector, a Qt based ebook reader
# Copyright (C) 2017-18 BasioMeusPuga
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# TODO
# Account for files with passwords
import os
import time
import zipfile
from rarfile import rarfile
class ParseCOMIC:
def __init__(self, filename, *args):
self.filename = filename
self.book = None
self.image_list = None
self.book_extension = os.path.splitext(self.filename)
def read_book(self):
try:
if self.book_extension[1] == '.cbz':
self.book = zipfile.ZipFile(
self.filename, mode='r', allowZip64=True)
self.image_list = [i.filename for i in self.book.infolist() if not i.is_dir()]
elif self.book_extension[1] == '.cbr':
self.book = rarfile.RarFile(self.filename)
self.image_list = [i.filename for i in self.book.infolist() if not i.isdir()]
self.image_list.sort()
except: # Specifying no exception here is warranted
print('Cannot parse ' + self.filename)
return
def get_title(self):
return self.book_extension[0]
def get_author(self):
return None
def get_year(self):
creation_time = time.ctime(os.path.getctime(self.filename))
creation_year = creation_time.split()[-1]
return creation_year
def get_cover_image(self):
# The first image in the archive may not be the cover
# It is implied, however, that the first image in order
# will be the cover
return self.book.read(self.image_list[0])
def get_isbn(self):
return None
def get_tags(self):
return None
def get_contents(self):
file_settings = {'images_only': True}
contents = [(f'Page {count + 1}', i) for count, i in enumerate(self.image_list)]
return contents, file_settings

View File

@@ -28,9 +28,8 @@ class ParseEPUB:
# Maybe also include book description
self.book_ref = None
self.book = None
self.temp_dir = temp_dir
self.filename = filename
self.file_md5 = file_md5
self.extract_path = os.path.join(temp_dir, file_md5)
def read_book(self):
self.book_ref = EPUB(self.filename)
@@ -59,10 +58,9 @@ class ParseEPUB:
return self.book['tags']
def get_contents(self):
extract_path = os.path.join(self.temp_dir, self.file_md5)
zipfile.ZipFile(self.filename).extractall(extract_path)
zipfile.ZipFile(self.filename).extractall(self.extract_path)
self.book_ref.parse_chapters(temp_dir=self.temp_dir)
self.book_ref.parse_chapters(temp_dir=self.extract_path)
file_settings = {
'images_only': False}
return self.book['book_list'], file_settings

104
parsers/pdf.py Normal file
View File

@@ -0,0 +1,104 @@
#!/usr/bin/env python3
# This file is a part of Lector, a Qt based ebook reader
# Copyright (C) 2018 BasioMeusPuga
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import io
from PyQt5 import QtCore
from bs4 import BeautifulSoup
proceed = True
try:
import popplerqt5
except ImportError:
print('python-poppler-qt5 is not installed. Pdf files will not work.')
proceed = False
class ParsePDF:
def __init__(self, filename, *args):
self.filename = filename
self.book = None
self.metadata = None
def read_book(self):
if not proceed:
return
self.book = popplerqt5.Poppler.Document.load(self.filename)
if not self.book:
return
self.metadata = BeautifulSoup(self.book.metadata(), 'xml')
def get_title(self):
try:
title = self.metadata.find('title').text
return title.replace('\n', '')
except AttributeError:
return 'Unknown'
def get_author(self):
try:
author = self.metadata.find('creator').text
return author.replace('\n', '')
except AttributeError:
return 'Unknown'
def get_year(self):
try:
year = self.metadata.find('MetadataDate').text
return year.replace('\n', '')
except AttributeError:
return 9999
def get_cover_image(self):
self.book.setRenderHint(
popplerqt5.Poppler.Document.Antialiasing
and popplerqt5.Poppler.Document.TextAntialiasing)
cover_page = self.book.page(0)
cover_image = cover_page.renderToImage(300, 300)
return resize_image(cover_image)
def get_isbn(self):
return None
def get_tags(self):
try:
tags = self.metadata.find('Keywords').text
return tags.replace('\n', '')
except AttributeError:
return None
def get_contents(self):
file_settings = {'images_only': True}
contents = [(f'Page {i + 1}', i) for i in range(self.book.numPages())]
return contents, file_settings
def resize_image(cover_image):
cover_image = cover_image.scaled(
420, 600, QtCore.Qt.IgnoreAspectRatio)
byte_array = QtCore.QByteArray()
buffer = QtCore.QBuffer(byte_array)
buffer.open(QtCore.QIODevice.WriteOnly)
cover_image.save(buffer, 'jpg', 75)
cover_image_final = io.BytesIO(byte_array)
cover_image_final.seek(0)
return cover_image_final.getvalue()

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#5c616c; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 7 3 L 7 7 L 3 7 L 3 9 L 7 9 L 7 13 L 9 13 L 9 9 L 13 9 L 13 7 L 9 7 L 9 3 L 7 3 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 428 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#5c616c; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 4 0.00390625 C 4 0.00390625 3 0.00390625 3 1.0039062 L 3 15.003906 L 8 12.003906 L 13 15.003906 L 13 1.0039062 C 13 1.0039062 13 0.00390625 12 0.00390625 L 4 0.00390625 z M 7 3.0039062 L 9 3.0039062 L 9 5.0039062 L 11 5.0039062 L 11 7.0039062 L 9 7.0039062 L 9 9.0039062 L 7 9.0039062 L 7 7.0039062 L 5 7.0039062 L 5 5.0039062 L 7 5.0039062 L 7 3.0039062 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 703 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#5c616c; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 8 0.390625 L 5.8808594 5.8847656 L 0 6.2011719 L 4.5722656 9.9160156 L 3.0566406 15.607422 L 8 12.40625 L 12.943359 15.607422 L 11.427734 9.9160156 L 16 6.2011719 L 10.119141 5.8847656 L 8 0.390625 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 546 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#5c616c; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 8 1 C 7.79297 1.66364 7.5132275 2.3110656 7.2109375 2.9472656 C 5.6704375 6.0974656 3.2599437 8.2540875 3.0273438 10.242188 C 3.0213438 10.271888 3.0052 10.304384 3 10.333984 L 3.0195312 10.339844 C 3.0145313 10.408244 3 10.476722 3 10.544922 C 3 13.005122 5.2386 15 8 15 C 10.7614 15 13 13.005122 13 10.544922 C 13 10.476722 12.985469 10.408214 12.980469 10.339844 L 13 10.333984 C 12.995 10.304484 12.978956 10.271887 12.972656 10.242188 C 12.740106 8.2539875 10.329662 6.0973656 8.7890625 2.9472656 C 8.4867825 2.3110456 8.20702 1.6636 8 1 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 891 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#5c616c; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 12.210938 1 C 11.998438 1 11.784141 1.0830469 11.619141 1.2480469 L 9.9902344 2.8886719 L 13.109375 6.0078125 L 14.75 4.3789062 C 15.08 4.0489063 15.08 3.5272656 14.75 3.1972656 L 12.800781 1.2480469 C 12.635781 1.0830469 12.423437 1 12.210938 1 z M 8.8691406 4.0078125 L 0.99023438 11.888672 L 0.99023438 15.007812 L 4.109375 15.007812 L 11.990234 7.1289062 L 8.8691406 4.0078125 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 729 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#5c616c; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 1 1 L 1 3 L 15 3 L 15 1 L 1 1 z M 1 5 L 1 7 L 9 7.0039062 L 9 5.0039062 L 1 5 z M 15 5.0039062 L 10 8.0039062 L 15 11.003906 L 15 5.0039062 z M 1 9 L 1 11 L 9 11 L 9 9 L 1 9 z M 1 13 L 1 15 L 15 15 L 15 13 L 1 13 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 561 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#5c616c; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 1 1 L 1 3 L 15 3 L 15 1 L 1 1 z M 1 5.0039062 L 1 11.003906 L 6 8.0039062 L 1 5.0039062 z M 7 5.0039062 L 7 7.0039062 L 15 7.0039062 L 15 5.0039062 L 7 5.0039062 z M 15 9 L 7 9.0039062 L 7 11.003906 L 15 11 L 15 9 z M 1 13 L 1 15 L 15 15 L 15 13 L 1 13 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 601 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#5c616c; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 1 1 L 1 3 L 15 3 L 15 1 L 1 1 z M 4 5.0039062 L 4 7.0039062 L 12 7.0039062 L 12 5.0039062 L 4 5.0039062 z M 4 9.0039062 L 4 11.003906 L 12 11.003906 L 12 9.0039062 L 4 9.0039062 z M 1 13 L 1 15 L 15 15 L 15 13 L 1 13 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 565 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#5c616c; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 1 1 L 1 3 L 15 3 L 15 1 L 1 1 z M 1 5.0039062 L 1 7.0039062 L 15 7.0039062 L 15 5.0039062 L 1 5.0039062 z M 1 9.0039062 L 1 11.003906 L 15 11.003906 L 15 9.0039062 L 1 9.0039062 z M 1 13 L 1 15 L 15 15 L 15 13 L 1 13 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 565 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#5c616c; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 1 1 L 1 3 L 15 3 L 15 1 L 1 1 z M 1 5.0039062 L 1 7.0039062 L 9 7.0039062 L 9 5.0039062 L 1 5.0039062 z M 1 9.0039062 L 1 11.003906 L 9 11.003906 L 9 9.0039062 L 1 9.0039062 z M 1 13 L 1 15 L 15 15 L 15 13 L 1 13 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 561 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#5c616c; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 1 1 L 1 3 L 15 3 L 15 1 L 1 1 z M 7 5.0039062 L 7 7.0039062 L 15 7.0039062 L 15 5.0039062 L 7 5.0039062 z M 7 9.0039062 L 7 11.003906 L 15 11.003906 L 15 9.0039062 L 7 9.0039062 z M 1 13 L 1 15 L 15 15 L 15 13 L 1 13 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 565 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#5c616c; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 5 3 L 5 4 L 2 4 L 2 12 L 5 12 L 5 13 L 14 13 L 14 10 L 5 10 L 5 11 L 3 11 L 3 9 L 4 9 L 4 7 L 3 7 L 3 5 L 5 5 L 5 6 L 14 6 L 14 3 L 5 3 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 484 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#5c616c; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 5 2 L 5 3 L 2 3 L 2 13 L 5 13 L 5 14 L 14 14 L 14 11 L 5 11 L 5 12 L 3 12 L 3 9 L 4 9 L 4 7 L 3 7 L 3 4 L 5 4 L 5 5 L 14 5 L 14 2 L 5 2 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 484 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#5c616c; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 7 1 L 2 15 L 4.5 15 L 5.5625 12 L 10.4375 12 L 11.5 15 L 14.28125 15 L 9 1 L 7 1 z M 14 1 A 1 1 0 0 0 13 2 A 1 1 0 0 0 14 3 A 1 1 0 0 0 15 2 A 1 1 0 0 0 14 1 z M 14 4 A 1 1 0 0 0 13 5 A 1 1 0 0 0 14 6 A 1 1 0 0 0 15 5 A 1 1 0 0 0 14 4 z M 8 5 L 9.75 10 L 6.25 10 L 8 5 z M 14 7 A 1 1 0 0 0 13 8 A 1 1 0 0 0 14 9 A 1 1 0 0 0 15 8 A 1 1 0 0 0 14 7 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 694 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#5c616c; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="m4.5 3a3.5 5 0 0 0 -3.5 5 3.5 5 0 0 0 3.5 5 3.5 5 0 0 0 3.5 -5 3.5 5 0 0 0 -3.5 -5zm3.5 5a3.5 5 0 0 0 3.5 5 3.5 5 0 0 0 3.5 -5 3.5 5 0 0 0 -3.5 -5 3.5 5 0 0 0 -3.5 5zm-3 0a2 2 0 0 1 2 2 2 2 0 0 1 -2 2 2 2 0 0 1 -2 -2 2 2 0 0 1 2 -2zm7 0a2 2 0 0 1 2 2 2 2 0 0 1 -2 2 2 2 0 0 1 -2 -2 2 2 0 0 1 2 -2z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 642 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#5c616c; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 8 1.015625 C 4.134 1.015625 1 4.149625 1 8.015625 C 1 11.881625 4.134 15.015625 8 15.015625 C 11.1748 15.015625 13.86145 12.912425 14.71875 10.015625 L 12.5625 10.015625 C 11.78823 11.775125 10.0457 13.015625 8 13.015625 C 5.2386 13.015625 3 10.777025 3 8.015625 C 3 5.254225 5.2386 3.015625 8 3.015625 C 9.3816 3.015625 10.615525 3.59065 11.515625 4.5 L 9.0058594 7.015625 L 15.005859 7.015625 L 15.005859 1.015625 L 12.953125 3.0683594 C 11.683125 1.8033594 9.9339063 1.015625 8.0039062 1.015625 L 8 1.015625 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 859 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#5c616c; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 3 7 L 3 9 L 13 9 L 13 7 L 3 7 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 378 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#5c616c; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 6.25 1 L 6.0957031 2.84375 A 5.5 5.5 0 0 0 4.4882812 3.7734375 L 2.8125 2.984375 L 1.0625 6.015625 L 2.5839844 7.0722656 A 5.5 5.5 0 0 0 2.5 8 A 5.5 5.5 0 0 0 2.5800781 8.9316406 L 1.0625 9.984375 L 2.8125 13.015625 L 4.484375 12.228516 A 5.5 5.5 0 0 0 6.0957031 13.152344 L 6.2460938 15.001953 L 9.7460938 15.001953 L 9.9003906 13.158203 A 5.5 5.5 0 0 0 11.507812 12.228516 L 13.183594 13.017578 L 14.933594 9.9863281 L 13.412109 8.9296875 A 5.5 5.5 0 0 0 13.496094 8.0019531 A 5.5 5.5 0 0 0 13.416016 7.0703125 L 14.933594 6.0175781 L 13.183594 2.9863281 L 11.511719 3.7734375 A 5.5 5.5 0 0 0 9.9003906 2.8496094 L 9.75 1 L 6.25 1 z M 8 6 A 2 2 0 0 1 10 8 A 2 2 0 0 1 8 10 A 2 2 0 0 1 6 8 A 2 2 0 0 1 8 6 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#5c616c; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="m1 1v14h14v-14h-14zm2 2h2v2h-2v-2zm4 0h2v2h-2v-2zm4 0h2v2h-2v-2zm-8 4h2v2h-2v-2zm4 0h2v2h-2v-2zm4 0h2v2h-2v-2zm-8 4h2v2h-2v-2zm4 0h2v2h-2v-2zm4 0h2v2h-2v-2z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 501 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#5c616c; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 6 0.9921875 C 5 0.9921875 5 1.9921875 5 1.9921875 L 2 1.9921875 C 2 1.9921875 1 1.9956938 1 2.9960938 L 1 3.9960938 L 14 3.9921875 L 14 2.9960938 C 14 1.9960938 13 1.9921875 13 1.9921875 L 10 1.9921875 C 10 1.9921875 10 0.9921875 9 0.9921875 L 6 0.9921875 z M 2 4.9960938 L 2 13.996094 C 2.00005 14.519674 2.47642 14.996044 3 14.996094 L 12 14.996094 C 12.52358 14.996044 12.99995 14.519674 13 13.996094 L 13 4.9960938 L 2 4.9960938 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 781 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#5c616c; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 2 2.0039062 C 1 2.0039062 1 3.0039062 1 3.0039062 L 1 7.0039062 L 3 7.0039062 L 3 4.0039062 L 6 4.0039062 L 6 2.0039062 L 2 2.0039062 z M 10 2.0039062 L 10 4.0039062 L 13 4.0039062 L 13 7.0039062 L 15 7.0039062 L 15 3.0039062 C 15 2.0039062 14 2.0039062 14 2.0039062 L 10 2.0039062 z M 1 9.0039062 L 1 13.003906 C 1 14.003906 2 14.003906 2 14.003906 L 6 14.003906 L 6 12.003906 L 3 12.003906 L 3 9.0039062 L 1 9.0039062 z M 13 9.0039062 L 13 12.003906 L 10 12.003906 L 10 14.003906 L 14 14.003906 C 14 14.003906 15 14.003906 15 13.003906 L 15 9.0039062 L 13 9.0039062 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 916 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#5c616c; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 1.25 3.0039062 C 1.1115 3.0039063 1 3.1154062 1 3.2539062 L 1 4.7539062 C 1 4.8924062 1.1115 5.0039062 1.25 5.0039062 L 2.75 5.0039062 C 2.8885 5.0039062 3 4.8924062 3 4.7539062 L 3 3.2539062 C 3 3.1154062 2.8885 3.0039062 2.75 3.0039062 L 1.25 3.0039062 z M 5.25 3.0039062 C 5.1115 3.0039063 5 3.1154062 5 3.2539062 L 5 4.7539062 C 5 4.8924062 5.1115 5.0039062 5.25 5.0039062 L 6.75 5.0039062 C 6.8885 5.0039062 7 4.8924062 7 4.7539062 L 7 3.2539062 C 7 3.1154062 6.8885 3.0039062 6.75 3.0039062 L 5.25 3.0039062 z M 9.25 3.0039062 C 9.1115 3.0039063 9 3.1154062 9 3.2539062 L 9 4.7539062 C 9 4.8924062 9.1115 5.0039062 9.25 5.0039062 L 10.75 5.0039062 C 10.8885 5.0039062 11 4.8924062 11 4.7539062 L 11 3.2539062 C 11 3.1154062 10.8885 3.0039062 10.75 3.0039062 L 9.25 3.0039062 z M 13.25 3.0039062 C 13.1115 3.0039063 13 3.1154062 13 3.2539062 L 13 4.7539062 C 13 4.8924062 13.1115 5.0039062 13.25 5.0039062 L 14.75 5.0039062 C 14.8885 5.0039062 15 4.8924062 15 4.7539062 L 15 3.2539062 C 15 3.1154062 14.8885 3.0039062 14.75 3.0039062 L 13.25 3.0039062 z M 1.25 7.0039062 C 1.1115 7.0039063 1 7.1154063 1 7.2539062 L 1 8.7539062 C 1 8.8924063 1.1115 9.0039062 1.25 9.0039062 L 2.75 9.0039062 C 2.8885 9.0039062 3 8.8924063 3 8.7539062 L 3 7.2539062 C 3 7.1154063 2.8885 7.0039062 2.75 7.0039062 L 1.25 7.0039062 z M 5.25 7.0039062 C 5.1115 7.0039063 5 7.1154063 5 7.2539062 L 5 8.7539062 C 5 8.8924063 5.1115 9.0039062 5.25 9.0039062 L 6.75 9.0039062 C 6.8885 9.0039062 7 8.8924063 7 8.7539062 L 7 7.2539062 C 7 7.1154063 6.8885 7.0039062 6.75 7.0039062 L 5.25 7.0039062 z M 9.25 7.0039062 C 9.1115 7.0039063 9 7.1154063 9 7.2539062 L 9 8.7539062 C 9 8.8924063 9.1115 9.0039062 9.25 9.0039062 L 10.75 9.0039062 C 10.8885 9.0039062 11 8.8924063 11 8.7539062 L 11 7.2539062 C 11 7.1154063 10.8885 7.0039062 10.75 7.0039062 L 9.25 7.0039062 z M 13.25 7.0039062 C 13.1115 7.0039063 13 7.1154063 13 7.2539062 L 13 8.7539062 C 13 8.8924063 13.1115 9.0039062 13.25 9.0039062 L 14.75 9.0039062 C 14.8885 9.0039062 15 8.8924063 15 8.7539062 L 15 7.2539062 C 15 7.1154063 14.8885 7.0039062 14.75 7.0039062 L 13.25 7.0039062 z M 1.25 11.003906 C 1.1115 11.003906 1 11.115406 1 11.253906 L 1 12.753906 C 1 12.892406 1.1115 13.003906 1.25 13.003906 L 2.75 13.003906 C 2.8885 13.003906 3 12.892406 3 12.753906 L 3 11.253906 C 3 11.115406 2.8885 11.003906 2.75 11.003906 L 1.25 11.003906 z M 5.25 11.003906 C 5.1115 11.003906 5 11.115406 5 11.253906 L 5 12.753906 C 5 12.892406 5.1115 13.003906 5.25 13.003906 L 6.75 13.003906 C 6.8885 13.003906 7 12.892406 7 12.753906 L 7 11.253906 C 7 11.115406 6.8885 11.003906 6.75 11.003906 L 5.25 11.003906 z M 9.25 11.003906 C 9.1115 11.003906 9 11.115406 9 11.253906 L 9 12.753906 C 9 12.892406 9.1115 13.003906 9.25 13.003906 L 10.75 13.003906 C 10.8885 13.003906 11 12.892406 11 12.753906 L 11 11.253906 C 11 11.115406 10.8885 11.003906 10.75 11.003906 L 9.25 11.003906 z M 13.25 11.003906 C 13.1115 11.003906 13 11.115406 13 11.253906 L 13 12.753906 C 13 12.892406 13.1115 13.003906 13.25 13.003906 L 14.75 13.003906 C 14.8885 13.003906 15 12.892406 15 12.753906 L 15 11.253906 C 15 11.115406 14.8885 11.003906 14.75 11.003906 L 13.25 11.003906 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#5c616c; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 10.029297 1 C 9.8819169 1.003 9.7293425 1.0150094 9.5703125 1.0371094 C 9.0034025 1.1159094 8.3186875 1.3914781 7.5546875 1.7988281 C 6.0140875 0.94567812 4.8137406 0.89374688 3.8066406 1.1542969 C 2.7378406 1.4308069 1.868925 1.8823869 0.515625 1.8417969 L 0 1.8261719 L 0 16 L 15 16 L 15 1.84375 L 14.482422 1.8613281 C 12.965822 1.9165281 12.211922 1.464645 11.232422 1.171875 C 10.865122 1.062075 10.471417 0.99098 10.029297 1 z M 5.21875 1.9941406 C 5.71774 2.0327406 6.2822 2.213495 7 2.609375 L 7 11.333984 C 5.8956 10.692224 4.7902063 10.643969 3.8164062 10.886719 C 3.1632062 11.049539 2.5692 11.237652 2 11.388672 L 2 2.6621094 C 2.8021 2.5141794 3.4740875 2.2830225 4.0546875 2.1328125 C 4.2857975 2.0730125 4.5091312 2.02398 4.7382812 2 C 4.8933012 1.9838 5.05242 1.9813406 5.21875 1.9941406 z M 10.337891 2.0019531 C 10.543791 2.0284531 10.742569 2.079065 10.949219 2.140625 C 11.483649 2.300375 12.1426 2.5531719 13 2.7011719 L 13 11.384766 C 12.43016 11.232366 11.837453 11.042719 11.189453 10.880859 C 10.209613 10.636099 9.0981 10.696078 8 11.367188 L 8 2.6679688 C 8.70328 2.2824487 9.2453875 2.0716725 9.6796875 2.0078125 C 9.9189475 1.9726125 10.131991 1.9756531 10.337891 2.0019531 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#5c616c; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 8 3.0039062 C 6.4492 3.0190063 4.8879094 3.3732319 3.5371094 4.1386719 C 2.9987094 4.4892919 2.3523344 4.9421175 1.8652344 5.3984375 C 1.0987444 6.1488575 0.4427 7.0244062 0 8.0039062 C 1.2149 10.683506 3.8859187 12.6474 6.8242188 12.9375 C 8.7516188 13.15561 10.768591 12.822631 12.462891 11.869141 C 13.001291 11.518521 13.647666 11.065695 14.134766 10.609375 C 14.901256 9.858955 15.5573 8.9834063 16 8.0039062 C 14.785 5.3245062 12.114181 3.3601125 9.1757812 3.0703125 C 8.7859013 3.0248425 8.39251 3.0038963 8 3.0039062 z M 8 5.0019531 L 8 5.0039062 C 9.607 4.9683062 11.0303 6.4057062 11 8.0039062 C 11.0515 9.7703063 9.2909813 11.294844 7.5507812 10.964844 C 5.7931812 10.758504 4.5587188 8.7851344 5.1367188 7.1152344 C 5.5058788 5.8858344 6.7125 4.9866531 8 5.0019531 z M 8 7.0039062 A 1 1 0 0 0 7 8.0039062 A 1 1 0 0 0 8 9.0039062 A 1 1 0 0 0 9 8.0039062 A 1 1 0 0 0 8 7.0039062 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#5c616c; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 3.1894531 2.0039062 C 2.5267531 2.0039062 2.0019531 2.5527963 2.0019531 3.2226562 L 2.0019531 7.0039062 L 4.0019531 7.0039062 L 4.0019531 4.0039062 L 7.0019531 4.0039062 L 7.0019531 2.0039062 L 3.1894531 2.0039062 z M 9.0019531 2.0039062 L 9.0019531 4.0039062 L 12.001953 4.0039062 L 12.001953 7.0039062 L 14.001953 7.0039062 L 14.001953 3.2226562 C 14.001953 2.5528963 13.477153 2.0039062 12.814453 2.0039062 L 9.0019531 2.0039062 z M 2.0019531 9.0039062 L 2.0019531 12.785156 C 2.0019531 13.454916 2.5267531 14.003906 3.1894531 14.003906 L 7.0019531 14.003906 L 7.0019531 12.003906 L 4.0019531 12.003906 L 4.0019531 9.0039062 L 2.0019531 9.0039062 z M 12.001953 9.0039062 L 12.001953 12.003906 L 9.0019531 12.003906 L 9.0019531 14.003906 L 12.814453 14.003906 C 13.477153 14.003906 14.001953 13.455016 14.001953 12.785156 L 14.001953 9.0039062 L 12.001953 9.0039062 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#5c616c; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 3.1875 2 C 2.5248 2 2 2.54895 2 3.21875 L 2 7 L 4 7 L 4 4 L 7 4 L 7 2 L 3.1875 2 z M 9 2 L 9 4 L 12 4 L 12 7 L 14 7 L 14 3.21875 C 14 2.54885 13.4755 2 12.8125 2 L 9 2 z M 7 5 L 7 11 L 9 11 L 9 5 L 7 5 z M 6 6 L 4 8 L 6 10 L 6 6 z M 10 6 L 10 10 L 12 8 L 10 6 z M 2 9 L 2 12.78125 C 2 13.45125 2.5248 14 3.1875 14 L 7 14 L 7 12 L 4 12 L 4 9 L 2 9 z M 12 9 L 12 12 L 9 12 L 9 14 L 12.8125 14 C 13.4755 14 14 13.45125 14 12.78125 L 14 9 L 12 9 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 790 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#5c616c; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 3 2 C 2.446 2 2 2.446 2 3 L 2 13 C 2 13.554 2.446 14 3 14 L 13 14 C 13.554 14 14 13.554 14 13 L 14 3 C 14 2.446 13.554 2 13 2 L 3 2 z M 7 5 L 9 5 L 9 7 L 11 7 L 11 9 L 9 9 L 9 11 L 7 11 L 7 9 L 5 9 L 5 7 L 7 7 L 7 5 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 564 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#5c616c; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 3 2 C 2.446 2 2 2.446 2 3 L 2 13 C 2 13.554 2.446 14 3 14 L 13 14 C 13.554 14 14 13.554 14 13 L 14 3 C 14 2.446 13.554 2 13 2 L 3 2 z M 7 5 L 9 5 L 9 11 L 7 11 L 7 7 L 6 7 L 6 6 C 6 6 7 6 7 5 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 540 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#5c616c; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 3 2 C 2.446 2 2 2.446 2 3 L 2 13 C 2 13.554 2.446 14 3 14 L 13 14 C 13.554 14 14 13.554 14 13 L 14 3 C 14 2.446 13.554 2 13 2 L 3 2 z M 5 7 L 11 7 L 11 9 L 5 9 L 5 7 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 514 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#d3dae3; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 7 3 L 7 7 L 3 7 L 3 9 L 7 9 L 7 13 L 9 13 L 9 9 L 13 9 L 13 7 L 9 7 L 9 3 L 7 3 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 428 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 22 22">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#d3dae3; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 4 0.00390625 C 4 0.00390625 3 0.00390625 3 1.0039062 L 3 15.003906 L 8 12.003906 L 13 15.003906 L 13 1.0039062 C 13 1.0039062 13 0.00390625 12 0.00390625 L 4 0.00390625 z M 7 3.0039062 L 9 3.0039062 L 9 5.0039062 L 11 5.0039062 L 11 7.0039062 L 9 7.0039062 L 9 9.0039062 L 7 9.0039062 L 7 7.0039062 L 5 7.0039062 L 5 5.0039062 L 7 5.0039062 L 7 3.0039062 z" transform="translate(3 3)"/>
</svg>

After

Width:  |  Height:  |  Size: 703 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#d3dae3; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 8 0.390625 L 5.8808594 5.8847656 L 0 6.2011719 L 4.5722656 9.9160156 L 3.0566406 15.607422 L 8 12.40625 L 12.943359 15.607422 L 11.427734 9.9160156 L 16 6.2011719 L 10.119141 5.8847656 L 8 0.390625 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 546 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#d3dae3; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 8 1 C 7.79297 1.66364 7.5132275 2.3110656 7.2109375 2.9472656 C 5.6704375 6.0974656 3.2599437 8.2540875 3.0273438 10.242188 C 3.0213438 10.271888 3.0052 10.304384 3 10.333984 L 3.0195312 10.339844 C 3.0145313 10.408244 3 10.476722 3 10.544922 C 3 13.005122 5.2386 15 8 15 C 10.7614 15 13 13.005122 13 10.544922 C 13 10.476722 12.985469 10.408214 12.980469 10.339844 L 13 10.333984 C 12.995 10.304484 12.978956 10.271887 12.972656 10.242188 C 12.740106 8.2539875 10.329662 6.0973656 8.7890625 2.9472656 C 8.4867825 2.3110456 8.20702 1.6636 8 1 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 891 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#d3dae3; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 12.210938 1 C 11.998438 1 11.784141 1.0830469 11.619141 1.2480469 L 9.9902344 2.8886719 L 13.109375 6.0078125 L 14.75 4.3789062 C 15.08 4.0489063 15.08 3.5272656 14.75 3.1972656 L 12.800781 1.2480469 C 12.635781 1.0830469 12.423437 1 12.210938 1 z M 8.8691406 4.0078125 L 0.99023438 11.888672 L 0.99023438 15.007812 L 4.109375 15.007812 L 11.990234 7.1289062 L 8.8691406 4.0078125 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 729 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#d3dae3; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 1 1 L 1 3 L 15 3 L 15 1 L 1 1 z M 1 5 L 1 7 L 9 7.0039062 L 9 5.0039062 L 1 5 z M 15 5.0039062 L 10 8.0039062 L 15 11.003906 L 15 5.0039062 z M 1 9 L 1 11 L 9 11 L 9 9 L 1 9 z M 1 13 L 1 15 L 15 15 L 15 13 L 1 13 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 561 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#d3dae3; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 1 1 L 1 3 L 15 3 L 15 1 L 1 1 z M 1 5.0039062 L 1 11.003906 L 6 8.0039062 L 1 5.0039062 z M 7 5.0039062 L 7 7.0039062 L 15 7.0039062 L 15 5.0039062 L 7 5.0039062 z M 15 9 L 7 9.0039062 L 7 11.003906 L 15 11 L 15 9 z M 1 13 L 1 15 L 15 15 L 15 13 L 1 13 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 601 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#d3dae3; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 1 1 L 1 3 L 15 3 L 15 1 L 1 1 z M 4 5.0039062 L 4 7.0039062 L 12 7.0039062 L 12 5.0039062 L 4 5.0039062 z M 4 9.0039062 L 4 11.003906 L 12 11.003906 L 12 9.0039062 L 4 9.0039062 z M 1 13 L 1 15 L 15 15 L 15 13 L 1 13 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 565 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#d3dae3; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 1 1 L 1 3 L 15 3 L 15 1 L 1 1 z M 1 5.0039062 L 1 7.0039062 L 15 7.0039062 L 15 5.0039062 L 1 5.0039062 z M 1 9.0039062 L 1 11.003906 L 15 11.003906 L 15 9.0039062 L 1 9.0039062 z M 1 13 L 1 15 L 15 15 L 15 13 L 1 13 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 565 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#d3dae3; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 1 1 L 1 3 L 15 3 L 15 1 L 1 1 z M 1 5.0039062 L 1 7.0039062 L 9 7.0039062 L 9 5.0039062 L 1 5.0039062 z M 1 9.0039062 L 1 11.003906 L 9 11.003906 L 9 9.0039062 L 1 9.0039062 z M 1 13 L 1 15 L 15 15 L 15 13 L 1 13 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 561 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#d3dae3; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 1 1 L 1 3 L 15 3 L 15 1 L 1 1 z M 7 5.0039062 L 7 7.0039062 L 15 7.0039062 L 15 5.0039062 L 7 5.0039062 z M 7 9.0039062 L 7 11.003906 L 15 11.003906 L 15 9.0039062 L 7 9.0039062 z M 1 13 L 1 15 L 15 15 L 15 13 L 1 13 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 565 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#d3dae3; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 5 3 L 5 4 L 2 4 L 2 12 L 5 12 L 5 13 L 14 13 L 14 10 L 5 10 L 5 11 L 3 11 L 3 9 L 4 9 L 4 7 L 3 7 L 3 5 L 5 5 L 5 6 L 14 6 L 14 3 L 5 3 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 484 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#d3dae3; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 5 2 L 5 3 L 2 3 L 2 13 L 5 13 L 5 14 L 14 14 L 14 11 L 5 11 L 5 12 L 3 12 L 3 9 L 4 9 L 4 7 L 3 7 L 3 4 L 5 4 L 5 5 L 14 5 L 14 2 L 5 2 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 484 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 22 22">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#d3dae3; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 7 1 L 2 15 L 4.5 15 L 5.5625 12 L 10.4375 12 L 11.5 15 L 14.28125 15 L 9 1 L 7 1 z M 14 1 A 1 1 0 0 0 13 2 A 1 1 0 0 0 14 3 A 1 1 0 0 0 15 2 A 1 1 0 0 0 14 1 z M 14 4 A 1 1 0 0 0 13 5 A 1 1 0 0 0 14 6 A 1 1 0 0 0 15 5 A 1 1 0 0 0 14 4 z M 8 5 L 9.75 10 L 6.25 10 L 8 5 z M 14 7 A 1 1 0 0 0 13 8 A 1 1 0 0 0 14 9 A 1 1 0 0 0 15 8 A 1 1 0 0 0 14 7 z" transform="translate(3 3)"/>
</svg>

After

Width:  |  Height:  |  Size: 694 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#d3dae3; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="m4.5 3a3.5 5 0 0 0 -3.5 5 3.5 5 0 0 0 3.5 5 3.5 5 0 0 0 3.5 -5 3.5 5 0 0 0 -3.5 -5zm3.5 5a3.5 5 0 0 0 3.5 5 3.5 5 0 0 0 3.5 -5 3.5 5 0 0 0 -3.5 -5 3.5 5 0 0 0 -3.5 5zm-3 0a2 2 0 0 1 2 2 2 2 0 0 1 -2 2 2 2 0 0 1 -2 -2 2 2 0 0 1 2 -2zm7 0a2 2 0 0 1 2 2 2 2 0 0 1 -2 2 2 2 0 0 1 -2 -2 2 2 0 0 1 2 -2z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 642 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#d3dae3; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 8 1.015625 C 4.134 1.015625 1 4.149625 1 8.015625 C 1 11.881625 4.134 15.015625 8 15.015625 C 11.1748 15.015625 13.86145 12.912425 14.71875 10.015625 L 12.5625 10.015625 C 11.78823 11.775125 10.0457 13.015625 8 13.015625 C 5.2386 13.015625 3 10.777025 3 8.015625 C 3 5.254225 5.2386 3.015625 8 3.015625 C 9.3816 3.015625 10.615525 3.59065 11.515625 4.5 L 9.0058594 7.015625 L 15.005859 7.015625 L 15.005859 1.015625 L 12.953125 3.0683594 C 11.683125 1.8033594 9.9339063 1.015625 8.0039062 1.015625 L 8 1.015625 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 859 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#d3dae3; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 3 7 L 3 9 L 13 9 L 13 7 L 3 7 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 378 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#d3dae3; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 6.25 1 L 6.0957031 2.84375 A 5.5 5.5 0 0 0 4.4882812 3.7734375 L 2.8125 2.984375 L 1.0625 6.015625 L 2.5839844 7.0722656 A 5.5 5.5 0 0 0 2.5 8 A 5.5 5.5 0 0 0 2.5800781 8.9316406 L 1.0625 9.984375 L 2.8125 13.015625 L 4.484375 12.228516 A 5.5 5.5 0 0 0 6.0957031 13.152344 L 6.2460938 15.001953 L 9.7460938 15.001953 L 9.9003906 13.158203 A 5.5 5.5 0 0 0 11.507812 12.228516 L 13.183594 13.017578 L 14.933594 9.9863281 L 13.412109 8.9296875 A 5.5 5.5 0 0 0 13.496094 8.0019531 A 5.5 5.5 0 0 0 13.416016 7.0703125 L 14.933594 6.0175781 L 13.183594 2.9863281 L 11.511719 3.7734375 A 5.5 5.5 0 0 0 9.9003906 2.8496094 L 9.75 1 L 6.25 1 z M 8 6 A 2 2 0 0 1 10 8 A 2 2 0 0 1 8 10 A 2 2 0 0 1 6 8 A 2 2 0 0 1 8 6 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#d3dae3; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="m1 1v14h14v-14h-14zm2 2h2v2h-2v-2zm4 0h2v2h-2v-2zm4 0h2v2h-2v-2zm-8 4h2v2h-2v-2zm4 0h2v2h-2v-2zm4 0h2v2h-2v-2zm-8 4h2v2h-2v-2zm4 0h2v2h-2v-2zm4 0h2v2h-2v-2z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 501 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#d3dae3; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 6 0.9921875 C 5 0.9921875 5 1.9921875 5 1.9921875 L 2 1.9921875 C 2 1.9921875 1 1.9956938 1 2.9960938 L 1 3.9960938 L 14 3.9921875 L 14 2.9960938 C 14 1.9960938 13 1.9921875 13 1.9921875 L 10 1.9921875 C 10 1.9921875 10 0.9921875 9 0.9921875 L 6 0.9921875 z M 2 4.9960938 L 2 13.996094 C 2.00005 14.519674 2.47642 14.996044 3 14.996094 L 12 14.996094 C 12.52358 14.996044 12.99995 14.519674 13 13.996094 L 13 4.9960938 L 2 4.9960938 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 781 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 22 22">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#d3dae3; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 2 2.0039062 C 1 2.0039062 1 3.0039062 1 3.0039062 L 1 7.0039062 L 3 7.0039062 L 3 4.0039062 L 6 4.0039062 L 6 2.0039062 L 2 2.0039062 z M 10 2.0039062 L 10 4.0039062 L 13 4.0039062 L 13 7.0039062 L 15 7.0039062 L 15 3.0039062 C 15 2.0039062 14 2.0039062 14 2.0039062 L 10 2.0039062 z M 1 9.0039062 L 1 13.003906 C 1 14.003906 2 14.003906 2 14.003906 L 6 14.003906 L 6 12.003906 L 3 12.003906 L 3 9.0039062 L 1 9.0039062 z M 13 9.0039062 L 13 12.003906 L 10 12.003906 L 10 14.003906 L 14 14.003906 C 14 14.003906 15 14.003906 15 13.003906 L 15 9.0039062 L 13 9.0039062 z" transform="translate(3 3)"/>
</svg>

After

Width:  |  Height:  |  Size: 916 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#d3dae3; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 1.25 3.0039062 C 1.1115 3.0039063 1 3.1154062 1 3.2539062 L 1 4.7539062 C 1 4.8924062 1.1115 5.0039062 1.25 5.0039062 L 2.75 5.0039062 C 2.8885 5.0039062 3 4.8924062 3 4.7539062 L 3 3.2539062 C 3 3.1154062 2.8885 3.0039062 2.75 3.0039062 L 1.25 3.0039062 z M 5.25 3.0039062 C 5.1115 3.0039063 5 3.1154062 5 3.2539062 L 5 4.7539062 C 5 4.8924062 5.1115 5.0039062 5.25 5.0039062 L 6.75 5.0039062 C 6.8885 5.0039062 7 4.8924062 7 4.7539062 L 7 3.2539062 C 7 3.1154062 6.8885 3.0039062 6.75 3.0039062 L 5.25 3.0039062 z M 9.25 3.0039062 C 9.1115 3.0039063 9 3.1154062 9 3.2539062 L 9 4.7539062 C 9 4.8924062 9.1115 5.0039062 9.25 5.0039062 L 10.75 5.0039062 C 10.8885 5.0039062 11 4.8924062 11 4.7539062 L 11 3.2539062 C 11 3.1154062 10.8885 3.0039062 10.75 3.0039062 L 9.25 3.0039062 z M 13.25 3.0039062 C 13.1115 3.0039063 13 3.1154062 13 3.2539062 L 13 4.7539062 C 13 4.8924062 13.1115 5.0039062 13.25 5.0039062 L 14.75 5.0039062 C 14.8885 5.0039062 15 4.8924062 15 4.7539062 L 15 3.2539062 C 15 3.1154062 14.8885 3.0039062 14.75 3.0039062 L 13.25 3.0039062 z M 1.25 7.0039062 C 1.1115 7.0039063 1 7.1154063 1 7.2539062 L 1 8.7539062 C 1 8.8924063 1.1115 9.0039062 1.25 9.0039062 L 2.75 9.0039062 C 2.8885 9.0039062 3 8.8924063 3 8.7539062 L 3 7.2539062 C 3 7.1154063 2.8885 7.0039062 2.75 7.0039062 L 1.25 7.0039062 z M 5.25 7.0039062 C 5.1115 7.0039063 5 7.1154063 5 7.2539062 L 5 8.7539062 C 5 8.8924063 5.1115 9.0039062 5.25 9.0039062 L 6.75 9.0039062 C 6.8885 9.0039062 7 8.8924063 7 8.7539062 L 7 7.2539062 C 7 7.1154063 6.8885 7.0039062 6.75 7.0039062 L 5.25 7.0039062 z M 9.25 7.0039062 C 9.1115 7.0039063 9 7.1154063 9 7.2539062 L 9 8.7539062 C 9 8.8924063 9.1115 9.0039062 9.25 9.0039062 L 10.75 9.0039062 C 10.8885 9.0039062 11 8.8924063 11 8.7539062 L 11 7.2539062 C 11 7.1154063 10.8885 7.0039062 10.75 7.0039062 L 9.25 7.0039062 z M 13.25 7.0039062 C 13.1115 7.0039063 13 7.1154063 13 7.2539062 L 13 8.7539062 C 13 8.8924063 13.1115 9.0039062 13.25 9.0039062 L 14.75 9.0039062 C 14.8885 9.0039062 15 8.8924063 15 8.7539062 L 15 7.2539062 C 15 7.1154063 14.8885 7.0039062 14.75 7.0039062 L 13.25 7.0039062 z M 1.25 11.003906 C 1.1115 11.003906 1 11.115406 1 11.253906 L 1 12.753906 C 1 12.892406 1.1115 13.003906 1.25 13.003906 L 2.75 13.003906 C 2.8885 13.003906 3 12.892406 3 12.753906 L 3 11.253906 C 3 11.115406 2.8885 11.003906 2.75 11.003906 L 1.25 11.003906 z M 5.25 11.003906 C 5.1115 11.003906 5 11.115406 5 11.253906 L 5 12.753906 C 5 12.892406 5.1115 13.003906 5.25 13.003906 L 6.75 13.003906 C 6.8885 13.003906 7 12.892406 7 12.753906 L 7 11.253906 C 7 11.115406 6.8885 11.003906 6.75 11.003906 L 5.25 11.003906 z M 9.25 11.003906 C 9.1115 11.003906 9 11.115406 9 11.253906 L 9 12.753906 C 9 12.892406 9.1115 13.003906 9.25 13.003906 L 10.75 13.003906 C 10.8885 13.003906 11 12.892406 11 12.753906 L 11 11.253906 C 11 11.115406 10.8885 11.003906 10.75 11.003906 L 9.25 11.003906 z M 13.25 11.003906 C 13.1115 11.003906 13 11.115406 13 11.253906 L 13 12.753906 C 13 12.892406 13.1115 13.003906 13.25 13.003906 L 14.75 13.003906 C 14.8885 13.003906 15 12.892406 15 12.753906 L 15 11.253906 C 15 11.115406 14.8885 11.003906 14.75 11.003906 L 13.25 11.003906 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#d3dae3; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 10.029297 1 C 9.8819169 1.003 9.7293425 1.0150094 9.5703125 1.0371094 C 9.0034025 1.1159094 8.3186875 1.3914781 7.5546875 1.7988281 C 6.0140875 0.94567812 4.8137406 0.89374688 3.8066406 1.1542969 C 2.7378406 1.4308069 1.868925 1.8823869 0.515625 1.8417969 L 0 1.8261719 L 0 16 L 15 16 L 15 1.84375 L 14.482422 1.8613281 C 12.965822 1.9165281 12.211922 1.464645 11.232422 1.171875 C 10.865122 1.062075 10.471417 0.99098 10.029297 1 z M 5.21875 1.9941406 C 5.71774 2.0327406 6.2822 2.213495 7 2.609375 L 7 11.333984 C 5.8956 10.692224 4.7902063 10.643969 3.8164062 10.886719 C 3.1632062 11.049539 2.5692 11.237652 2 11.388672 L 2 2.6621094 C 2.8021 2.5141794 3.4740875 2.2830225 4.0546875 2.1328125 C 4.2857975 2.0730125 4.5091312 2.02398 4.7382812 2 C 4.8933012 1.9838 5.05242 1.9813406 5.21875 1.9941406 z M 10.337891 2.0019531 C 10.543791 2.0284531 10.742569 2.079065 10.949219 2.140625 C 11.483649 2.300375 12.1426 2.5531719 13 2.7011719 L 13 11.384766 C 12.43016 11.232366 11.837453 11.042719 11.189453 10.880859 C 10.209613 10.636099 9.0981 10.696078 8 11.367188 L 8 2.6679688 C 8.70328 2.2824487 9.2453875 2.0716725 9.6796875 2.0078125 C 9.9189475 1.9726125 10.131991 1.9756531 10.337891 2.0019531 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#d3dae3; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 8 3.0039062 C 6.4492 3.0190063 4.8879094 3.3732319 3.5371094 4.1386719 C 2.9987094 4.4892919 2.3523344 4.9421175 1.8652344 5.3984375 C 1.0987444 6.1488575 0.4427 7.0244062 0 8.0039062 C 1.2149 10.683506 3.8859187 12.6474 6.8242188 12.9375 C 8.7516188 13.15561 10.768591 12.822631 12.462891 11.869141 C 13.001291 11.518521 13.647666 11.065695 14.134766 10.609375 C 14.901256 9.858955 15.5573 8.9834063 16 8.0039062 C 14.785 5.3245062 12.114181 3.3601125 9.1757812 3.0703125 C 8.7859013 3.0248425 8.39251 3.0038963 8 3.0039062 z M 8 5.0019531 L 8 5.0039062 C 9.607 4.9683062 11.0303 6.4057062 11 8.0039062 C 11.0515 9.7703063 9.2909813 11.294844 7.5507812 10.964844 C 5.7931812 10.758504 4.5587188 8.7851344 5.1367188 7.1152344 C 5.5058788 5.8858344 6.7125 4.9866531 8 5.0019531 z M 8 7.0039062 A 1 1 0 0 0 7 8.0039062 A 1 1 0 0 0 8 9.0039062 A 1 1 0 0 0 9 8.0039062 A 1 1 0 0 0 8 7.0039062 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#d3dae3; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 3.1894531 2.0039062 C 2.5267531 2.0039062 2.0019531 2.5527963 2.0019531 3.2226562 L 2.0019531 7.0039062 L 4.0019531 7.0039062 L 4.0019531 4.0039062 L 7.0019531 4.0039062 L 7.0019531 2.0039062 L 3.1894531 2.0039062 z M 9.0019531 2.0039062 L 9.0019531 4.0039062 L 12.001953 4.0039062 L 12.001953 7.0039062 L 14.001953 7.0039062 L 14.001953 3.2226562 C 14.001953 2.5528963 13.477153 2.0039062 12.814453 2.0039062 L 9.0019531 2.0039062 z M 2.0019531 9.0039062 L 2.0019531 12.785156 C 2.0019531 13.454916 2.5267531 14.003906 3.1894531 14.003906 L 7.0019531 14.003906 L 7.0019531 12.003906 L 4.0019531 12.003906 L 4.0019531 9.0039062 L 2.0019531 9.0039062 z M 12.001953 9.0039062 L 12.001953 12.003906 L 9.0019531 12.003906 L 9.0019531 14.003906 L 12.814453 14.003906 C 13.477153 14.003906 14.001953 13.455016 14.001953 12.785156 L 14.001953 9.0039062 L 12.001953 9.0039062 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#d3dae3; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 3.1875 2 C 2.5248 2 2 2.54895 2 3.21875 L 2 7 L 4 7 L 4 4 L 7 4 L 7 2 L 3.1875 2 z M 9 2 L 9 4 L 12 4 L 12 7 L 14 7 L 14 3.21875 C 14 2.54885 13.4755 2 12.8125 2 L 9 2 z M 7 5 L 7 11 L 9 11 L 9 5 L 7 5 z M 6 6 L 4 8 L 6 10 L 6 6 z M 10 6 L 10 10 L 12 8 L 10 6 z M 2 9 L 2 12.78125 C 2 13.45125 2.5248 14 3.1875 14 L 7 14 L 7 12 L 4 12 L 4 9 L 2 9 z M 12 9 L 12 12 L 9 12 L 9 14 L 12.8125 14 C 13.4755 14 14 13.45125 14 12.78125 L 14 9 L 12 9 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 790 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#d3dae3; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 3 2 C 2.446 2 2 2.446 2 3 L 2 13 C 2 13.554 2.446 14 3 14 L 13 14 C 13.554 14 14 13.554 14 13 L 14 3 C 14 2.446 13.554 2 13 2 L 3 2 z M 7 5 L 9 5 L 9 7 L 11 7 L 11 9 L 9 9 L 9 11 L 7 11 L 7 9 L 5 9 L 5 7 L 7 7 L 7 5 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 564 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#d3dae3; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 3 2 C 2.446 2 2 2.446 2 3 L 2 13 C 2 13.554 2.446 14 3 14 L 13 14 C 13.554 14 14 13.554 14 13 L 14 3 C 14 2.446 13.554 2 13 2 L 3 2 z M 7 5 L 9 5 L 9 11 L 7 11 L 7 7 L 6 7 L 6 6 C 6 6 7 6 7 5 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 540 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<defs>
<style id="current-color-scheme" type="text/css">
.ColorScheme-Text { color:#d3dae3; } .ColorScheme-Highlight { color:#5294e2; }
</style>
</defs>
<path style="fill:currentColor" class="ColorScheme-Text" d="M 3 2 C 2.446 2 2 2.446 2 3 L 2 13 C 2 13.554 2.446 14 3 14 L 13 14 C 13.554 14 14 13.554 14 13 L 14 3 C 14 2.446 13.554 2 13 2 L 3 2 z M 5 7 L 11 7 L 11 9 L 5 9 L 5 7 z" transform="translate(4 4)"/>
</svg>

After

Width:  |  Height:  |  Size: 514 B

View File

@@ -1,5 +1,64 @@
<RCC>
<qresource prefix="images">
<file>xmark.svg</file>
<file>DarkIcons/add.svg</file>
<file>DarkIcons/bookmark-new.svg</file>
<file>DarkIcons/bookmarks.svg</file>
<file>DarkIcons/color-picker.svg</file>
<file>DarkIcons/edit-rename.svg</file>
<file>DarkIcons/format-indent-less.svg</file>
<file>DarkIcons/format-indent-more.svg</file>
<file>DarkIcons/format-justify-center.svg</file>
<file>DarkIcons/format-justify-fill.svg</file>
<file>DarkIcons/format-justify-left.svg</file>
<file>DarkIcons/format-justify-right.svg</file>
<file>DarkIcons/format-line-spacing-double.svg</file>
<file>DarkIcons/format-line-spacing-triple.svg</file>
<file>DarkIcons/gtk-select-font.svg</file>
<file>DarkIcons/mail-thread-watch.svg</file>
<file>DarkIcons/reload.svg</file>
<file>DarkIcons/remove.svg</file>
<file>DarkIcons/settings.svg</file>
<file>DarkIcons/table.svg</file>
<file>DarkIcons/trash-empty.svg</file>
<file>DarkIcons/view-fullscreen.svg</file>
<file>DarkIcons/view-grid.svg</file>
<file>DarkIcons/view-readermode.svg</file>
<file>DarkIcons/visibility.svg</file>
<file>DarkIcons/zoom-fit-best.svg</file>
<file>DarkIcons/zoom-fit-width.svg</file>
<file>DarkIcons/zoom-in.svg</file>
<file>DarkIcons/zoom-original.svg</file>
<file>DarkIcons/zoom-out.svg</file>
<file>LightIcons/add.svg</file>
<file>LightIcons/bookmark-new.svg</file>
<file>LightIcons/bookmarks.svg</file>
<file>LightIcons/color-picker.svg</file>
<file>LightIcons/edit-rename.svg</file>
<file>LightIcons/format-indent-less.svg</file>
<file>LightIcons/format-indent-more.svg</file>
<file>LightIcons/format-justify-center.svg</file>
<file>LightIcons/format-justify-fill.svg</file>
<file>LightIcons/format-justify-left.svg</file>
<file>LightIcons/format-justify-right.svg</file>
<file>LightIcons/format-line-spacing-double.svg</file>
<file>LightIcons/format-line-spacing-triple.svg</file>
<file>LightIcons/gtk-select-font.svg</file>
<file>LightIcons/mail-thread-watch.svg</file>
<file>LightIcons/reload.svg</file>
<file>LightIcons/remove.svg</file>
<file>LightIcons/settings.svg</file>
<file>LightIcons/table.svg</file>
<file>LightIcons/trash-empty.svg</file>
<file>LightIcons/view-fullscreen.svg</file>
<file>LightIcons/view-grid.svg</file>
<file>LightIcons/view-readermode.svg</file>
<file>LightIcons/visibility.svg</file>
<file>LightIcons/zoom-fit-best.svg</file>
<file>LightIcons/zoom-fit-width.svg</file>
<file>LightIcons/zoom-in.svg</file>
<file>LightIcons/zoom-original.svg</file>
<file>LightIcons/zoom-out.svg</file>
<file>QMPlay2.svg</file>
<file>color.svg</file>
<file>blank.png</file>

View File

@@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>1009</width>
<width>1216</width>
<height>658</height>
</rect>
</property>
@@ -69,6 +69,29 @@
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="languageLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Dictionary:</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="languageBox"/>
</item>
</layout>
</item>
</layout>
</item>
</layout>
@@ -93,25 +116,43 @@
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<widget class="QCheckBox" name="comicsRemain">
<property name="text">
<string>Leave comics on disc</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QLabel" name="languageLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<widget class="QLabel" name="label">
<property name="toolTip">
<string>Restart to see changes</string>
</property>
<property name="text">
<string>Dictionary:</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
<string>Icon theme: </string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="languageBox"/>
<widget class="QRadioButton" name="darkIconsRadio">
<property name="toolTip">
<string>Restart to see changes</string>
</property>
<property name="text">
<string>Dar&amp;k</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="lightIconsRadio">
<property name="toolTip">
<string>Restart to see changes</string>
</property>
<property name="text">
<string>&amp;Light</string>
</property>
</widget>
</item>
</layout>
</item>

7
resources/raw/xmark.svg Normal file
View File

@@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" version="1.1" viewBox="0 0 24 24">
<circle style="fill:#252a35" cx="12" cy="12" r="10"/>
<g transform="matrix(0.70710678,0.70710678,-0.70710678,0.70710678,12,-4.9705627)">
<rect style="fill:#ffffff" width="2" height="14" x="-13" y="5" transform="matrix(0,-1,1,0,0,0)"/>
<rect style="fill:#ffffff" width="2" height="14" x="11" y="5"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 416 B

File diff suppressed because it is too large Load Diff

View File

@@ -11,7 +11,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(1009, 658)
Dialog.resize(1216, 658)
self.gridLayout_3 = QtWidgets.QGridLayout(Dialog)
self.gridLayout_3.setObjectName("gridLayout_3")
self.verticalLayout_2 = QtWidgets.QVBoxLayout()
@@ -46,16 +46,6 @@ class Ui_Dialog(object):
self.autoTags = QtWidgets.QCheckBox(self.groupBox)
self.autoTags.setObjectName("autoTags")
self.horizontalLayout_4.addWidget(self.autoTags)
self.verticalLayout.addLayout(self.horizontalLayout_4)
self.gridLayout.addLayout(self.verticalLayout, 0, 0, 1, 1)
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.coverShadows = QtWidgets.QCheckBox(self.groupBox)
self.coverShadows.setObjectName("coverShadows")
self.horizontalLayout.addWidget(self.coverShadows)
self.performCulling = QtWidgets.QCheckBox(self.groupBox)
self.performCulling.setObjectName("performCulling")
self.horizontalLayout.addWidget(self.performCulling)
self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
self.languageLabel = QtWidgets.QLabel(self.groupBox)
@@ -70,7 +60,32 @@ class Ui_Dialog(object):
self.languageBox = QtWidgets.QComboBox(self.groupBox)
self.languageBox.setObjectName("languageBox")
self.horizontalLayout_3.addWidget(self.languageBox)
self.horizontalLayout.addLayout(self.horizontalLayout_3)
self.horizontalLayout_4.addLayout(self.horizontalLayout_3)
self.verticalLayout.addLayout(self.horizontalLayout_4)
self.gridLayout.addLayout(self.verticalLayout, 0, 0, 1, 1)
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.coverShadows = QtWidgets.QCheckBox(self.groupBox)
self.coverShadows.setObjectName("coverShadows")
self.horizontalLayout.addWidget(self.coverShadows)
self.performCulling = QtWidgets.QCheckBox(self.groupBox)
self.performCulling.setObjectName("performCulling")
self.horizontalLayout.addWidget(self.performCulling)
self.comicsRemain = QtWidgets.QCheckBox(self.groupBox)
self.comicsRemain.setObjectName("comicsRemain")
self.horizontalLayout.addWidget(self.comicsRemain)
self.horizontalLayout_5 = QtWidgets.QHBoxLayout()
self.horizontalLayout_5.setObjectName("horizontalLayout_5")
self.label = QtWidgets.QLabel(self.groupBox)
self.label.setObjectName("label")
self.horizontalLayout_5.addWidget(self.label)
self.darkIconsRadio = QtWidgets.QRadioButton(self.groupBox)
self.darkIconsRadio.setObjectName("darkIconsRadio")
self.horizontalLayout_5.addWidget(self.darkIconsRadio)
self.lightIconsRadio = QtWidgets.QRadioButton(self.groupBox)
self.lightIconsRadio.setObjectName("lightIconsRadio")
self.horizontalLayout_5.addWidget(self.lightIconsRadio)
self.horizontalLayout.addLayout(self.horizontalLayout_5)
self.gridLayout.addLayout(self.horizontalLayout, 1, 0, 1, 1)
self.verticalLayout_2.addWidget(self.groupBox)
self.gridLayout_3.addLayout(self.verticalLayout_2, 0, 0, 1, 1)
@@ -99,10 +114,17 @@ class Ui_Dialog(object):
self.refreshLibrary.setText(_translate("Dialog", "Startup: Refresh library"))
self.fileRemember.setText(_translate("Dialog", "Remember open files"))
self.autoTags.setText(_translate("Dialog", "Generate tags from files"))
self.languageLabel.setText(_translate("Dialog", "Dictionary:"))
self.coverShadows.setText(_translate("Dialog", "Cover shadows"))
self.performCulling.setToolTip(_translate("Dialog", "Enabling reduces startup time and memory usage"))
self.performCulling.setText(_translate("Dialog", "Load covers only when needed"))
self.languageLabel.setText(_translate("Dialog", "Dictionary:"))
self.comicsRemain.setText(_translate("Dialog", "Leave comics on disc"))
self.label.setToolTip(_translate("Dialog", "Restart to see changes"))
self.label.setText(_translate("Dialog", "Icon theme: "))
self.darkIconsRadio.setToolTip(_translate("Dialog", "Restart to see changes"))
self.darkIconsRadio.setText(_translate("Dialog", "Dar&k"))
self.lightIconsRadio.setToolTip(_translate("Dialog", "Restart to see changes"))
self.lightIconsRadio.setText(_translate("Dialog", "&Light"))
self.okButton.setText(_translate("Dialog", "Scan Library"))
self.cancelButton.setText(_translate("Dialog", "Close"))
self.aboutButton.setText(_translate("Dialog", "About"))

5
setup.cfg Normal file
View File

@@ -0,0 +1,5 @@
[bdist_wheel]
# This flag says that the code is written to work on both Python 2 and Python
# 3. If at all possible, it is good practice to do this. If you cannot, you
# will need to generate wheels for each Python version that you support.
universal=1

77
setup.py Normal file
View File

@@ -0,0 +1,77 @@
import codecs
from os import path
from setuptools import setup, find_packages
HERE = path.abspath(path.dirname(__file__))
MAJOR_VERSION = '0'
MINOR_VERSION = '2'
MICRO_VERSION = '0'
VERSION = "{}.{}.{}".format(MAJOR_VERSION, MINOR_VERSION, MICRO_VERSION)
# Get the long description from the README file
with codecs.open(path.join(HERE, 'README.md'), encoding='utf-8') as f:
LONG_DESC = f.read()
INSTALL_DEPS = ['PyQt5>=5.10.1',
'requests>=2.18.4',
'beautifulsoup4>=4.6.0']
TEST_DEPS = ['pytest',
'unittest2']
DEV_DEPS = []
setup(
name='lector',
description='Qt-based ebook reader',
long_description=LONG_DESC,
url='https://github.com/BasioMeusPuga/Lector',
author='BasioMeusPuga',
author_email='disgruntled.mob@gmail.com',
license='GPL v3.0',
version=VERSION,
classifiers=[
# How mature is this project? Common values are
# 3 - Alpha
# 4 - Beta
# 5 - Production/Stable
'Development Status :: 3 - Alpha',
'Intended Audience :: End Users/Desktop',
'License :: OSI Approved :: GNU General Public License v3 (GPLv3)',
'Programming Language :: Python :: 3.6',
],
# What does your project relate to?
keywords='qt ebook epub kindle mobi comic cbz cbr pdf',
packages=find_packages(),
entry_points={
'gui_scripts': [
'lector = lector.__main__:main']
},
# List run-time dependencies here. These will be installed by pip when
# your project is installed. For an analysis of "install_requires" vs pip's
# requirements files see:
# https://packaging.python.org/en/latest/requirements.html
install_requires=INSTALL_DEPS,
python_requires='>=3.6, <4.0',
package_data={'': ['about.html']},
include_package_data=True,
# List additional groups of dependencies here (e.g. development
# dependencies). You can install these using the following syntax,
# for example:
# $ pip install -e .[dev,test]
extras_require={
'dev': DEV_DEPS,
'test': TEST_DEPS,
'PDF': ['python-poppler-qt5']
},
)