Esempio n. 1
0
def get_pixmap(icon_name):
    '''
    Retrieve a QPixmap for the named image
    Any icons belonging to the plugin must be prefixed with 'images/'
    '''
    global plugin_icon_resources, plugin_name

    if not icon_name.startswith('images/'):
        # We know this is definitely not an icon belonging to this plugin
        pixmap = QPixmap()
        pixmap.load(I(icon_name))
        return pixmap

    # Check to see whether the icon exists as a Calibre resource
    # This will enable skinning if the user stores icons within a folder like:
    # ...\AppData\Roaming\calibre\resources\images\Plugin Name\
    if plugin_name:
        local_images_dir = get_local_images_dir(plugin_name)
        local_image_path = os.path.join(local_images_dir,
                                        icon_name.replace('images/', ''))
        if os.path.exists(local_image_path):
            pixmap = QPixmap()
            pixmap.load(local_image_path)
            return pixmap

    # As we did not find an icon elsewhere, look within our zip resources
    if icon_name in plugin_icon_resources:
        pixmap = QPixmap()
        pixmap.loadFromData(plugin_icon_resources[icon_name])
        return pixmap
    return None
Esempio n. 2
0
 def files_dropped_on_book(self, event, paths, cid=None):
     accept = False
     if self.gui.current_view() is not self.gui.library_view:
         return
     db = self.gui.library_view.model().db
     cover_changed = False
     current_idx = self.gui.library_view.currentIndex()
     if cid is None:
         if not current_idx.isValid(): return
         cid = db.id(current_idx.row()) if cid is None else cid
     for path in paths:
         ext = os.path.splitext(path)[1].lower()
         if ext:
             ext = ext[1:]
         if ext in IMAGE_EXTENSIONS:
             pmap = QPixmap()
             pmap.load(path)
             if not pmap.isNull():
                 accept = True
                 db.set_cover(cid, pmap)
                 cover_changed = True
         elif ext in BOOK_EXTENSIONS:
             db.add_format_with_hooks(cid, ext, path, index_is_id=True)
             accept = True
     if accept and event is not None:
         event.accept()
     if current_idx.isValid():
         self.gui.library_view.model().current_changed(current_idx, current_idx)
     if cover_changed:
         if self.gui.cover_flow:
             self.gui.cover_flow.dataChanged()
Esempio n. 3
0
 def files_dropped_on_book(self, event, paths, cid=None):
     accept = False
     if self.gui.current_view() is not self.gui.library_view:
         return
     db = self.gui.library_view.model().db
     cover_changed = False
     current_idx = self.gui.library_view.currentIndex()
     if cid is None:
         if not current_idx.isValid(): return
         cid = db.id(current_idx.row()) if cid is None else cid
     for path in paths:
         ext = os.path.splitext(path)[1].lower()
         if ext:
             ext = ext[1:]
         if ext in IMAGE_EXTENSIONS:
             pmap = QPixmap()
             pmap.load(path)
             if not pmap.isNull():
                 accept = True
                 db.set_cover(cid, pmap)
                 cover_changed = True
         elif ext in BOOK_EXTENSIONS:
             db.add_format_with_hooks(cid, ext, path, index_is_id=True)
             accept = True
     if accept and event is not None:
         event.accept()
     if current_idx.isValid():
         self.gui.library_view.model().current_changed(
             current_idx, current_idx)
     if cover_changed:
         if self.gui.cover_flow:
             self.gui.cover_flow.dataChanged()
Esempio n. 4
0
def get_pixmap(icon_name):
    '''
    Retrieve a QPixmap for the named image
    Any icons belonging to the plugin must be prefixed with 'images/'
    '''
    global plugin_icon_resources, plugin_name

    if not icon_name.startswith('images/'):
        # We know this is definitely not an icon belonging to this plugin
        pixmap = QPixmap()
        pixmap.load(I(icon_name))
        return pixmap

    # Check to see whether the icon exists as a Calibre resource
    # This will enable skinning if the user stores icons within a folder like:
    # ...\AppData\Roaming\calibre\resources\images\Plugin Name\
    if plugin_name:
        local_images_dir = get_local_images_dir(plugin_name)
        local_image_path = os.path.join(local_images_dir, icon_name.replace('images/', ''))
        if os.path.exists(local_image_path):
            pixmap = QPixmap()
            pixmap.load(local_image_path)
            return pixmap

    # As we did not find an icon elsewhere, look within our zip resources
    if icon_name in plugin_icon_resources:
        pixmap = QPixmap()
        pixmap.loadFromData(plugin_icon_resources[icon_name])
        return pixmap
    return None
Esempio n. 5
0
 def _setLangIcons(self):
     itemcount = self.window.cmbx_lang.count()
     for i in range(0, itemcount + 1):
         if self.window.cmbx_lang.itemText(i) == u'English':
             path = './Resources/FlagsIcons/USA.png'
         elif self.window.cmbx_lang.itemText(i) == u'Русский':
             path = './Resources/FlagsIcons/Russia.png'
         elif self.window.cmbx_lang.itemText(i) == u'Română':
             path = './Resources/FlagsIcons/Moldova.png'
         img = QPixmap()
         img.load(path)
         icon = QIcon(img)
         self.window.cmbx_lang.setItemIcon(i, icon)
Esempio n. 6
0
    def render_images(self, outpath, mi, items):
        printer = get_pdf_printer(self.opts, for_comic=True, output_file_name=outpath)
        printer.setDocName(mi.title)

        painter = QPainter(printer)
        painter.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform)

        for i, imgpath in enumerate(items):
            self.log("Rendering image:", i)
            p = QPixmap()
            p.load(imgpath)
            if not p.isNull():
                if i > 0:
                    printer.newPage()
                draw_image_page(printer, painter, p)
            else:
                self.log.warn("Failed to load image", i)
        painter.end()
Esempio n. 7
0
 def files_dropped_on_book(self, event, paths, cid=None, do_confirm=True):
     accept = False
     if self.gui.current_view() is not self.gui.library_view:
         return
     db = self.gui.library_view.model().db
     cover_changed = False
     current_idx = self.gui.library_view.currentIndex()
     if cid is None:
         if not current_idx.isValid():
             return
         cid = db.id(current_idx.row()) if cid is None else cid
     formats = []
     for path in paths:
         ext = os.path.splitext(path)[1].lower()
         if ext:
             ext = ext[1:]
         if ext in IMAGE_EXTENSIONS:
             pmap = QPixmap()
             pmap.load(path)
             if not pmap.isNull():
                 accept = True
                 db.set_cover(cid, pmap)
                 cover_changed = True
         elif ext in BOOK_EXTENSIONS:
             formats.append((ext, path))
             accept = True
     if accept and event is not None:
         event.accept()
     if do_confirm and formats:
         if not confirm(_(
                 'You have dropped some files onto the book <b>%s</b>. This will'
                 ' add or replace the files for this book. Do you want to proceed?'
         ) % db.title(cid, index_is_id=True),
                        'confirm_drop_on_book',
                        parent=self.gui):
             formats = []
     for ext, path in formats:
         db.add_format_with_hooks(cid, ext, path, index_is_id=True)
     if current_idx.isValid():
         self.gui.library_view.model().current_changed(
             current_idx, current_idx)
     if cover_changed:
         if self.gui.cover_flow:
             self.gui.cover_flow.dataChanged()
 def __init__(self, parent, icon_name, title):
     QHBoxLayout.__init__(self)
     title_font = QFont()
     title_font.setPointSize(16)
     title_image_label = QLabel(parent)
     pixmap = QPixmap()
     pixmap.load(I(icon_name))
     if pixmap is None:
         error_dialog(parent, _('Restart required'),
                      _('You must restart Calibre before using this plugin!'), show=True)
     else:
         title_image_label.setPixmap(pixmap)
     title_image_label.setMaximumSize(32, 32)
     title_image_label.setScaledContents(True)
     self.addWidget(title_image_label)
     shelf_label = QLabel(title, parent)
     shelf_label.setFont(title_font)
     self.addWidget(shelf_label)
     self.insertStretch(-1)
Esempio n. 9
0
def get_pixmap(icon_name):
    '''
    Retrieve a QPixmap for the named image
    Any zipped icons belonging to the plugin must be prefixed with 'images/'
    '''
    global plugin_icon_resources

    if not icon_name.startswith('images/'):
        # We know this is definitely not an icon belonging to this plugin
        pixmap = QPixmap()
        pixmap.load(I(icon_name))
        return pixmap

    # As we did not find an icon elsewhere, look within our zip resources
    if icon_name in plugin_icon_resources:
        pixmap = QPixmap()
        pixmap.loadFromData(plugin_icon_resources[icon_name])
        return pixmap
    return None
Esempio n. 10
0
 def __init__(self, parent, icon_name, title):
     QHBoxLayout.__init__(self)
     title_font = QFont()
     title_font.setPointSize(16)
     title_image_label = QLabel(parent)
     pixmap = QPixmap()
     pixmap.load(I(icon_name))
     if pixmap is None:
         error_dialog(parent, _('Restart required'),
                      _('You must restart Calibre before using this plugin!'), show=True)
     else:
         title_image_label.setPixmap(pixmap)
     title_image_label.setMaximumSize(32, 32)
     title_image_label.setScaledContents(True)
     self.addWidget(title_image_label)
     shelf_label = QLabel(title, parent)
     shelf_label.setFont(title_font)
     self.addWidget(shelf_label)
     self.insertStretch(-1)
Esempio n. 11
0
def get_pixmap(icon_name):
    """
    Retrieve a QPixmap for the named image
    Any zipped icons belonging to the plugin must be prefixed with 'images/'
    """
    global plugin_icon_resources

    if not icon_name.startswith("images/"):
        # We know this is definitely not an icon belonging to this plugin
        pixmap = QPixmap()
        pixmap.load(I(icon_name))
        return pixmap

    # As we did not find an icon elsewhere, look within our zip resources
    if icon_name in plugin_icon_resources:
        pixmap = QPixmap()
        pixmap.loadFromData(plugin_icon_resources[icon_name])
        return pixmap
    return None
Esempio n. 12
0
 def files_dropped_on_book(self, event, paths, cid=None, do_confirm=True):
     accept = False
     if self.gui.current_view() is not self.gui.library_view:
         return
     db = self.gui.library_view.model().db
     cover_changed = False
     current_idx = self.gui.library_view.currentIndex()
     if cid is None:
         if not current_idx.isValid():
             return
         cid = db.id(current_idx.row()) if cid is None else cid
     formats = []
     for path in paths:
         ext = os.path.splitext(path)[1].lower()
         if ext:
             ext = ext[1:]
         if ext in IMAGE_EXTENSIONS:
             pmap = QPixmap()
             pmap.load(path)
             if not pmap.isNull():
                 accept = True
                 db.set_cover(cid, pmap)
                 cover_changed = True
         elif ext in BOOK_EXTENSIONS:
             formats.append((ext, path))
             accept = True
     if accept and event is not None:
         event.accept()
     if do_confirm and formats:
         if not confirm(
             _('You have dropped some files onto the book <b>%s</b>. This will'
               ' add or replace the files for this book. Do you want to proceed?') % db.title(cid, index_is_id=True),
             'confirm_drop_on_book', parent=self.gui):
             formats = []
     for ext, path in formats:
         db.add_format_with_hooks(cid, ext, path, index_is_id=True)
     if current_idx.isValid():
         self.gui.library_view.model().current_changed(current_idx, current_idx)
     if cover_changed:
         if self.gui.cover_flow:
             self.gui.cover_flow.dataChanged()
Esempio n. 13
0
    def render_images(self, outpath, mi, items):
        printer = get_pdf_printer(self.opts,
                                  for_comic=True,
                                  output_file_name=outpath)
        printer.setDocName(mi.title)

        painter = QPainter(printer)
        painter.setRenderHints(QPainter.Antialiasing
                               | QPainter.SmoothPixmapTransform)

        for i, imgpath in enumerate(items):
            self.log('Rendering image:', i)
            p = QPixmap()
            p.load(imgpath)
            if not p.isNull():
                if i > 0:
                    printer.newPage()
                draw_image_page(printer, painter, p)
            else:
                self.log.warn('Failed to load image', i)
        painter.end()
Esempio n. 14
0
    def render_images(self, outpath, mi, items):
        printer = get_pdf_printer(self.opts, for_comic=True,
                output_file_name=outpath)
        printer.setDocName(mi.title)
        printer.setCreator(u'%s [%s]'%(__appname__, __version__))
        # Seems to be no way to set author

        painter = QPainter(printer)
        painter.setRenderHints(QPainter.Antialiasing|QPainter.SmoothPixmapTransform)

        for i, imgpath in enumerate(items):
            self.log('Rendering image:', i)
            p = QPixmap()
            p.load(imgpath)
            if not p.isNull():
                if i > 0:
                    printer.newPage()
                draw_image_page(printer, painter, p)
            else:
                self.log.warn('Failed to load image', i)
        painter.end()
        def _fetch_marvin_cover(border_width=0):
            '''
            Retrieve LargeCoverJpg from cache
            '''
            #self._log_location('border_width: {0}'.format(border_width))
            con = sqlite3.connect(self.marvin_db_path)
            with con:
                con.row_factory = sqlite3.Row

                # Fetch Hash from mainDb
                cover_cur = con.cursor()
                cover_cur.execute('''SELECT
                                      Hash
                                     FROM Books
                                     WHERE ID = '{0}'
                                  '''.format(self.book_id))
                row = cover_cur.fetchone()

            book_hash = row[b'Hash']
            large_covers_subpath = self.connected_device._cover_subpath(size="large")
            cover_path = '/'.join([large_covers_subpath, '%s.jpg' % book_hash])
            stats = self.parent.ios.exists(cover_path)
            if stats:
                self._log("fetching large cover from cache")
                #self._log("cover size: {:,} bytes".format(int(stats['st_size'])))
                cover_bytes = self.parent.ios.read(cover_path, mode='rb')
                m_image = QImage()
                m_image.loadFromData(cover_bytes)

                if border_width:
                    # Construct a QPixmap with oversized yellow background
                    m_image = m_image.scaledToHeight(
                        self.COVER_ICON_SIZE - border_width * 2,
                        Qt.SmoothTransformation)

                    self.m_pixmap = QPixmap(
                        QSize(m_image.width() + border_width * 2,
                              m_image.height() + border_width * 2))

                    m_painter = QPainter(self.m_pixmap)
                    m_painter.setRenderHints(m_painter.Antialiasing)

                    m_painter.fillRect(self.m_pixmap.rect(), self.MISMATCH_COLOR)
                    m_painter.drawImage(border_width,
                                        border_width,
                                        m_image)
                else:
                    m_image = m_image.scaledToHeight(
                        self.COVER_ICON_SIZE,
                        Qt.SmoothTransformation)

                    self.m_pixmap = QPixmap(
                        QSize(m_image.width(),
                              m_image.height()))

                    m_painter = QPainter(self.m_pixmap)
                    m_painter.setRenderHints(m_painter.Antialiasing)

                    m_painter.drawImage(0, 0, m_image)

                self.marvin_cover.setPixmap(self.m_pixmap)
            else:
                # No cover available, use generic
                self._log("No cached cover, using generic")
                pixmap = QPixmap()
                pixmap.load(I('book.png'))
                pixmap = pixmap.scaled(self.COVER_ICON_SIZE,
                                       self.COVER_ICON_SIZE,
                                       aspectRatioMode=Qt.KeepAspectRatio,
                                       transformMode=Qt.SmoothTransformation)
                self.marvin_cover.setPixmap(pixmap)
Esempio n. 16
0
class LetsShareBooksDialog(QDialog):
    started_calibre_web_server = QtCore.pyqtSignal()
    calibre_didnt_start = QtCore.pyqtSignal()
    established_ssh_tunnel = QtCore.pyqtSignal()

    def __init__(self, gui, icon, do_user_config, qaction, us):
        QDialog.__init__(self, gui)
        self.main_gui = gui
        self.do_user_config = do_user_config
        self.qaction = qaction
        self.us = us
        self.initial = True

        self.lsb_url_text = 'Be a librarian. Share your library.'
        self.url_label_tooltip = '<<<< Be a librarian. Click on Start sharing button.<<<<'
        self.lsb_url = 'nourl'
        if prefs['librarian'] == 'l' or prefs['librarian'] == '':
            self.librarian = get_libranon()
        else:
            self.librarian = prefs['librarian']

        self.metadata_thread = MetadataLibThread(self.librarian)
        self.check_connection = ConnectionCheck()

        self.clip = QApplication.clipboard()
        self.pxmp = QPixmap()
        self.pxmp.load('images/icon_connected.png')
        self.icon_connected = QIcon(self.pxmp)

        self.setStyleSheet("""
        QDialog {
                background-color: white;
        }

        QPushButton {
                font-size: 16px;
                border-style: solid;
                border-color: red;
                font-family:'BitstreamVeraSansMono',Consolas,monospace;
                text-transform: uppercase;
        }

        QPushButton#arrow {
                border-width: 16px;
                border-right-color:white;
                padding: -10px;
                color:red;
        }

        QPushButton#url {
                background-color: red;
                min-width: 460px;
                color: white;
                text-align: left;
               }

        QPushButton#url:hover {
                background-color: white;
                color: red;
                }

        QPushButton#share {
                background-color: red;
                color: white;
                margin-right: 10px;
                }

        QPushButton#share:hover {
                background-color: white;
                color: red;
                }

        QPushButton#url2 {
                color: #222;
                text-align: left;
        }
        QPushButton#url2:hover {
                color: red;
                }

        QLineEdit#edit {
                background-color: white;
                color: black;
                font-size: 16px;
                border-style: solid;
                border-color: red;
                font-family:'BitstreamVeraSansMono',Consolas,monospace;
                text-transform: uppercase;
        }


        """)

        self.ll = QVBoxLayout()
        #self.ll.setSpacing(1)

        self.l = QHBoxLayout()
        self.l.setSpacing(0)
        self.l.setMargin(0)
        #self.l.setContentsMargins(0,0,0,0)
        self.w = QWidget()
        self.w.setLayout(self.l)

        self.setLayout(self.ll)
        self.setWindowIcon(icon)

        self.debug_label = QLabel()
        self.ll.addWidget(self.debug_label)
        self.debug_label.show()

        self.lets_share_button = QPushButton()
        self.lets_share_button.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)
        self.lets_share_button.setObjectName("share")
        #self.lets_share_button.clicked.connect(self.lets_share)

        self.l.addWidget(self.lets_share_button)

        self.url_label = QPushButton()
        self.url_label.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)
        self.url_label.setObjectName("url")
        #self.url_label.clicked.connect(self.open_url)
        self.l.addWidget(self.url_label)

        self.arrow_button = QPushButton("_____")
        self.arrow_button.setObjectName("arrow")
        self.l.addWidget(self.arrow_button)

        self.ll.addWidget(self.w)
        self.ll.addSpacing(5)

        self.libranon_layout = QHBoxLayout()
        self.libranon_layout.setSpacing(0)
        self.libranon_layout.setMargin(0)
        #self.l.setContentsMargins(0,0,0,0)
        self.libranon_container = QWidget()
        self.libranon_container.setLayout(self.libranon_layout)

        self.edit = QLineEdit()
        self.edit.setObjectName("edit")
        self.edit.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.edit.setToolTip("Change your librarian name")
        self.edit.setText(self.librarian)
        #self.edit.textChanged.connect(self.handle_text_changed)

        self.save_libranon = QPushButton("librarian:")
        self.save_libranon.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
        self.save_libranon.setObjectName("share")
        self.save_libranon.setToolTip("Save your librarian name")
        self.libranon_layout.addWidget(self.save_libranon)
        self.libranon_layout.addWidget(self.edit)
        self.save_libranon.clicked.connect(self.save_librarian)

        self.ll.addWidget(self.libranon_container)
        self.ll.addSpacing(10)

        self.chat_button = QPushButton("Chat room: https://chat.memoryoftheworld.org")
        #self.chat_button.hovered.connect(self.setCursorToHand)
        self.chat_button.setObjectName("url2")
        self.chat_button.setToolTip('Meetings every thursday at 23:59 (central eruopean time)')
        self.chat_button.clicked.connect(functools.partial(self.open_url, "https://chat.memoryoftheworld.org/?nick={}".format(self.librarian.lower().replace(" ", "_"))))
        self.ll.addWidget(self.chat_button)

        self.about_project_button = QPushButton('Public Library: http://www.memoryoftheworld.org')
        self.about_project_button.setObjectName("url2")
        self.about_project_button.setToolTip('When everyone is librarian, library is everywhere.')
        self.metadata_thread.uploaded.connect(lambda: self.render_library_button("{}://library.{}".format(prefs['server_prefix'], prefs['lsb_server']), "Building together real-time p2p library infrastructure."))

        self.ll.addWidget(self.about_project_button)

        self.debug_log = QListWidget()
        self.ll.addWidget(self.debug_log)
        self.debug_log.addItem("Initiatied!")
        self.debug_log.hide()

        from PyQt4 import QtWebKit
        self.webview = QtWebKit.QWebView()
        self.webview.setMaximumWidth(680)
        self.webview.setMaximumHeight(400)
        self.webview.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.webview.setUrl(QtCore.QUrl( "https://chat.memoryoftheworld.org/?nick={}".format(self.librarian.lower().replace(" ", "_"))))
        self.ll.addWidget(self.webview)
        #self.webview.hide()

        #- check if there is a new version of plugin ----------------------------------------------

        self.plugin_url = "https://github.com/marcellmars/letssharebooks/raw/master/calibreletssharebooks/letssharebooks_calibre.zip"
        self.running_version = ".".join(map(str, lsb.version))
        try:
            r = requests.get('https://raw.github.com/marcellmars/letssharebooks/master/calibreletssharebooks/_version', timeout=3)
            self.latest_version = r.text[-1]
        except:
            self.latest_version = "0.0.0"

        self.upgrade_button = QPushButton('Please download and upgrade from {0} to {1} version of plugin.'.format(self.us.running_version, self.latest_version))
        self.upgrade_button.setObjectName("url2")
        self.upgrade_button.setToolTip('Running latest version you make developers happy')
        self.upgrade_button.clicked.connect(functools.partial(self.open_url, self.plugin_url))

        version_list = [self.us.running_version, self.us.latest_version]
        version_list.sort(key=lambda s: map(int, s.split('.')))
        if self.us.running_version != self.us.latest_version:
            if self.us.running_version == version_list[0]:
                self.ll.addSpacing(20)
                self.ll.addWidget(self.upgrade_button)

        #------------------------------------------------------------------------------------------

        self.resize(self.sizeHint())

        #- parsing/tee log file -------------------------------------------------------------------

        self.se = open("/tmp/lsb.log", "w+b")
        #self.se = tempfile.NamedTemporaryFile()
        self.so = self.se

        sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
        os.dup2(self.so.fileno(), sys.stdout.fileno())
        os.dup2(self.se.fileno(), sys.stderr.fileno())

        #- state machine --------------------------------------------------------------------------

        self.machine = QtCore.QStateMachine()

        self.on = QtCore.QState()
        self.on.setObjectName("on")
        self.on.entered.connect(lambda: self.render_lsb_button("Start sharing", self.lsb_url_text))

        self.calibre_web_server = QtCore.QState()
        self.calibre_web_server.setObjectName("calibre_web_server")
        self.calibre_web_server.entered.connect(self.start_calibre_server)
        self.calibre_web_server.entered.connect(lambda: self.render_lsb_button("Stop sharing", self.lsb_url_text))
        self.calibre_web_server.assignProperty(self.debug_label, 'text', 'Starting Calibre web server...')

        self.ssh_server = QtCore.QState()
        self.ssh_server.setObjectName("ssh_server")
        self.ssh_server.entered.connect(lambda: self.render_lsb_button("Stop sharing", "Connecting..."))
        self.ssh_server.entered.connect(self.establish_ssh_server)
        self.ssh_server.assignProperty(self.debug_label, 'text', 'Establishing SSH tunnel...')

        self.ssh_server_established = QtCore.QState()
        self.ssh_server_established.setObjectName("ssh_server_established")
        self.ssh_server_established.entered.connect(lambda: self.render_lsb_button("Stop sharing", self.lsb_url_text))
        self.ssh_server_established.entered.connect(self.check_connections)
        self.ssh_server_established.assignProperty(self.debug_label, 'text', 'Established SSH tunnel...')

        self.url_label_clicked = QtCore.QState()
        self.url_label_clicked.setObjectName("url_label_clicked")
        self.url_label_clicked.entered.connect(lambda: self.open_url(self.lsb_url))
        self.url_label_clicked.assignProperty(self.debug_label, 'text', 'URL label clicked!')

        self.about_project_clicked = QtCore.QState()
        self.about_project_clicked.setObjectName("about_project_clicked")
        self.about_project_clicked.entered.connect(lambda: self.open_url("{}://library.{}".format(prefs['server_prefix'], prefs['lsb_server'])))
        self.about_project_clicked.assignProperty(self.debug_label, 'text', 'about_project_button clicked!')

        self.library_state_changed = QtCore.QState()
        self.library_state_changed.entered.connect(lambda: self.render_library_button("Uploading library metadata...", "Sharing with the others who share their libraries now..."))
        self.library_state_changed.setObjectName("library_state_changed")
        self.library_state_changed.entered.connect(self.sync_metadata)

        self.off = QtCore.QState()
        self.off.setObjectName("off")
        self.off.entered.connect(lambda: self.disconnect_all())
        self.off.assignProperty(self.debug_label, 'text', 'Start again...')

        self.on.addTransition(self.lets_share_button.clicked, self.calibre_web_server)

        self.calibre_web_server.addTransition(self.lets_share_button.clicked, self.off)
        self.calibre_web_server.addTransition(self.calibre_didnt_start, self.off)
        self.calibre_web_server.addTransition(self.started_calibre_web_server, self.ssh_server)

        self.ssh_server.addTransition(self.lets_share_button.clicked, self.off)
        self.ssh_server.addTransition(self.check_connection.lost_connection, self.off)
        self.ssh_server.addTransition(self.established_ssh_tunnel, self.ssh_server_established)

        self.ssh_server_established.addTransition(self.lets_share_button.clicked, self.off)
        self.ssh_server_established.addTransition(self.url_label.clicked, self.url_label_clicked)
        self.ssh_server_established.addTransition(self.about_project_button.clicked, self.about_project_clicked)
        self.ssh_server_established.addTransition(self.check_connection.lost_connection, self.off)
        self.ssh_server_established.addTransition(self.us.library_changed, self.library_state_changed)

        self.url_label_clicked.addTransition(self.ssh_server_established)
        self.about_project_clicked.addTransition(self.ssh_server_established)

        self.library_state_changed.addTransition(self.metadata_thread.uploaded, self.ssh_server_established)
        self.library_state_changed.addTransition(self.metadata_thread.upload_error, self.off)
        self.library_state_changed.addTransition(self.lets_share_button.clicked, self.off)
        self.library_state_changed.addTransition(self.url_label.clicked, self.url_label_clicked)

        self.off.addTransition(self.on)

        self.machine.addState(self.on)
        self.machine.addState(self.calibre_web_server)
        self.machine.addState(self.ssh_server)
        self.machine.addState(self.ssh_server_established)
        self.machine.addState(self.url_label_clicked)
        self.machine.addState(self.about_project_clicked)
        self.machine.addState(self.library_state_changed)
        self.machine.addState(self.off)


        self.machine.setInitialState(self.on)
        self.machine.start()

        #------------------------------------------------------------------------------------------
    def sql_db_changed(self, event, ids):
        # this could be used for better update on added/removed books
        if not self.metadata_thread.isRunning():
            self.sync_metadata()
        else:
            print("metadata_thread is running! no sync!")

    def sync_metadata(self):
        from calibre.gui2.ui import get_gui
        try:
            del self.sql_db
        except:
            pass
        self.sql_db = get_gui().current_db
        self.sql_db.add_listener(self.sql_db_changed)
        self.metadata_thread.sql_db = self.sql_db
        self.metadata_thread.port = self.port
        self.metadata_thread.uploaded.connect(lambda: self.debug_log.addItem("uploaded!"))
        self.metadata_thread.upload_error.connect(lambda: self.debug_log.addItem("upload_ERROR!"))
        self.metadata_thread.start()

    def check_connections(self):
        #self.webview.show()
        if self.initial:
            print("initial!")
            self.us.library_changed_emit()
            self.initial = False
        self.qaction.setIcon(get_icon('images/icon_connected.png'))
        self.check_connection.add_urls(["http://*****:*****@{2} -R {0}:localhost:{1} -P 722".format(self.port, self.calibre_server_port, prefs['lsb_server']), shell=True)
            self.lsb_url = "{}://www{}.{}".format(prefs['server_prefix'], self.port, prefs['lsb_server'])
            self.lsb_url_text = "Go to: {}".format(self.lsb_url)
            QTimer.singleShot(3000, self.established_ssh_tunnel.emit)
        else:
            self.ssh_proc = subprocess.Popen(['ssh', '-T', '-N', '-g', '-o', 'TCPKeepAlive=yes', '-o', 'UserKnownHostsFile=/dev/null', '-o', 'StrictHostKeyChecking=no','-o', 'ServerAliveINterval=60', prefs['lsb_server'], '-l', 'tunnel', '-R', '0:localhost:{0}'.format(self.calibre_server_port), '-p', '722'])
            if self.ssh_proc:
                def parse_log():
                    gotcha = False
                    try:
                        self.se.seek(0)
                        result = self.se.readlines()
                        self.se.seek(0)
                        self.se.truncate()

                        for line in result:
                            m = re.match("^Allocated port (.*) for .*", line)
                            try:
                                self.port = m.groups()[0]
                                self.lsb_url = '{}://www{}.{}'.format(prefs['server_prefix'], self.port, prefs['lsb_server'])
                                self.lsb_url_text = "Go to: {0}".format(self.lsb_url)
                                self.url_label_tooltip = 'Copy URL to clipboard and check it out in a browser!'
                                self.established_ssh_tunnel.emit()
                                gotcha = True
                            except:
                                pass
                    finally:
                        if not gotcha:
                            QTimer.singleShot(500, parse_log)
                parse_log()

    def start_calibre_server(self):
        if self.main_gui.content_server is None:
            self.main_gui.start_content_server()
            opts, args = server_config().option_parser().parse_args(['calibre-server'])
            self.calibre_server_port = opts.port
            self.started_calibre_web_server.emit()
        else:
            self.calibre_didnt_start.emit()

    def config(self):
        self.do_user_config(parent=self)
        self.label.setText(prefs['lsb_server'])

    def save_librarian(self):
        print('librarian {} saved!'.format(str(self.edit.text())))
        if self.edit.text() != "" and self.edit.text() != "l":
            prefs['librarian'] = str(self.edit.text())
        else:
            prefs['librarian'] = get_libranon()
            self.edit.setText(prefs['librarian'])

    def open_url(self, url):
        self.clip.setText(url)
        webbrowser.open(url)

    def keyPressEvent(self, event):
        if event.key() == QtCore.Qt.Key_Escape:
            pass

    def closeEvent(self, e):
        print("close popup!")
        self.hide()
Esempio n. 17
0
class GuiRunner(QObject):
    '''Make sure an event loop is running before starting the main work of
    initialization'''
    def __init__(self, opts, args, actions, listener, app, gui_debug=None):
        self.startup_time = time.time()
        self.opts, self.args, self.listener, self.app = opts, args, listener, app
        self.gui_debug = gui_debug
        self.actions = actions
        self.main = None
        QObject.__init__(self)
        self.splash_screen = None
        self.timer = QTimer.singleShot(1, self.initialize)
        if DEBUG:
            prints('Starting up...')

    def start_gui(self, db):
        from calibre.gui2.ui import Main
        main = self.main = Main(self.opts, gui_debug=self.gui_debug)
        if self.splash_screen is not None:
            self.splash_screen.showMessage(_('Initializing user interface...'))
        with gprefs:  # Only write gui.json after initialization is complete
            main.initialize(self.library_path, db, self.listener, self.actions)
        if self.splash_screen is not None:
            self.splash_screen.finish(main)
        if DEBUG:
            prints(
                'Started up in %.2f seconds' %
                (time.time() - self.startup_time), 'with', len(db.data),
                'books')
        add_filesystem_book = partial(
            main.iactions['Add Books'].add_filesystem_book, allow_device=False)
        sys.excepthook = main.unhandled_exception
        if len(self.args) > 1:
            files = [
                os.path.abspath(p) for p in self.args[1:]
                if not os.path.isdir(p)
            ]
            if len(files) < len(sys.argv[1:]):
                prints('Ignoring directories passed as command line arguments')
            if files:
                add_filesystem_book(files)
        for event in self.app.file_event_hook.events:
            add_filesystem_book(event)
        self.app.file_event_hook = add_filesystem_book

    def initialization_failed(self):
        print 'Catastrophic failure initializing GUI, bailing out...'
        QCoreApplication.exit(1)
        raise SystemExit(1)

    def initialize_db_stage2(self, db, tb):
        from calibre.db.legacy import LibraryDatabase

        if db is None and tb is not None:
            # DB Repair failed
            error_dialog(self.splash_screen,
                         _('Repairing failed'),
                         _('The database repair failed. Starting with '
                           'a new empty library.'),
                         det_msg=tb,
                         show=True)
        if db is None:
            candidate = choose_dir(
                self.splash_screen,
                'choose calibre library',
                _('Choose a location for your new calibre e-book library'),
                default_dir=get_default_library_path())
            if not candidate:
                self.initialization_failed()

            try:
                self.library_path = candidate
                db = LibraryDatabase(candidate)
            except:
                error_dialog(
                    self.splash_screen,
                    _('Bad database location'),
                    _('Bad database location %r. calibre will now quit.') %
                    self.library_path,
                    det_msg=traceback.format_exc(),
                    show=True)
                self.initialization_failed()

        try:
            self.start_gui(db)
        except Exception:
            error_dialog(
                self.main,
                _('Startup error'),
                _('There was an error during {0} startup.'
                  ' Parts of {0} may not function. Click Show details to learn more.'
                  ).format(__appname__),
                det_msg=traceback.format_exc(),
                show=True)

    def initialize_db(self):
        from calibre.db.legacy import LibraryDatabase
        db = None
        try:
            db = LibraryDatabase(self.library_path)
        except apsw.Error:
            repair = question_dialog(
                self.splash_screen,
                _('Corrupted database'),
                _('The library database at %s appears to be corrupted. Do '
                  'you want calibre to try and rebuild it automatically? '
                  'The rebuild may not be completely successful. '
                  'If you say No, a new empty calibre library will be created.'
                  ) % force_unicode(self.library_path, filesystem_encoding),
                det_msg=traceback.format_exc())
            if repair:
                if repair_library(self.library_path):
                    db = LibraryDatabase(self.library_path)
        except:
            error_dialog(self.splash_screen,
                         _('Bad database location'),
                         _('Bad database location %r. Will start with '
                           ' a new, empty calibre library') %
                         self.library_path,
                         det_msg=traceback.format_exc(),
                         show=True)

        self.initialize_db_stage2(db, None)

    def show_splash_screen(self):
        self.splash_pixmap = QPixmap()
        self.splash_pixmap.load(I('library.png'))
        self.splash_screen = QSplashScreen(self.splash_pixmap)
        self.splash_screen.showMessage(
            _('Starting %s: Loading books...') % __appname__)
        self.splash_screen.show()
        QApplication.instance().processEvents()

    def initialize(self, *args):
        if gprefs['show_splash_screen']:
            self.show_splash_screen()

        self.library_path = get_library_path(parent=self.splash_screen)
        if not self.library_path:
            self.initialization_failed()

        self.initialize_db()
Esempio n. 18
0
class GuiRunner(QObject):
    '''Make sure an event loop is running before starting the main work of
    initialization'''

    def __init__(self, opts, args, actions, listener, app, gui_debug=None):
        self.startup_time = time.time()
        self.opts, self.args, self.listener, self.app = opts, args, listener, app
        self.gui_debug = gui_debug
        self.actions = actions
        self.main = None
        QObject.__init__(self)
        self.splash_screen = None
        self.timer = QTimer.singleShot(1, self.initialize)
        if DEBUG:
            prints('Starting up...')

    def start_gui(self, db):
        from calibre.gui2.ui import Main
        main = Main(self.opts, gui_debug=self.gui_debug)
        if self.splash_screen is not None:
            self.splash_screen.showMessage(_('Initializing user interface...'))
        with gprefs:  # Only write gui.json after initialization is complete
            main.initialize(self.library_path, db, self.listener, self.actions)
        if self.splash_screen is not None:
            self.splash_screen.finish(main)
        if DEBUG:
            prints('Started up in %.2f seconds'%(time.time() -
                self.startup_time), 'with', len(db.data), 'books')
        add_filesystem_book = partial(main.iactions['Add Books'].add_filesystem_book, allow_device=False)
        sys.excepthook = main.unhandled_exception
        if len(self.args) > 1:
            files = [os.path.abspath(p) for p in self.args[1:] if not
                    os.path.isdir(p)]
            if len(files) < len(sys.argv[1:]):
                prints('Ignoring directories passed as command line arguments')
            if files:
                add_filesystem_book(files)
        for event in self.app.file_event_hook.events:
            add_filesystem_book(event)
        self.app.file_event_hook = add_filesystem_book
        self.main = main

    def initialization_failed(self):
        print 'Catastrophic failure initializing GUI, bailing out...'
        QCoreApplication.exit(1)
        raise SystemExit(1)

    def initialize_db_stage2(self, db, tb):

        if db is None and tb is not None:
            # DB Repair failed
            error_dialog(self.splash_screen, _('Repairing failed'),
                    _('The database repair failed. Starting with '
                        'a new empty library.'),
                    det_msg=tb, show=True)
        if db is None:
            candidate = choose_dir(self.splash_screen, 'choose calibre library',
                _('Choose a location for your new calibre e-book library'),
                default_dir=get_default_library_path())
            if not candidate:
                self.initialization_failed()

            try:
                self.library_path = candidate
                db = self.db_class(candidate)
            except:
                error_dialog(self.splash_screen, _('Bad database location'),
                    _('Bad database location %r. calibre will now quit.'
                     )%self.library_path,
                    det_msg=traceback.format_exc(), show=True)
                self.initialization_failed()

        self.start_gui(db)

    def initialize_db(self):
        from calibre.db import get_db_loader
        db = None
        self.db_class, errs = get_db_loader()
        try:
            db = self.db_class(self.library_path)
        except errs:
            repair = question_dialog(self.splash_screen, _('Corrupted database'),
                    _('The library database at %s appears to be corrupted. Do '
                    'you want calibre to try and rebuild it automatically? '
                    'The rebuild may not be completely successful. '
                    'If you say No, a new empty calibre library will be created.')
                    % force_unicode(self.library_path, filesystem_encoding),
                    det_msg=traceback.format_exc()
                    )
            if repair:
                if repair_library(self.library_path):
                    db = self.db_class(self.library_path)
        except:
            error_dialog(self.splash_screen, _('Bad database location'),
                    _('Bad database location %r. Will start with '
                    ' a new, empty calibre library')%self.library_path,
                    det_msg=traceback.format_exc(), show=True)

        self.initialize_db_stage2(db, None)

    def show_splash_screen(self):
        self.splash_pixmap = QPixmap()
        self.splash_pixmap.load(I('library.png'))
        self.splash_screen = QSplashScreen(self.splash_pixmap)
        self.splash_screen.showMessage(_('Starting %s: Loading books...') %
                __appname__)
        self.splash_screen.show()
        QApplication.instance().processEvents()

    def initialize(self, *args):
        if gprefs['show_splash_screen']:
            self.show_splash_screen()

        self.library_path = get_library_path(parent=self.splash_screen)
        if not self.library_path:
            self.initialization_failed()

        self.initialize_db()
Esempio n. 19
0
class LetsShareBooksDialog(QDialog):
    def __init__(self, gui, icon, do_user_config, qaction, us):
        QDialog.__init__(self, gui)
        self.gui = gui
        self.do_user_config = do_user_config
        self.qaction = qaction
        self.us = us
        self.clip = QApplication.clipboard()
        self.main_gui = calibre_main()
        
        self.urllib_thread = UrlLibThread(self.us)
        self.kill_servers_thread = KillServersThread(self.us)

        
        self.us.check_finished = True
        
        self.pxmp = QPixmap()
        self.pxmp.load('images/icon_connected.png')
        self.icon_connected = QIcon(self.pxmp)

        self.setStyleSheet("""
        QDialog {
                background-color: white;
        }

        QPushButton { 
                font-size: 16px; 
                border-style: solid;
                border-color: red;
                font-family:'BitstreamVeraSansMono',Consolas,monospace;
                text-transform: uppercase;
        }

        QPushButton#arrow {
                border-width: 16px;
                border-right-color:white;
                padding: -10px;
                color:red;
        }

        QPushButton#url {
                background-color: red;
                min-width: 460px;
                color: white;
                text-align: left;
               }
        
        QPushButton#url:hover {
                background-color: white;
                color: red;
                }

        QPushButton#share {
                background-color: red;
                color: white;
                margin-right: 10px;
                }

        QPushButton#share:hover {
                background-color: white;
                color: red;
                }

        QPushButton#url2 {
                color: #222;
                text-align: left;
        }
        QPushButton#url2:hover {
                color: red;
                }
                """)

        self.ll = QVBoxLayout()
        #self.ll.setSpacing(1)
        
        self.l = QHBoxLayout()
        self.l.setSpacing(0)
        self.l.setMargin(0)
        #self.l.setContentsMargins(0,0,0,0)
        self.w = QWidget()
        self.w.setLayout(self.l)

        self.setLayout(self.ll)
        self.setWindowIcon(icon)

        self.lets_share_button = QPushButton()
        self.lets_share_button.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)
        self.lets_share_button.setObjectName("share")
        self.lets_share_button.clicked.connect(self.lets_share)
        
        self.stop_share_button = QPushButton()
        self.stop_share_button.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)
        self.stop_share_button.setObjectName("share")
        self.stop_share_button.clicked.connect(self.stop_share)

        self.l.addWidget(self.lets_share_button)
        self.l.addWidget(self.stop_share_button)
        
        if self.us.button_state == "start":
            self.lets_share_button.show()
            self.stop_share_button.hide()
            self.lets_share_button.setText(self.us.share_button_text)
        else:
            self.lets_share_button.hide()
            self.stop_share_button.show()
            self.stop_share_button.setText(self.us.share_button_text)

        self.url_label = QPushButton()
        self.url_label.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)
        self.url_label.setObjectName("url")
        self.url_label.clicked.connect(self.open_url)
        self.l.addWidget(self.url_label)
        
        self.arrow_button = QPushButton("_____")
        self.arrow_button.setObjectName("arrow")
        self.l.addWidget(self.arrow_button)

        self.ll.addWidget(self.w)
        self.ll.addSpacing(10)
        
        self.chat_button = QPushButton("Chat room: https://chat.memoryoftheworld.org")
        #self.chat_button.hovered.connect(self.setCursorToHand)
        self.chat_button.setObjectName("url2")
        self.chat_button.setToolTip('Meetings every thursday at 23:59 (central eruopean time)')
        self.chat_button.clicked.connect(functools.partial(self.open_url2, "https://chat.memoryoftheworld.org"))
        self.ll.addWidget(self.chat_button)
        
        self.about_project_button = QPushButton('Public Library: http://www.memoryoftheworld.org')
        self.about_project_button.setObjectName("url2")
        self.about_project_button.setToolTip('When everyone is librarian, library is everywhere.')
        self.about_project_button.clicked.connect(functools.partial(self.open_url2, "http://www.memoryoftheworld.org"))
        self.ll.addWidget(self.about_project_button)
        
        self.debug_log = QListWidget()
        self.ll.addWidget(self.debug_log)
        self.debug_log.addItem("Initiatied!")
      
        self.metadata_thread = MetadataLibThread(self.debug_log)
        
        self.metadata_button = QPushButton("Get library metadata!")
        self.metadata_button.setObjectName("url2")
        self.metadata_button.setToolTip('Get library metadata!')
        self.metadata_button.clicked.connect(self.get_metadata)
        self.ll.addWidget(self.metadata_button)

        self.upgrade_button = QPushButton('Please download and upgrade from {0} to {1} version of plugin.'.format(self.us.running_version, self.us.latest_version))
        self.upgrade_button.setObjectName("url2")
        self.upgrade_button.setToolTip('Running latest version you make developers happy')
        self.upgrade_button.clicked.connect(functools.partial(self.open_url2, self.us.plugin_url))

        version_list = [self.us.running_version, self.us.latest_version]
        version_list.sort(key=lambda s: map(int, s.split('.')))
        if self.us.running_version != self.us.latest_version:
            if self.us.running_version == version_list[0]:
                self.ll.addSpacing(20)
                self.ll.addWidget(self.upgrade_button)

        self.resize(self.sizeHint())

        self.se = open("lsb.log", "w+b")
        self.so = self.se

        sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
        os.dup2(self.so.fileno(), sys.stdout.fileno())
        os.dup2(self.se.fileno(), sys.stderr.fileno())

        self.timer = QTimer()
        self.timer.timeout.connect(self.check_and_render)
        self.timer_period = 300
        self.timer.start(self.timer_period)
        
        self.error_log = ""

    def lets_share(self):
        self.lets_share_button.setEnabled(False)
        self.timer.stop()
        self.us.share_button_text = "Connecting..."
        #self.debug_log.addItem("Let's share!")
        self.us.counter = 0
        self.us.lost_connection = False

        if not self.us.ssh_proc:
            self.main_gui.start_content_server()
            opts, args = server_config().option_parser().parse_args(['calibre-server'])
            self.calibre_server_port = opts.port

            if sys.platform == "win32":
                self.win_reg = subprocess.Popen("regedit /s .hosts.reg")
                self.us.win_port = int(random.random()*40000+10000)
                self.us.ssh_proc = subprocess.Popen("lsbtunnel.exe -N -T tunnel@{2} -R {0}:localhost:{1} -P 722".format(self.us.win_port, self.calibre_server_port, prefs['lsb_server']), shell=True)
                self.us.lsb_url = "https://www{0}.{1}".format(self.us.win_port, prefs['lsb_server'])
                #_dev_self.us.lsb_url = "http://www{0}.{1}".format(self.us.win_port, prefs['lsb_server'])
                self.us.lsb_url_text = "Go to: {0}".format(self.us.lsb_url)
                self.us.found_url = True
            else:
                self.us.ssh_proc = subprocess.Popen(['ssh', '-T', '-N', '-g', '-o', 'UserKnownHostsFile=.userknownhostsfile', '-o', 'TCPKeepAlive=yes', '-o', 'ServerAliveINterval=60', prefs['lsb_server'], '-l', 'tunnel', '-R', '0:localhost:{0}'.format(self.calibre_server_port), '-p', '722'])
                self.us.found_url = None
            
            self.qaction.setIcon(get_icon('images/icon_connected.png'))
            self.us.connecting = True
            self.us.connecting_now = datetime.datetime.now()
            self.timer.start(self.timer_period)
              
    def stop_share(self):
        self.stop_share_button.setEnabled(False)
        #self.debug_log.addItem("Stop Share!")
        self.timer.stop()
        self.us.lsb_url = 'nourl'
        self.us.urllib_result = ''
        self.us.disconnecting = True

        self.qaction.setIcon(get_icon('images/icon.png'))
        
        self.kill_servers_thread.start()

        self.timer.start(self.timer_period)

    def check_and_render(self):
        #self.show_debug()
        if self.us.button_state == "start":
            self.stop_share_button.hide()
            self.lets_share_button.show()
            self.lets_share_button.setText(self.us.share_button_text)
        else:
            self.lets_share_button.hide()
            self.stop_share_button.show()
            self.stop_share_button.setText(self.us.share_button_text)
       
        
        if self.us.disconnecting:
            self.us.share_button_text = "Disconnecting..."
            if self.us.lost_connection:
                self.us.lsb_url_text = 'Lost connection. Please start sharing again.'
                self.us.url_label_tooltip = '<<<< Click on Start sharing button again.'
            else:
                self.us.lsb_url_text = 'Be a librarian. Share your library.'
                self.us.url_label_tooltip = '<<<< Be a librarian. Click on Start sharing button.<<<<'

            if self.us.kill_finished:
                #self.debug_log.addItem("Let's share connect!")
                self.us.button_state = "start"
                self.us.share_button_text = "Start sharing"
                self.us.disconnecting = False
                self.us.kill_finished = False
                self.lets_share_button.setEnabled(True)

        elif self.us.connecting:
            if self.us.connecting_now:
                if (datetime.datetime.now() - self.us.connecting_now) > datetime.timedelta(seconds=10):
                    #self.debug_log.addItem("Timeout!")
                    self.us.http_error = None
                    self.us.lost_connection = True
                    self.us.connecting = False
                    self.us.connecting_now = None
                    self.stop_share()
                elif self.us.found_url:
                    self.us.check_finished = False
                    self.urllib_thread.start()

            if self.us.lsb_url == "nourl" and self.us.ssh_proc and sys.platform != "win32":
                #self.debug_log.addItem("Wait for Allocated port!")
            
                self.se.seek(0)
                result = self.se.readlines()
        
                for line in result:
                    m = re.match("^Allocated port (.*) for .*", line)
                    try:
                        #self.debug_log.addItem(self.us.lsb_url)
                        self.us.lsb_url = 'https://www{0}.{1}'.format(m.groups()[0], prefs['lsb_server'])
                        #_dev_self.us.lsb_url = 'http://www{0}.{1}'.format(m.groups()[0], prefs['lsb_server'])
                        self.us.lsb_url_text = "Go to: {0}".format(self.us.lsb_url)
                        self.us.url_label_tooltip = 'Copy URL to clipboard and check it out in a browser!'
                        self.us.http_error = None
                        self.us.found_url = True
                    except:
                        pass
        
            elif self.us.urllib_result == 200:
                #self.debug_log.addItem("Finish Connecting State!")
                self.se.seek(0)
                self.se.truncate()
                self.us.share_button_text = "Stop sharing"
                self.us.button_state = "stop"
                self.stop_share_button.setEnabled(True)
                self.us.connecting = False
                self.us.connecting_now = None
                self.us.found_url = None

        elif self.us.http_error and self.us.button_state == "stop":
            #self.debug_log.addItem("Error!")
            self.us.http_error = None
            self.us.lost_connection = True
            self.stop_share()


        elif self.us.check_finished: 
            #if self.debug_log.item(self.debug_log.count()-1).text()[:10] == "Finally Ca":
            #    self.us.debug_counter = self.us.debug_counter + 1
            #else:
            #    self.debug_log.addItem("Finally Called Thread!({0})".format(self.us.debug_counter))
            #    self.us.debug_counter = 1
            self.us.check_finished = False
            self.urllib_thread.start()

        if self.us.urllib_result == 200 and self.us.button_state == "stop":
            self.stop_share_button.setEnabled(True)

        if self.us.lsb_url == 'nourl' and self.us.button_state == "start":
            self.lets_share_button.setEnabled(True)

        self.setWindowTitle("{0} - {1}".format(self.us.window_title, self.us.lsb_url))
        self.url_label.setToolTip(self.us.url_label_tooltip)
        self.url_label.setText(self.us.lsb_url_text)

    def open_url(self):
        if self.us.lsb_url == "nourl" and not self.us.http_error:
            self.us.url_label_tooltip = '<<<< Be a librarian. Click on Start sharing button.'
            self.us.lsb_url_text = '<<<< Be a librarian. Click on Start sharing button.'
        else:
            self.clip.setText(self.us.lsb_url)
            webbrowser.open(str(self.us.lsb_url))
            if self.us.lsb_url != "nourl":
                self.us.lsb_url_text = "Library at: {0}".format(self.us.lsb_url)

    def open_url2(self, url):
        self.clip.setText(url)
        webbrowser.open(url)

    def get_metadata(self):
        self.metadata_thread.start()

    def show_debug(self):
        if self.us.debug_item:
            self.debug_log.addItem(str(self.us.debug_item))
            self.us.debug_item = None
        self.debug_log.scrollToBottom()
        self.debug_log.repaint()

    def closeEvent(self, e):
        self.hide()
        #self.urllib_thread.stop()
        #self.kill_servers_thread.stop()

    def config(self):
        self.do_user_config(parent=self)
        self.label.setText(prefs['lsb_server'])
Esempio n. 20
0
        def _fetch_marvin_cover(with_border=False):
            '''
            Retrieve LargeCoverJpg from cache
            '''
            self._log_location()
            con = sqlite3.connect(self.marvin_db_path)
            with con:
                con.row_factory = sqlite3.Row

                # Fetch Hash from mainDb
                cover_cur = con.cursor()
                cover_cur.execute('''SELECT
                                      Hash
                                     FROM Books
                                     WHERE ID = '{0}'
                                  '''.format(self.book_id))
                row = cover_cur.fetchone()

            book_hash = row[b'Hash']
            large_covers_subpath = self.connected_device._cover_subpath(
                size="large")
            cover_path = '/'.join([large_covers_subpath, '%s.jpg' % book_hash])
            stats = self.parent.ios.exists(cover_path)
            if stats:
                self._log("fetching large cover from cache")
                #self._log("cover size: {:,} bytes".format(int(stats['st_size'])))
                cover_bytes = self.parent.ios.read(cover_path, mode='rb')
                m_image = QImage()
                m_image.loadFromData(cover_bytes)

                if with_border:
                    m_image = m_image.scaledToHeight(
                        self.COVER_ICON_SIZE - self.BORDER_WIDTH * 2,
                        Qt.SmoothTransformation)

                    # Construct a QPixmap with yellow background
                    self.m_pixmap = QPixmap(
                        QSize(m_image.width() + self.BORDER_WIDTH * 2,
                              m_image.height() + self.BORDER_WIDTH * 2))

                    m_painter = QPainter(self.m_pixmap)
                    m_painter.setRenderHints(m_painter.Antialiasing)

                    m_painter.fillRect(self.m_pixmap.rect(),
                                       QColor(0xFD, 0xFF, 0x99))
                    m_painter.drawImage(self.BORDER_WIDTH, self.BORDER_WIDTH,
                                        m_image)
                else:
                    m_image = m_image.scaledToHeight(self.COVER_ICON_SIZE,
                                                     Qt.SmoothTransformation)

                    self.m_pixmap = QPixmap(
                        QSize(m_image.width(), m_image.height()))

                    m_painter = QPainter(self.m_pixmap)
                    m_painter.setRenderHints(m_painter.Antialiasing)

                    m_painter.drawImage(0, 0, m_image)

                self.marvin_cover.setPixmap(self.m_pixmap)
            else:
                # No cover available, use generic
                self._log("No cached cover, using generic")
                pixmap = QPixmap()
                pixmap.load(I('book.png'))
                pixmap = pixmap.scaled(self.COVER_ICON_SIZE,
                                       self.COVER_ICON_SIZE,
                                       aspectRatioMode=Qt.KeepAspectRatio,
                                       transformMode=Qt.SmoothTransformation)
                self.marvin_cover.setPixmap(pixmap)
Esempio n. 21
0
class ImagePopup(object):

    def __init__(self, parent):
        self.current_img = QPixmap()
        self.current_url = QUrl()
        self.parent = parent
        self.dialogs = []

    def __call__(self):
        if self.current_img.isNull():
            return
        d = ImageView(self.parent, self.current_img, self.current_url)
        self.dialogs.append(d)
        d.finished.connect(self.cleanup, type=Qt.QueuedConnection)
        d()

    def cleanup(self):
        for d in tuple(self.dialogs):
            if not d.isVisible():
                self.dialogs.remove(d)

if __name__ == '__main__':
    import sys
    app = QApplication([])
    p = QPixmap()
    p.load(sys.argv[-1])
    u = QUrl.fromLocalFile(sys.argv[-1])
    d = ImageView(None, p, u)
    d()
    app.exec_()
Esempio n. 22
0
class LetsShareBooksDialog(QDialog):
    def __init__(self, gui, icon, do_user_config, qaction, us):
        QDialog.__init__(self, gui)
        self.gui = gui
        self.do_user_config = do_user_config
        self.qaction = qaction
        self.us = us
        self.clip = QApplication.clipboard()
        self.main_gui = calibre_main()
        
        self.urllib_thread = UrlLibThread(self.us)
        self.kill_servers_thread = KillServersThread(self.us)

        self.us.check_finished = True
        
        self.pxmp = QPixmap()
        self.pxmp.load('images/icon_connected.png')
        self.icon_connected = QIcon(self.pxmp)

        self.setStyleSheet("""
        QDialog {
                background-color: white;
        }

        QPushButton { 
                font-size: 16px; 
                border-style: solid;
                border-color: red;
                font-family:'BitstreamVeraSansMono',Consolas,monospace;
                text-transform: uppercase;
        }

        QPushButton#arrow {
                border-width: 16px;
                border-right-color:white;
                padding: -10px;
                color:red;
        }

        QPushButton#url {
                background-color: red;
                min-width: 460px;
                color: white;
                text-align: left;
               }
        
        QPushButton#url:hover {
                background-color: white;
                color: red;
                }

        QPushButton#share {
                background-color: red;
                color: white;
                margin-right: 10px;
                }

        QPushButton#share:hover {
                background-color: white;
                color: red;
                }

        QPushButton#url2 {
                color: #222;
                text-align: left;
        }
        QPushButton#url2:hover {
                color: red;
                }
                """)

        self.ll = QVBoxLayout()
        #self.ll.setSpacing(1)
        
        self.l = QHBoxLayout()
        self.l.setSpacing(0)
        self.l.setMargin(0)
        #self.l.setContentsMargins(0,0,0,0)
        self.w = QWidget()
        self.w.setLayout(self.l)

        self.setLayout(self.ll)
        self.setWindowIcon(icon)

        self.lets_share_button = QPushButton()
        self.lets_share_button.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)
        self.lets_share_button.setObjectName("share")
        self.lets_share_button.clicked.connect(self.lets_share)
        
        self.stop_share_button = QPushButton()
        self.stop_share_button.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)
        self.stop_share_button.setObjectName("share")
        self.stop_share_button.clicked.connect(self.stop_share)

        self.l.addWidget(self.lets_share_button)
        self.l.addWidget(self.stop_share_button)
        
        if self.us.button_state == "start":
            self.lets_share_button.show()
            self.stop_share_button.hide()
            self.lets_share_button.setText(self.us.share_button_text)
        else:
            self.lets_share_button.hide()
            self.stop_share_button.show()
            self.stop_share_button.setText(self.us.share_button_text)

        self.url_label = QPushButton()
        self.url_label.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)
        self.url_label.setObjectName("url")
        self.url_label.clicked.connect(self.open_url)
        self.l.addWidget(self.url_label)
        
        self.arrow_button = QPushButton("_____")
        self.arrow_button.setObjectName("arrow")
        self.l.addWidget(self.arrow_button)

        self.ll.addWidget(self.w)
        self.ll.addSpacing(10)
        
        self.chat_button = QPushButton("Chat room: https://chat.memoryoftheworld.org")
        #self.chat_button.hovered.connect(self.setCursorToHand)
        self.chat_button.setObjectName("url2")
        self.chat_button.setToolTip('Meetings every thursday at 23:59 (central eruopean time)')
        self.chat_button.clicked.connect(functools.partial(self.open_url2, "https://chat.memoryoftheworld.org"))
        self.ll.addWidget(self.chat_button)
        
        self.about_project_button = QPushButton('Public Library: http://www.memoryoftheworld.org')
        self.about_project_button.setObjectName("url2")
        self.about_project_button.setToolTip('When everyone is librarian, library is everywhere.')
        self.about_project_button.clicked.connect(functools.partial(self.open_url2, "http://www.memoryoftheworld.org"))
        self.ll.addWidget(self.about_project_button)
        
        #self.debug_log = QListWidget()
        #self.ll.addWidget(self.debug_log)
        #self.debug_log.addItem("Initiatied!")
       
        self.upgrade_button = QPushButton('Please download and upgrade from {0} to {1} version of plugin.'.format(self.us.running_version, self.us.latest_version))
        self.upgrade_button.setObjectName("url2")
        self.upgrade_button.setToolTip('Running latest version you make developers happy')
        self.upgrade_button.clicked.connect(functools.partial(self.open_url2, self.us.plugin_url))

        version_list = [self.us.running_version, self.us.latest_version]
        version_list.sort(key=lambda s: map(int, s.split('.')))
        if self.us.running_version != self.us.latest_version:
            if self.us.running_version == version_list[0]:
                self.ll.addSpacing(20)
                self.ll.addWidget(self.upgrade_button)

        self.resize(self.sizeHint())

        self.se = open("lsb.log", "w+b")
        self.so = self.se

        sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
        os.dup2(self.so.fileno(), sys.stdout.fileno())
        os.dup2(self.se.fileno(), sys.stderr.fileno())

        self.timer = QTimer()
        self.timer.timeout.connect(self.check_and_render)
        self.timer_period = 300
        self.timer.start(self.timer_period)
        
        self.error_log = ""

    def lets_share(self):
        self.lets_share_button.setEnabled(False)
        self.timer.stop()
        self.us.share_button_text = "Connecting..."
        #self.debug_log.addItem("Let's share!")
        self.us.counter = 0
        self.us.lost_connection = False

        if not self.us.ssh_proc:
            self.main_gui.start_content_server()
            opts, args = server_config().option_parser().parse_args(['calibre-server'])
            self.calibre_server_port = opts.port

            if sys.platform == "win32":
                self.win_reg = subprocess.Popen("regedit /s .hosts.reg")
                self.us.win_port = int(random.random()*40000+10000)
                self.us.ssh_proc = subprocess.Popen("lsbtunnel.exe -N -T tunnel@{2} -R {0}:localhost:{1} -P 722".format(self.us.win_port, self.calibre_server_port, prefs['lsb_server']), shell=True)
                self.us.lsb_url = "https://www{0}.{1}".format(self.us.win_port, prefs['lsb_server'])
                #_dev_self.us.lsb_url = "http://www{0}.{1}".format(self.us.win_port, prefs['lsb_server'])
                self.us.lsb_url_text = "Go to: {0}".format(self.us.lsb_url)
                self.us.found_url = True
            else:
                self.us.ssh_proc = subprocess.Popen(['ssh', '-T', '-N', '-g', '-o', 'UserKnownHostsFile=.userknownhostsfile', '-o', 'TCPKeepAlive=yes', '-o', 'ServerAliveINterval=60', prefs['lsb_server'], '-l', 'tunnel', '-R', '0:localhost:{0}'.format(self.calibre_server_port), '-p', '722'])
                self.us.found_url = None
            
            self.qaction.setIcon(get_icon('images/icon_connected.png'))
            self.us.connecting = True
            self.us.connecting_now = datetime.datetime.now()
            self.timer.start(self.timer_period)
              
    def stop_share(self):
        self.stop_share_button.setEnabled(False)
        #self.debug_log.addItem("Stop Share!")
        self.timer.stop()
        self.us.lsb_url = 'nourl'
        self.us.urllib_result = ''
        self.us.disconnecting = True

        self.qaction.setIcon(get_icon('images/icon.png'))
        
        self.kill_servers_thread.start()

        self.timer.start(self.timer_period)

    def check_and_render(self):
        #self.show_debug()
        if self.us.button_state == "start":
            self.stop_share_button.hide()
            self.lets_share_button.show()
            self.lets_share_button.setText(self.us.share_button_text)
        else:
            self.lets_share_button.hide()
            self.stop_share_button.show()
            self.stop_share_button.setText(self.us.share_button_text)
       
        
        if self.us.disconnecting:
            self.us.share_button_text = "Disconnecting..."
            if self.us.lost_connection:
                self.us.lsb_url_text = 'Lost connection. Please start sharing again.'
                self.us.url_label_tooltip = '<<<< Click on Start sharing button again.'
            else:
                self.us.lsb_url_text = 'Be a librarian. Share your library.'
                self.us.url_label_tooltip = '<<<< Be a librarian. Click on Start sharing button.<<<<'

            if self.us.kill_finished:
                #self.debug_log.addItem("Let's share connect!")
                self.us.button_state = "start"
                self.us.share_button_text = "Start sharing"
                self.us.disconnecting = False
                self.us.kill_finished = False
                self.lets_share_button.setEnabled(True)

        elif self.us.connecting:
            if self.us.connecting_now:
                if (datetime.datetime.now() - self.us.connecting_now) > datetime.timedelta(seconds=10):
                    #self.debug_log.addItem("Timeout!")
                    self.us.http_error = None
                    self.us.lost_connection = True
                    self.us.connecting = False
                    self.us.connecting_now = None
                    self.stop_share()
                elif self.us.found_url:
                    self.us.check_finished = False
                    self.urllib_thread.start()

            if self.us.lsb_url == "nourl" and self.us.ssh_proc and sys.platform != "win32":
                #self.debug_log.addItem("Wait for Allocated port!")
            
                self.se.seek(0)
                result = self.se.readlines()
        
                for line in result:
                    m = re.match("^Allocated port (.*) for .*", line)
                    try:
                        #self.debug_log.addItem(self.us.lsb_url)
                        self.us.lsb_url = 'https://www{0}.{1}'.format(m.groups()[0], prefs['lsb_server'])
                        #_dev_self.us.lsb_url = 'http://www{0}.{1}'.format(m.groups()[0], prefs['lsb_server'])
                        self.us.lsb_url_text = "Go to: {0}".format(self.us.lsb_url)
                        self.us.url_label_tooltip = 'Copy URL to clipboard and check it out in a browser!'
                        self.us.http_error = None
                        self.us.found_url = True
                    except:
                        pass
        
            elif self.us.urllib_result == 200:
                #self.debug_log.addItem("Finish Connecting State!")
                self.se.seek(0)
                self.se.truncate()
                self.us.share_button_text = "Stop sharing"
                self.us.button_state = "stop"
                self.stop_share_button.setEnabled(True)
                self.us.connecting = False
                self.us.connecting_now = None
                self.us.found_url = None

        elif self.us.http_error and self.us.button_state == "stop":
            #self.debug_log.addItem("Error!")
            self.us.http_error = None
            self.us.lost_connection = True
            self.stop_share()


        elif self.us.check_finished: 
            #if self.debug_log.item(self.debug_log.count()-1).text()[:10] == "Finally Ca":
            #    self.us.debug_counter = self.us.debug_counter + 1
            #else:
            #    self.debug_log.addItem("Finally Called Thread!({0})".format(self.us.debug_counter))
            #    self.us.debug_counter = 1
            self.us.check_finished = False
            self.urllib_thread.start()

        if self.us.urllib_result == 200 and self.us.button_state == "stop":
            self.stop_share_button.setEnabled(True)

        if self.us.lsb_url == 'nourl' and self.us.button_state == "start":
            self.lets_share_button.setEnabled(True)

        self.setWindowTitle("{0} - {1}".format(self.us.window_title, self.us.lsb_url))
        self.url_label.setToolTip(self.us.url_label_tooltip)
        self.url_label.setText(self.us.lsb_url_text)

    def open_url(self):
        if self.us.lsb_url == "nourl" and not self.us.http_error:
            self.us.url_label_tooltip = '<<<< Be a librarian. Click on Start sharing button.'
            self.us.lsb_url_text = '<<<< Be a librarian. Click on Start sharing button.'
        else:
            self.clip.setText(self.us.lsb_url)
            webbrowser.open(str(self.us.lsb_url))
            if self.us.lsb_url != "nourl":
                self.us.lsb_url_text = "Library at: {0}".format(self.us.lsb_url)

    def open_url2(self, url):
        self.clip.setText(url)
        webbrowser.open(url)

    def show_debug(self):
        if self.us.debug_item:
            self.debug_log.addItem(str(self.us.debug_item))
            self.us.debug_item = None
        self.debug_log.scrollToBottom()
        self.debug_log.repaint()

    def closeEvent(self, e):
        self.hide()
        #self.urllib_thread.stop()
        #self.kill_servers_thread.stop()

    def config(self):
        self.do_user_config(parent=self)
        self.label.setText(prefs['lsb_server'])
Esempio n. 23
0
class GuiRunner(QObject):
    """Make sure an event loop is running before starting the main work of
    initialization"""

    def __init__(self, opts, args, actions, listener, app, gui_debug=None):
        self.startup_time = time.time()
        self.opts, self.args, self.listener, self.app = opts, args, listener, app
        self.gui_debug = gui_debug
        self.actions = actions
        self.main = None
        QObject.__init__(self)
        self.splash_screen = None
        self.timer = QTimer.singleShot(1, self.initialize)
        if DEBUG:
            prints("Starting up...")

    def start_gui(self, db):
        from calibre.gui2.ui import Main

        main = self.main = Main(self.opts, gui_debug=self.gui_debug)
        if self.splash_screen is not None:
            self.splash_screen.showMessage(_("Initializing user interface..."))
        with gprefs:  # Only write gui.json after initialization is complete
            main.initialize(self.library_path, db, self.listener, self.actions)
        if self.splash_screen is not None:
            self.splash_screen.finish(main)
        if DEBUG:
            prints("Started up in %.2f seconds" % (time.time() - self.startup_time), "with", len(db.data), "books")
        add_filesystem_book = partial(main.iactions["Add Books"].add_filesystem_book, allow_device=False)
        sys.excepthook = main.unhandled_exception
        if len(self.args) > 1:
            files = [os.path.abspath(p) for p in self.args[1:] if not os.path.isdir(p)]
            if len(files) < len(sys.argv[1:]):
                prints("Ignoring directories passed as command line arguments")
            if files:
                add_filesystem_book(files)
        for event in self.app.file_event_hook.events:
            add_filesystem_book(event)
        self.app.file_event_hook = add_filesystem_book

    def initialization_failed(self):
        print "Catastrophic failure initializing GUI, bailing out..."
        QCoreApplication.exit(1)
        raise SystemExit(1)

    def initialize_db_stage2(self, db, tb):
        from calibre.db.legacy import LibraryDatabase

        if db is None and tb is not None:
            # DB Repair failed
            error_dialog(
                self.splash_screen,
                _("Repairing failed"),
                _("The database repair failed. Starting with " "a new empty library."),
                det_msg=tb,
                show=True,
            )
        if db is None:
            candidate = choose_dir(
                self.splash_screen,
                "choose calibre library",
                _("Choose a location for your new calibre e-book library"),
                default_dir=get_default_library_path(),
            )
            if not candidate:
                self.initialization_failed()

            try:
                self.library_path = candidate
                db = LibraryDatabase(candidate)
            except:
                error_dialog(
                    self.splash_screen,
                    _("Bad database location"),
                    _("Bad database location %r. calibre will now quit.") % self.library_path,
                    det_msg=traceback.format_exc(),
                    show=True,
                )
                self.initialization_failed()

        try:
            self.start_gui(db)
        except Exception:
            error_dialog(
                self.main,
                _("Startup error"),
                _(
                    "There was an error during {0} startup."
                    " Parts of {0} may not function. Click Show details to learn more."
                ).format(__appname__),
                det_msg=traceback.format_exc(),
                show=True,
            )

    def initialize_db(self):
        from calibre.db.legacy import LibraryDatabase

        db = None
        try:
            db = LibraryDatabase(self.library_path)
        except apsw.Error:
            repair = question_dialog(
                self.splash_screen,
                _("Corrupted database"),
                _(
                    "The library database at %s appears to be corrupted. Do "
                    "you want calibre to try and rebuild it automatically? "
                    "The rebuild may not be completely successful. "
                    "If you say No, a new empty calibre library will be created."
                )
                % force_unicode(self.library_path, filesystem_encoding),
                det_msg=traceback.format_exc(),
            )
            if repair:
                if repair_library(self.library_path):
                    db = LibraryDatabase(self.library_path)
        except:
            error_dialog(
                self.splash_screen,
                _("Bad database location"),
                _("Bad database location %r. Will start with " " a new, empty calibre library") % self.library_path,
                det_msg=traceback.format_exc(),
                show=True,
            )

        self.initialize_db_stage2(db, None)

    def show_splash_screen(self):
        self.splash_pixmap = QPixmap()
        self.splash_pixmap.load(I("library.png"))
        self.splash_screen = QSplashScreen(self.splash_pixmap)
        self.splash_screen.showMessage(_("Starting %s: Loading books...") % __appname__)
        self.splash_screen.show()
        QApplication.instance().processEvents()

    def initialize(self, *args):
        if gprefs["show_splash_screen"]:
            self.show_splash_screen()

        self.library_path = get_library_path(parent=self.splash_screen)
        if not self.library_path:
            self.initialization_failed()

        self.initialize_db()
Esempio n. 24
0
class ImagePopup(object):

    def __init__(self, parent):
        self.current_img = QPixmap()
        self.current_url = QUrl()
        self.parent = parent
        self.dialogs = []

    def __call__(self):
        if self.current_img.isNull():
            return
        d = ImageView(self.parent, self.current_img, self.current_url)
        self.dialogs.append(d)
        d.finished.connect(self.cleanup, type=Qt.QueuedConnection)
        d()

    def cleanup(self):
        for d in tuple(self.dialogs):
            if not d.isVisible():
                self.dialogs.remove(d)

if __name__ == '__main__':
    import sys
    app = QApplication([])
    p = QPixmap()
    p.load(sys.argv[-1])
    u = QUrl.fromLocalFile(sys.argv[-1])
    d = ImageView(None, p, u)
    d()
    app.exec_()