This commit is contained in:
Kovid Goyal 2007-07-30 20:39:39 +00:00
parent 1a36564830
commit 8e8940f69e
17 changed files with 321 additions and 87 deletions

View File

@ -197,6 +197,9 @@ _check_symlinks_prescript()
print 'Adding unrtf'
os.link(os.path.expanduser('~/unrtf'), os.path.join(frameworks_dir, 'unrtf'))
print
print 'Adding pdftohtml'
os.link(os.path.expanduser('~/pdftohtml'), os.path.join(frameworks_dir, 'pdftohtml'))
print
print 'Installing prescipt'
sf = [os.path.basename(s) for s in all_names]
cs = BuildAPP.CHECK_SYMLINKS_PRESCRIPT % dict(dest_path=repr('/usr/bin'),

View File

@ -30,6 +30,7 @@ entry_points = {
'rtf2lrf = libprs500.ebooks.lrf.rtf.convert_from:main',\
'web2disk = libprs500.web.fetch.simple:main',\
'web2lrf = libprs500.ebooks.lrf.web.convert_from:main',\
'pdf2lrf = libprs500.ebooks.lrf.pdf.convert_from:main',\
],
'gui_scripts' : [ APPNAME+' = libprs500.gui.main:main']
}

View File

@ -13,7 +13,7 @@
## with this program; if not, write to the Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
''' E-book management software'''
__version__ = "0.3.79"
__version__ = "0.3.81"
__docformat__ = "epytext"
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
__appname__ = 'libprs500'

View File

@ -255,11 +255,17 @@ class HTMLConverter(object):
# Fix pdftohtml markup
PDFTOHTML = [
# Remove <hr> tags
(re.compile(r'<hr.*?>', re.IGNORECASE), lambda match: ''),
(re.compile(r'<hr.*?>', re.IGNORECASE), lambda match: '<span style="page-break-after:always"> </span>'),
# Remove page numbers
(re.compile(r'\d+<br>', re.IGNORECASE), lambda match: ''),
# Remove <br> and replace <br><br> with <p>
(re.compile(r'<br.*?>\s*<br.*?>', re.IGNORECASE), lambda match: '<p>'),
(re.compile(r'(.{75,}?)<br.*?>', re.IGNORECASE),
lambda match: match.group(1)),
(re.compile(r'(.*)<br.*?>', re.IGNORECASE),
lambda match: match.group() if re.match('<', match.group(1).lstrip()) or len(match.group(1)) < 40
else match.group(1)),
# Remove hyphenation
(re.compile(r'-\n|-\n\r'), lambda match: ''),
]
class Link(object):

View File

@ -18,7 +18,7 @@ from subprocess import Popen, PIPE
from libprs500.ebooks.lrf import option_parser as lrf_option_parser
from libprs500.ebooks import ConversionError
from libprs500.ebooks.lrf.html.convert_from import process_file
from libprs500 import isosx
from libprs500 import isosx, __appname__
CLIT = 'clit'
if isosx and hasattr(sys, 'frameworks_dir'):
CLIT = os.path.join(sys.frameworks_dir, CLIT)
@ -32,7 +32,7 @@ def option_parser():
def generate_html(pathtolit):
if not os.access(pathtolit, os.R_OK):
raise ConversionError, 'Cannot read from ' + pathtolit
tdir = mkdtemp(prefix='libprs500_lit2lrf_')
tdir = mkdtemp(prefix=__appname__+'_')
cmd = ' '.join([CLIT, '"'+pathtolit+'"', tdir])
p = Popen(cmd, shell=True, stderr=PIPE)
ret = p.wait()

View File

@ -0,0 +1,14 @@
## Copyright (C) 2007 Kovid Goyal kovid@kovidgoyal.net
## 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 2 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, write to the Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

View File

@ -0,0 +1,73 @@
## Copyright (C) 2007 Kovid Goyal kovid@kovidgoyal.net
## 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 2 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, write to the Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
''''''
import sys, os, subprocess
from libprs500 import isosx
from libprs500.ebooks import ConversionError
from libprs500.ptempfile import PersistentTemporaryFile
from libprs500.ebooks.lrf import option_parser as lrf_option_parser
from libprs500.ebooks.lrf.html.convert_from import process_file
PDFTOHTML = 'pdftohtml'
if isosx and hasattr(sys, 'frameworks_dir'):
PDFTOHTML = os.path.join(sys.frameworks_dir, PDFTOHTML)
def generate_html(pathtopdf):
'''
Convert the pdf into html.
@return: A closed PersistentTemporaryFile.
'''
if not os.access(pathtopdf, os.R_OK):
raise ConversionError, 'Cannot read from ' + pathtopdf
pf = PersistentTemporaryFile('.html')
pf.close()
cmd = PDFTOHTML + ' -noframes -p -nomerge "%s" "%s"'%(pathtopdf, pf.name)
p = subprocess.Popen(cmd, shell=True, stderr=subprocess.PIPE)
ret = p.wait()
if ret != 0:
err = p.stderr.read()
raise ConversionError, err
return pf
def option_parser():
return lrf_option_parser(
'''Usage: %prog [options] mybook.pdf\n\n'''
'''%prog converts mybook.pdf to mybook.lrf\n\n'''
)
def main(args=sys.argv):
parser = option_parser()
options, args = parser.parse_args(args)
if len(args) != 2:
parser.print_help()
print
print 'No pdf file specified'
return 1
pdf = os.path.abspath(os.path.expanduser(args[1]))
htmlfile = generate_html(pdf)
if not options.output:
ext = '.lrs' if options.lrs else '.lrf'
options.output = os.path.abspath(os.path.basename(os.path.splitext(args[1])[0]) + ext)
else:
options.output = os.path.abspath(options.output)
options.pdftohtml = True
process_file(htmlfile.name, options)
return 0
if __name__ == '__main__':
sys.exit(main())

View File

@ -7,10 +7,6 @@ RC = images_rc.pyc
%_rc.pyc : %.qrc %
pyrcc4 $< > $*_rc.py
python -c "import compiler; compiler.compileFile('$*_rc.py')"
echo > $*_rc.py
touch $*_rc.pyc
all : $(UI) $(RC)

View File

@ -14,8 +14,8 @@
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
""" The GUI for libprs500. """
import sys, os, re, StringIO, traceback
from PyQt4.QtCore import QVariant, QSettings
from PyQt4.QtGui import QFileDialog, QMessageBox, QPixmap
from PyQt4.QtCore import QVariant, QSettings, QFileInfo
from PyQt4.QtGui import QFileDialog, QMessageBox, QPixmap, QFileIconProvider
from libprs500 import __appname__ as APP_TITLE
from libprs500 import __author__
NONE = QVariant() #: Null value to return from the data function of item models
@ -37,6 +37,8 @@ def error_dialog(parent, title, msg):
d.setIconPixmap(QPixmap(':/images/dialog_error.svg'))
return d
def qstring_to_unicode(q):
return unicode(q.toUtf8(), 'utf8')
def human_readable(size):
""" Convert a size in bytes into a human readable form """
@ -53,31 +55,111 @@ def human_readable(size):
size = size[:size.find(".")+2]
return size + " " + suffix
def choose_files(window, dialog, title, filetype='',
extensions=[], all_files=True):
class FileIconProvider(QFileIconProvider):
ICONS = {
'default' : 'unknown',
'dir' : 'dir',
'zero' : 'zero',
'jpeg' : 'jpeg',
'jpg' : 'jpeg',
'gif' : 'gif',
'png' : 'png',
'bmp' : 'bmp',
'svg' : 'svg',
'html' : 'html',
'lit' : 'lit',
'lrf' : 'lrf',
'lrx' : 'lrx',
'pdf' : 'pdf',
'rar' : 'rar',
'zip' : 'zip',
'txt' : 'txt',
}
def __init__(self):
QFileIconProvider.__init__(self)
self.icons = {}
for key in self.__class__.ICONS.keys():
self.icons[key] = ':/images/mimetypes/'+self.__class__.ICONS[key]+'.svg'
def pixmap(self, fileinfo):
key = 'default'
icons = self.icons
if fileinfo.isSymlink():
if not fileinfo.exists():
return icons['zero']
fileinfo = QFileInfo(fileinfo.readLink())
if fileinfo.isDir():
key = 'dir'
else:
ext = qstring_to_unicode(fileinfo.extension(True)).lower()
key = [i for i in icons.keys() if i in ext]
key = key[0] if key else 'default'
if key:
key = key[0]
candidate = icons[key]
if isinstance(candidate, QPixmap):
return candidate
pixmap = QPixmap(candidate)
icons[key] = pixmap
return pixmap
file_icon_provider = None
class FileDialog(QFileDialog):
def __init__(self, title='Choose Files',
filters=[],
add_all_files_filter=True,
parent=None,
modal = True,
name = '',
mode = QFileDialog.ExistingFiles,
):
QFileDialog.__init__(self, parent)
self.setModal(modal)
global file_icon_provider
if not file_icon_provider:
file_icon_provider = FileIconProvider()
if not self.iconProvider() is file_icon_provider:
self.setIconProvider(file_icon_provider)
settings = QSettings()
_dir = settings.value(name, QVariant(os.path.expanduser("~"))).toString()
self.setDirectory(_dir)
ftext = ''
if filters:
for filter in filters:
text, extensions = filter
extensions = ['.'+i if not i.startswith('.') else i for i in extensions]
ftext += '%s (%s);;'%(text, ' '.join(extensions))
if add_all_files_filter or not ftext:
ftext += 'All files (*)'
self.setFilters(ftext)
self.setWindowTitle(title)
def get_files(self):
self.exec_()
return tuple(os.path.abspath(qstring_to_unicode(i)) for i in self.selectedFiles())
def choose_files(window, name, title,
filters=[], all_files=True, select_only_single_file=False):
'''
Ask user to choose a bunch of files.
@param dialog: Unique gialog name used to store the opened directory
@param name: Unique dialog name used to store the opened directory
@param title: Title to show in dialogs titlebar
@param filetype: What types of files is this dialog choosing
@params extensions: list of allowable extension
@params all_files: If True show all files
@param filters: list of allowable extensions. Each element of the list
must be a 2-tuple with first element a string describing
the type of files to be filtered and second element a list
of extensions.
@param all_files: If True add All files to filters.
@param select_only_single_file: If True only one file can be selected
'''
settings = QSettings()
_dir = settings.value(dialog, QVariant(os.path.expanduser("~"))).toString()
books = []
extensions = ['*.'+i for i in extensions]
if extensions:
filter = filetype + ' (' + ' '.join(extensions) + ')'
if all_files:
filter += ';;All files (*)'
else:
filter = 'All files (*)'
files = QFileDialog.getOpenFileNames(window, title, _dir, filter)
for file in files:
file = unicode(file.toUtf8(), 'utf8')
books.append(os.path.abspath(file))
if books:
settings.setValue(dialog, QVariant(os.path.dirname(books[0])))
return books
mode = QFileDialog.ExistingFile if select_only_single_file else QFileDialog.ExistingFiles
fd = FileDialog(title=title, name=name, filters=filters,
parent=window, add_all_files_filter=all_files, mode=mode,
)
return fd.get_files()

View File

@ -14,5 +14,13 @@
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
'''Various dialogs used in the GUI'''
from PyQt4.QtCore import QObject
from PyQt4.QtGui import QDialog
class ModalDialog(QObject):
def __init__(self, window):
QObject.__init__(self, window)
self.dialog = QDialog(window)
self.accept = self.dialog.accept
self.reject = self.dialog.reject
self.window = window

View File

@ -20,9 +20,11 @@ import os
from PyQt4.QtCore import Qt, SIGNAL
from PyQt4.Qt import QObject, QPixmap, QListWidgetItem, QErrorMessage, \
QVariant, QSettings, QFileDialog, QDialog
QVariant, QSettings, QFileDialog
from libprs500.gui2 import qstring_to_unicode, error_dialog
from libprs500.gui2.dialogs import ModalDialog
from libprs500.gui2.dialogs.metadata_single_ui import Ui_MetadataSingleDialog
class Format(QListWidgetItem):
@ -32,7 +34,7 @@ class Format(QListWidgetItem):
QListWidgetItem.__init__(self, ext.upper(), parent, \
QListWidgetItem.UserType)
class EditBookDialog(Ui_MetadataSingleDialog, QDialog):
class MetadataSingleDialog(Ui_MetadataSingleDialog, ModalDialog):
def select_cover(self, checked):
settings = QSettings()
@ -40,25 +42,27 @@ class EditBookDialog(Ui_MetadataSingleDialog, QDialog):
QVariant(os.path.expanduser("~"))).toString()
_file = str(QFileDialog.getOpenFileName(self.parent, \
"Choose cover for " + str(self.title.text()), _dir, \
"Images (*.png *.gif *.jpeg *.jpg);;All files (*)"))
"Images (*.png *.gif *.jpeg *.jpg *.svg);;All files (*)"))
if len(_file):
_file = os.path.abspath(_file)
settings.setValue("change cover dir", \
QVariant(os.path.dirname(_file)))
if not os.access(_file, os.R_OK):
QErrorMessage(self.parent).showMessage("You do not have "+\
"permission to read the file: " + _file)
d = error_dialog(self.window, 'Cannot read',
'You do not have permission to read the file: ' + _file)
d.exec_()
return
cf, cover = None, None
try:
cf = open(_file, "rb")
cover = cf.read()
except IOError, e:
QErrorMessage(self.parent).showMessage("There was an error"+\
" reading from file: " + _file + "\n"+str(e))
d = error_dialog(self.window, 'Error reading file',
"<p>There was an error reading from file: <br /><b>" + _file + "</b></p><br />"+str(e))
d.exec_()
if cover:
pix = QPixmap()
pix.loadFromData(cover, "", Qt.AutoColor)
pix.loadFromData(cover)
if pix.isNull():
QErrorMessage(self.parent).showMessage(_file + \
" is not a valid picture")
@ -83,7 +87,7 @@ class EditBookDialog(Ui_MetadataSingleDialog, QDialog):
for _file in files:
_file = os.path.abspath(_file)
if not os.access(_file, os.R_OK):
QErrorMessage(self.parent).showMessage("You do not have "+\
QErrorMessage(self.window).showMessage("You do not have "+\
"permission to read the file: " + _file)
continue
ext = os.path.splitext(_file)[1].lower()
@ -124,15 +128,17 @@ class EditBookDialog(Ui_MetadataSingleDialog, QDialog):
self.db.remove_format(self.id, ext)
self.db.update_max_size(self.id)
def __init__(self, parent, row, db):
def __init__(self, window, row, db, slot):
Ui_MetadataSingleDialog.__init__(self)
QDialog.__init__(parent)
self.setupUi(parent)
ModalDialog.__init__(self, window)
self.setupUi(self.dialog)
self.splitter.setStretchFactor(100, 1)
self.db = db
self.id = db.id(row)
self.cover_data = None
self.formats_changed = False
self.cover_changed = False
self.slot = slot
QObject.connect(self.cover_button, SIGNAL("clicked(bool)"), \
self.select_cover)
QObject.connect(self.add_format_button, SIGNAL("clicked(bool)"), \
@ -140,10 +146,8 @@ class EditBookDialog(Ui_MetadataSingleDialog, QDialog):
QObject.connect(self.remove_format_button, SIGNAL("clicked(bool)"), \
self.remove_format)
QObject.connect(self.button_box, SIGNAL("accepted()"), \
self.sync_formats)
self.sync)
data = self.db.get_row_by_id(self.id, \
["title","authors","rating","publisher","tags","comments"])
self.title.setText(db.title(row))
au = self.db.authors(row)
self.authors.setText(au if au else '')
@ -154,7 +158,8 @@ class EditBookDialog(Ui_MetadataSingleDialog, QDialog):
rating = self.db.rating(row)
if rating > 0:
self.rating.setValue(rating)
self.comments.setPlainText(data["comments"] if data["comments"] else "")
comments = self.db.comments(row)
self.comments.setPlainText(comments if comments else '')
cover = self.db.cover(row)
if cover:
pm = QPixmap()
@ -166,3 +171,17 @@ class EditBookDialog(Ui_MetadataSingleDialog, QDialog):
# if not ext:
# ext = "Unknown"
# Format(self.formats, ext)
self.dialog.exec_()
def sync(self):
if self.formats_changed:
self.sync_formats()
title = qstring_to_unicode(self.title.text())
self.db.set_title(self.id, title)
au = qstring_to_unicode(self.authors.text()).split(',')
self.db.set_authors(self.id, au)
self.slot()
def reject(self):
self.rejected = True

View File

@ -494,22 +494,6 @@
<include location="../images.qrc" />
</resources>
<connections>
<connection>
<sender>button_box</sender>
<signal>rejected()</signal>
<receiver>MetadataSingleDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel" >
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel" >
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>button_box</sender>
<signal>accepted()</signal>
@ -526,5 +510,21 @@
</hint>
</hints>
</connection>
<connection>
<sender>button_box</sender>
<signal>rejected()</signal>
<receiver>MetadataSingleDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel" >
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel" >
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -10,22 +10,27 @@
<file>images/jobs.svg</file>
<file alias="library" >images/library.png</file>
<file>images/list_remove.svg</file>
<file>images/mimetypes/bmp.svg</file>
<file>images/mimetypes/dir.svg</file>
<file>images/mimetypes/gif.svg</file>
<file>images/mimetypes/html.svg</file>
<file>images/mimetypes/jpeg.svg</file>
<file>images/mimetypes/lit.svg</file>
<file>images/mimetypes/lrf.svg</file>
<file>images/mimetypes/lrx.svg</file>
<file>images/mimetypes/pdf.svg</file>
<file>images/mimetypes/png.svg</file>
<file>images/mimetypes/rar.svg</file>
<file>images/mimetypes/rtf.svg</file>
<file>images/mimetypes/svg.svg</file>
<file>images/mimetypes/txt.svg</file>
<file>images/mimetypes/unknown.svg</file>
<file>images/mimetypes/zero.svg</file>
<file>images/mimetypes/zip.svg</file>
<file>images/plus.svg</file>
<file>images/reader.svg</file>
<file>images/sd.svg</file>
<file>images/sync.svg</file>
<file>images/trash.svg</file>
</qresource>
<qresource prefix="/" >
<file>images/mimetypes/format_html.svg</file>
<file>images/mimetypes/format_lit.svg</file>
<file>images/mimetypes/format_lrf.svg</file>
<file>images/mimetypes/format_lrx.svg</file>
<file>images/mimetypes/format_pdf.svg</file>
<file>images/mimetypes/format_rar.svg</file>
<file>images/mimetypes/format_rtf.svg</file>
<file>images/mimetypes/format_txt.svg</file>
<file>images/mimetypes/format_unknown.svg</file>
<file>images/mimetypes/format_zip.svg</file>
</qresource>
</RCC>

View File

@ -28,6 +28,7 @@ from libprs500.gui2.main_ui import Ui_MainWindow
from libprs500.gui2.device import DeviceDetector, DeviceManager
from libprs500.gui2.status import StatusBar
from libprs500.gui2.jobs import JobManager, JobException
from libprs500.gui2.dialogs.metadata_single import MetadataSingleDialog
class Main(QObject, Ui_MainWindow):
@ -194,8 +195,9 @@ class Main(QObject, Ui_MainWindow):
'''
Add books from the local filesystem to either the library or the device.
'''
books = choose_files(self.window, 'add books dialog dir', 'Select books', 'Books',
extensions=['lrf', 'lrx', 'rar', 'zip', 'rtf', 'lit', 'txt', 'htm', 'html', 'xhtml', 'epub'])
books = choose_files(self.window, 'add books dialog dir', 'Select books',
filters=[('Books', ['lrf', 'lrx', 'rar', 'zip',
'rtf', 'lit', 'txt', 'htm', 'html', 'xhtml', 'epub',])])
if not books:
return
on_card = False if self.stack.currentIndex() != 2 else True
@ -309,9 +311,21 @@ class Main(QObject, Ui_MainWindow):
############################### Edit metadata ##############################
def edit_metadata(self, checked):
'''
Edit metadata of selected books in library or on device.
Edit metadata of selected books in library individually.
'''
pass
rows = self.library_view.selectionModel().selectedRows()
if not rows or len(rows) == 0:
return
changed = False
def cs():
changed = True
for row in rows:
MetadataSingleDialog(self.window, row.row(), self.library_view.model().db, cs)
if changed:
self.library_view.model().resort()
self.library_view.model().research()
############################################################################
############################# Syncing to device#############################

View File

@ -626,6 +626,7 @@ class LibraryDatabase(object):
return self.data[index][1]
def authors(self, index):
''' Authors as a comman separated list or None'''
return self.data[index][2]
def publisher(self, index):
@ -641,6 +642,7 @@ class LibraryDatabase(object):
return self.data[index][6]
def cover(self, index):
'''Cover as a data string or None'''
id = self.id(index)
matches = self.conn.execute('SELECT data from covers where id=?', (id,)).fetchall()
if not matches:
@ -651,6 +653,7 @@ class LibraryDatabase(object):
return None
def tags(self, index):
'''tags as a comman separated list or None'''
id = self.id(index)
matches = self.conn.execute('SELECT concat(name) FROM tags WHERE tags.id IN (SELECT tag from books_tags_link WHERE book=?)', (id,)).fetchall()
if not matches:
@ -658,6 +661,7 @@ class LibraryDatabase(object):
return matches[0][0]
def comments(self, index):
'''Comments as string or None'''
id = self.id(index)
matches = self.conn.execute('SELECT text FROM comments WHERE book=?', (id,)).fetchall()
if not matches:
@ -678,7 +682,9 @@ class LibraryDatabase(object):
def set(self, row, column, val):
''' Convenience method for setting the title, authors, publisher or rating '''
'''
Convenience method for setting the title, authors, publisher or rating
'''
id = self.data[row][0]
cols = {'title' : 1, 'authors': 2, 'publisher': 3, 'rating':4}
col = cols[column]
@ -699,10 +705,14 @@ class LibraryDatabase(object):
self.set_rating(id, val)
def set_authors(self, id, authors):
'''
@param authors: A list of authors.
'''
self.conn.execute('DELETE FROM books_authors_link WHERE book=?',(id,))
for a in authors:
if not a:
continue
a = a.strip()
author = self.conn.execute('SELECT id from authors WHERE name=?', (a,)).fetchone()
if author:
aid = author[0]

View File

@ -80,6 +80,7 @@ def setup_completion():
f.write(opts_and_exts('txt2lrf', txtop, ['txt']))
f.write(opts_and_exts('lit2lrf', htmlop, ['lit']))
f.write(opts_and_exts('rtf2lrf', htmlop, ['rtf']))
f.write(opts_and_exts('pdf2lrf', htmlop, ['pdf']))
f.write(opts_and_exts('lrf-meta', metaop, ['lrf']))
f.write('''
_prs500_ls()

View File

@ -57,6 +57,7 @@ Var MUI_TEMP
!define LIBUNRAR_DIR "C:\Program Files\UnrarDLL"
!define CLIT "C:\clit\clit.exe"
!define UNRTF "C:\unrtf\unrtf.exe"
!define PDFTOHTML "C:\pdftohtml\pdftohtml.exe"
;------------------------------------------------------------------------------------------------------
;General
@ -126,6 +127,7 @@ Section "libprs500" Seclibprs500
File /r "${PY2EXE_DIR}\*"
File "${CLIT}"
File "${UNRTF}"
File "${PDFTOHTML}"
SetOutPath "$INSTDIR\driver"
File "${LIBUSB_DIR}\*.dll"