Example #1
0
    def __init__(self, parent):
        super(CharacterDialog, self).__init__(parent)
        self.setWindowTitle(_("KeepKey Seed Recovery"))
        self.character_pos = 0
        self.word_pos = 0
        self.loop = QEventLoop()
        self.word_help = QLabel()
        self.char_buttons = []

        vbox = QVBoxLayout(self)
        vbox.addWidget(WWLabel(CHARACTER_RECOVERY))
        hbox = QHBoxLayout()
        hbox.addWidget(self.word_help)
        for i in range(4):
            char_button = CharacterButton('*')
            char_button.setMaximumWidth(36)
            self.char_buttons.append(char_button)
            hbox.addWidget(char_button)
        self.accept_button = CharacterButton(_("Accept Word"))
        self.accept_button.clicked.connect(partial(self.process_key, 32))
        self.rejected.connect(partial(self.loop.exit, 1))
        hbox.addWidget(self.accept_button)
        hbox.addStretch(1)
        vbox.addLayout(hbox)

        self.finished_button = QPushButton(_("Seed Entered"))
        self.cancel_button = QPushButton(_("Cancel"))
        self.finished_button.clicked.connect(
            partial(self.process_key, Qt.Key_Return))
        self.cancel_button.clicked.connect(self.rejected)
        buttons = Buttons(self.finished_button, self.cancel_button)
        vbox.addSpacing(40)
        vbox.addLayout(buttons)
        self.refresh()
        self.show()
Example #2
0
    def __init__(
        self,
        parent=None,
    ):
        print repr(self), repr(parent)
        QDialog.__init__(self, parent)
        self.parent = parent
        self.setWindowTitle("{0} {1}: Rename {0}".format(
            PLUGIN_NAME, PLUGIN_VERSION, parent.key_type_name))
        layout = QVBoxLayout(self)
        self.setLayout(layout)

        data_group_box = QGroupBox('', self)
        layout.addWidget(data_group_box)
        data_group_box_layout = QVBoxLayout()
        data_group_box.setLayout(data_group_box_layout)

        data_group_box_layout.addWidget(QLabel('New Key Name:', self))
        self.key_ledit = QLineEdit(self.parent.listy.currentItem().text(),
                                   self)
        self.key_ledit.setToolTip(
            u"Enter a new name for this existing {0}.".format(
                parent.key_type_name))
        data_group_box_layout.addWidget(self.key_ledit)

        layout.addSpacing(20)

        self.button_box = QDialogButtonBox(QDialogButtonBox.Ok
                                           | QDialogButtonBox.Cancel)
        self.button_box.accepted.connect(self.accept)
        self.button_box.rejected.connect(self.reject)
        layout.addWidget(self.button_box)

        self.resize(self.sizeHint())
Example #3
0
    def __init__(self, parent):
        super(CharacterDialog, self).__init__(parent)
        self.setWindowTitle(_("KeepKey Seed Recovery"))
        self.character_pos = 0
        self.word_pos = 0
        self.loop = QEventLoop()
        self.word_help = QLabel()
        self.char_buttons = []

        vbox = QVBoxLayout(self)
        vbox.addWidget(WWLabel(CHARACTER_RECOVERY))
        hbox = QHBoxLayout()
        hbox.addWidget(self.word_help)
        for i in range(4):
            char_button = CharacterButton('*')
            char_button.setMaximumWidth(36)
            self.char_buttons.append(char_button)
            hbox.addWidget(char_button)
        self.accept_button = CharacterButton(_("Accept Word"))
        self.accept_button.clicked.connect(partial(self.process_key, 32))
        self.rejected.connect(partial(self.loop.exit, 1))
        hbox.addWidget(self.accept_button)
        hbox.addStretch(1)
        vbox.addLayout(hbox)

        self.finished_button = QPushButton(_("Seed Entered"))
        self.cancel_button = QPushButton(_("Cancel"))
        self.finished_button.clicked.connect(partial(self.process_key,
                                                     Qt.Key_Return))
        self.cancel_button.clicked.connect(self.rejected)
        buttons = Buttons(self.finished_button, self.cancel_button)
        vbox.addSpacing(40)
        vbox.addLayout(buttons)
        self.refresh()
        self.show()
Example #4
0
 def __init__(self, parent, config_name=None, buttons=[], *args):
     """Creates dialog.
     'config_name' is used to get/set default window size from Config object
     'buttons' can be a list of names or (QPixmapWrapper,name[,tooltip]) tuples to provide
     custom buttons at the bottom of the dialog. When a button is clicked, the dialog
     emits SIGNAL("name").
     A "Close" button is always provided, this simply hides the dialog.
     """
     QDialog.__init__(self, parent, *args)
     self.setModal(False)
     lo = QVBoxLayout(self)
     # create viewer
     self.label = QLabel(self)
     self.label.setMargin(5)
     self.label.setWordWrap(True)
     lo.addWidget(self.label)
     self.label.hide()
     self.viewer = QTextBrowser(self)
     lo.addWidget(self.viewer)
     # self.viewer.setReadOnly(True)
     self.viewer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
     QObject.connect(self.viewer, SIGNAL("anchorClicked(const QUrl &)"), self._urlClicked)
     self._source = None
     lo.addSpacing(5)
     # create button bar
     btnfr = QFrame(self)
     btnfr.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed)
     # btnfr.setMargin(5)
     lo.addWidget(btnfr)
     lo.addSpacing(5)
     btnfr_lo = QHBoxLayout(btnfr)
     btnfr_lo.setMargin(5)
     # add user buttons
     self._user_buttons = {}
     for name in buttons:
         if isinstance(name, str):
             btn = QPushButton(name, btnfr)
         elif isinstance(name, (list, tuple)):
             if len(name) < 3:
                 pixmap, name = name
                 tip = None
             else:
                 pixmap, name, tip = name
             btn = QPushButton(pixmap.icon(), name, btnfr)
             if tip:
                 btn.setToolTip(tip)
         self._user_buttons[name] = btn
         btn._clicked = Kittens.utils.curry(self.emit, SIGNAL(name))
         self.connect(btn, SIGNAL("clicked()"), btn._clicked)
         btnfr_lo.addWidget(btn, 1)
     # add a Close button
     btnfr_lo.addStretch(100)
     closebtn = QPushButton(pixmaps.grey_round_cross.icon(), "Close", btnfr)
     self.connect(closebtn, SIGNAL("clicked()"), self.hide)
     btnfr_lo.addWidget(closebtn, 1)
     # resize selves
     self.config_name = config_name or "html-viewer"
     width = Config.getint('%s-width' % self.config_name, 512)
     height = Config.getint('%s-height' % self.config_name, 512)
     self.resize(QSize(width, height))
Example #5
0
    def __init__(self, parent=None,):
        print repr(self), repr(parent)
        QDialog.__init__(self, parent)
        self.parent = parent
        self.setWindowTitle("{0} {1}: Rename {0}".format(PLUGIN_NAME, PLUGIN_VERSION, parent.key_type_name))
        layout = QVBoxLayout(self)
        self.setLayout(layout)

        data_group_box = QGroupBox('', self)
        layout.addWidget(data_group_box)
        data_group_box_layout = QVBoxLayout()
        data_group_box.setLayout(data_group_box_layout)

        data_group_box_layout.addWidget(QLabel('New Key Name:', self))
        self.key_ledit = QLineEdit(self.parent.listy.currentItem().text(), self)
        self.key_ledit.setToolTip(u"Enter a new name for this existing {0}.".format(parent.key_type_name))
        data_group_box_layout.addWidget(self.key_ledit)

        layout.addSpacing(20)

        self.button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        self.button_box.accepted.connect(self.accept)
        self.button_box.rejected.connect(self.reject)
        layout.addWidget(self.button_box)

        self.resize(self.sizeHint())
Example #6
0
class BlockingBusy(QDialog):
    def __init__(self, msg, parent=None, window_title=_('Working')):
        QDialog.__init__(self, parent)

        self._layout = QVBoxLayout()
        self.setLayout(self._layout)
        self.msg = QLabel(msg)
        #self.msg.setWordWrap(True)
        self.font = QFont()
        self.font.setPointSize(self.font.pointSize() + 8)
        self.msg.setFont(self.font)
        self.pi = ProgressIndicator(self)
        self.pi.setDisplaySize(100)
        self._layout.addWidget(self.pi, 0, Qt.AlignHCenter)
        self._layout.addSpacing(15)
        self._layout.addWidget(self.msg, 0, Qt.AlignHCenter)
        self.start()
        self.setWindowTitle(window_title)
        self.resize(self.sizeHint())

    def start(self):
        self.pi.startAnimation()

    def stop(self):
        self.pi.stopAnimation()

    def accept(self):
        self.stop()
        return QDialog.accept(self)

    def reject(self):
        pass  # Cannot cancel this dialog
Example #7
0
 def __init__(self, parent, modal=True, flags=Qt.WindowFlags(), caption="Select Tags", ok_button="Select"):
     QDialog.__init__(self, parent, flags)
     self.setModal(modal)
     self.setWindowTitle(caption)
     lo = QVBoxLayout(self)
     lo.setMargin(10)
     lo.setSpacing(5)
     # tag selector
     self.wtagsel = QListWidget(self)
     lo.addWidget(self.wtagsel)
     #    self.wtagsel.setColumnMode(QListBox.FitToWidth)
     self.wtagsel.setSelectionMode(QListWidget.MultiSelection)
     QObject.connect(self.wtagsel, SIGNAL("itemSelectionChanged()"), self._check_tag)
     # buttons
     lo.addSpacing(10)
     lo2 = QHBoxLayout()
     lo.addLayout(lo2)
     lo2.setContentsMargins(0, 0, 0, 0)
     lo2.setMargin(5)
     self.wokbtn = QPushButton(ok_button, self)
     self.wokbtn.setMinimumWidth(128)
     QObject.connect(self.wokbtn, SIGNAL("clicked()"), self.accept)
     self.wokbtn.setEnabled(False)
     cancelbtn = QPushButton("Cancel", self)
     cancelbtn.setMinimumWidth(128)
     QObject.connect(cancelbtn, SIGNAL("clicked()"), self.reject)
     lo2.addWidget(self.wokbtn)
     lo2.addStretch(1)
     lo2.addWidget(cancelbtn)
     self.setMinimumWidth(384)
     self._tagnames = []
Example #8
0
class BlockingBusy(QDialog):

    def __init__(self, msg, parent=None, window_title=_('Working')):
        QDialog.__init__(self, parent)

        self._layout = QVBoxLayout()
        self.setLayout(self._layout)
        self.msg = QLabel(msg)
        #self.msg.setWordWrap(True)
        self.font = QFont()
        self.font.setPointSize(self.font.pointSize() + 8)
        self.msg.setFont(self.font)
        self.pi = ProgressIndicator(self)
        self.pi.setDisplaySize(100)
        self._layout.addWidget(self.pi, 0, Qt.AlignHCenter)
        self._layout.addSpacing(15)
        self._layout.addWidget(self.msg, 0, Qt.AlignHCenter)
        self.start()
        self.setWindowTitle(window_title)
        self.resize(self.sizeHint())

    def start(self):
        self.pi.startAnimation()

    def stop(self):
        self.pi.stopAnimation()

    def accept(self):
        self.stop()
        return QDialog.accept(self)

    def reject(self):
        pass # Cannot cancel this dialog
Example #9
0
 def __init__(self, parent):
     QWidget.__init__(self, parent)
     l = QVBoxLayout()
     self.setLayout(l)
     l.addStretch(10)
     self.pi = ProgressIndicator(self, 128)
     l.addWidget(self.pi, alignment=Qt.AlignHCenter)
     self.dummy = QLabel('<h2>\xa0')
     l.addSpacing(10)
     l.addWidget(self.dummy, alignment=Qt.AlignHCenter)
     l.addStretch(10)
     self.text = _('Calculating differences, please wait...')
Example #10
0
 def __init__(self, parent):
     QWidget.__init__(self, parent)
     l = QVBoxLayout()
     self.setLayout(l)
     l.addStretch(10)
     self.pi = ProgressIndicator(self, 128)
     l.addWidget(self.pi, alignment=Qt.AlignHCenter)
     self.dummy = QLabel('<h2>\xa0')
     l.addSpacing(10)
     l.addWidget(self.dummy, alignment=Qt.AlignHCenter)
     l.addStretch(10)
     self.text = _('Calculating differences, please wait...')
Example #11
0
 def __init__(self, parent):
     QWidget.__init__(self, parent)
     l = QVBoxLayout()
     self.setLayout(l)
     l.addStretch(10)
     self.pi = ProgressIndicator(self, 128)
     l.addWidget(self.pi, alignment=Qt.AlignHCenter)
     self.dummy = QLabel('<h2>\xa0')
     l.addSpacing(10)
     l.addWidget(self.dummy, alignment=Qt.AlignHCenter)
     l.addStretch(10)
     self.setVisible(False)
     self.text = ''
Example #12
0
    def __init__(self, parent=None,):
        QDialog.__init__(self, parent)
        self.parent = parent
        self.setWindowTitle(u"{0} {1}: Create New eReader Key".format(PLUGIN_NAME, PLUGIN_VERSION))
        layout = QVBoxLayout(self)
        self.setLayout(layout)

        data_group_box = QGroupBox(u"", self)
        layout.addWidget(data_group_box)
        data_group_box_layout = QVBoxLayout()
        data_group_box.setLayout(data_group_box_layout)

        key_group = QHBoxLayout()
        data_group_box_layout.addLayout(key_group)
        key_group.addWidget(QLabel(u"Unique Key Name:", self))
        self.key_ledit = QLineEdit("", self)
        self.key_ledit.setToolTip(u"<p>Enter an identifying name for this new key.\nIt should be something that will help you remember what personal information was used to create it.")
        key_group.addWidget(self.key_ledit)
        key_label = QLabel(_(''), self)
        key_label.setAlignment(Qt.AlignHCenter)
        data_group_box_layout.addWidget(key_label)

        name_group = QHBoxLayout()
        data_group_box_layout.addLayout(name_group)
        name_group.addWidget(QLabel(u"Your Name:", self))
        self.name_ledit = QLineEdit(u"", self)
        self.name_ledit.setToolTip(u"Enter the name for this eReader key, usually the name on your credit card.\nIt will only be used to generate this one-time key and won\'t be stored anywhere in calibre or on your computer.\n(ex: Mr Jonathan Q Smith)")
        name_group.addWidget(self.name_ledit)
        name_disclaimer_label = QLabel(_(u"(Will not be saved in configuration data)"), self)
        name_disclaimer_label.setAlignment(Qt.AlignHCenter)
        data_group_box_layout.addWidget(name_disclaimer_label)

        ccn_group = QHBoxLayout()
        data_group_box_layout.addLayout(ccn_group)
        ccn_group.addWidget(QLabel(u"Credit Card#:", self))
        self.cc_ledit = QLineEdit(u"", self)
        self.cc_ledit.setToolTip(u"<p>Enter the last 8 digits of credit card number for this eReader key.\nThey will only be used to generate this one-time key and won\'t be stored anywhere in calibre or on your computer.")
        ccn_group.addWidget(self.cc_ledit)
        ccn_disclaimer_label = QLabel(_('(Will not be saved in configuration data)'), self)
        ccn_disclaimer_label.setAlignment(Qt.AlignHCenter)
        data_group_box_layout.addWidget(ccn_disclaimer_label)
        layout.addSpacing(10)

        self.button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        self.button_box.accepted.connect(self.accept)
        self.button_box.rejected.connect(self.reject)
        layout.addWidget(self.button_box)

        self.resize(self.sizeHint())
Example #13
0
 def __init__(self, parent, modal=True, flags=Qt.WindowFlags()):
     QDialog.__init__(self, parent, flags)
     self.setModal(modal)
     self.setWindowTitle("Add FITS brick")
     lo = QVBoxLayout(self)
     lo.setMargin(10)
     lo.setSpacing(5)
     # file selector
     self.wfile = FileSelector(self,
                               label="FITS filename:",
                               dialog_label="FITS file",
                               default_suffix="fits",
                               file_types="FITS files (*.fits *.FITS)",
                               file_mode=QFileDialog.ExistingFile)
     lo.addWidget(self.wfile)
     # overwrite or add mode
     lo1 = QGridLayout()
     lo.addLayout(lo1)
     lo1.setContentsMargins(0, 0, 0, 0)
     lo1.addWidget(QLabel("Padding factor:", self), 0, 0)
     self.wpad = QLineEdit("2", self)
     self.wpad.setValidator(QDoubleValidator(self))
     lo1.addWidget(self.wpad, 0, 1)
     lo1.addWidget(QLabel("Assign source name:", self), 1, 0)
     self.wname = QLineEdit(self)
     lo1.addWidget(self.wname, 1, 1)
     # OK/cancel buttons
     lo.addSpacing(10)
     lo2 = QHBoxLayout()
     lo.addLayout(lo2)
     lo2.setContentsMargins(0, 0, 0, 0)
     lo2.setMargin(5)
     self.wokbtn = QPushButton("OK", self)
     self.wokbtn.setMinimumWidth(128)
     QObject.connect(self.wokbtn, SIGNAL("clicked()"), self.accept)
     self.wokbtn.setEnabled(False)
     cancelbtn = QPushButton("Cancel", self)
     cancelbtn.setMinimumWidth(128)
     QObject.connect(cancelbtn, SIGNAL("clicked()"), self.reject)
     lo2.addWidget(self.wokbtn)
     lo2.addStretch(1)
     lo2.addWidget(cancelbtn)
     self.setMinimumWidth(384)
     # signals
     QObject.connect(self.wfile, SIGNAL("filenameSelected"),
                     self._fileSelected)
     # internal state
     self.qerrmsg = QErrorMessage(self)
Example #14
0
 def __init__(self, parent, modal=True, flags=Qt.WindowFlags()):
     QDialog.__init__(self, parent, flags)
     self.setModal(modal)
     self.setWindowTitle("Add Tag")
     lo = QVBoxLayout(self)
     lo.setMargin(10)
     lo.setSpacing(5)
     # tag selector
     lo1 = QHBoxLayout()
     lo.addLayout(lo1)
     lo1.setSpacing(5)
     self.wtagsel = QComboBox(self)
     self.wtagsel.setEditable(True)
     wtagsel_lbl = QLabel("&Tag:", self)
     wtagsel_lbl.setBuddy(self.wtagsel)
     lo1.addWidget(wtagsel_lbl, 0)
     lo1.addWidget(self.wtagsel, 1)
     QObject.connect(self.wtagsel, SIGNAL("activated(int)"),
                     self._check_tag)
     QObject.connect(self.wtagsel,
                     SIGNAL("editTextChanged(const QString &)"),
                     self._check_tag_text)
     # value editor
     self.valedit = ValueTypeEditor(self)
     lo.addWidget(self.valedit)
     # buttons
     lo.addSpacing(10)
     lo2 = QHBoxLayout()
     lo.addLayout(lo2)
     lo2.setContentsMargins(0, 0, 0, 0)
     lo2.setMargin(5)
     self.wokbtn = QPushButton("OK", self)
     self.wokbtn.setMinimumWidth(128)
     QObject.connect(self.wokbtn, SIGNAL("clicked()"), self.accept)
     self.wokbtn.setEnabled(False)
     cancelbtn = QPushButton("Cancel", self)
     cancelbtn.setMinimumWidth(128)
     QObject.connect(cancelbtn, SIGNAL("clicked()"), self.reject)
     lo2.addWidget(self.wokbtn)
     lo2.addStretch(1)
     lo2.addWidget(cancelbtn)
     self.setMinimumWidth(384)
Example #15
0
 def __init__(self, parent, modal=True, flags=Qt.WindowFlags()):
     QDialog.__init__(self, parent, flags)
     self.setModal(modal)
     self.setWindowTitle("Add Tag")
     lo = QVBoxLayout(self)
     lo.setMargin(10)
     lo.setSpacing(5)
     # tag selector
     lo1 = QHBoxLayout()
     lo.addLayout(lo1)
     lo1.setSpacing(5)
     self.wtagsel = QComboBox(self)
     self.wtagsel.setEditable(True)
     wtagsel_lbl = QLabel("&Tag:", self)
     wtagsel_lbl.setBuddy(self.wtagsel)
     lo1.addWidget(wtagsel_lbl, 0)
     lo1.addWidget(self.wtagsel, 1)
     QObject.connect(self.wtagsel, SIGNAL("activated(int)"), self._check_tag)
     QObject.connect(self.wtagsel, SIGNAL("editTextChanged(const QString &)"), self._check_tag_text)
     # value editor
     self.valedit = ValueTypeEditor(self)
     lo.addWidget(self.valedit)
     # buttons
     lo.addSpacing(10)
     lo2 = QHBoxLayout()
     lo.addLayout(lo2)
     lo2.setContentsMargins(0, 0, 0, 0)
     lo2.setMargin(5)
     self.wokbtn = QPushButton("OK", self)
     self.wokbtn.setMinimumWidth(128)
     QObject.connect(self.wokbtn, SIGNAL("clicked()"), self.accept)
     self.wokbtn.setEnabled(False)
     cancelbtn = QPushButton("Cancel", self)
     cancelbtn.setMinimumWidth(128)
     QObject.connect(cancelbtn, SIGNAL("clicked()"), self.reject)
     lo2.addWidget(self.wokbtn)
     lo2.addStretch(1)
     lo2.addWidget(cancelbtn)
     self.setMinimumWidth(384)
Example #16
0
 def __init__(self, parent, modal=True, flags=Qt.WindowFlags()):
     QDialog.__init__(self, parent, flags)
     self.setModal(modal)
     self.setWindowTitle("Export Karma annotations")
     lo = QVBoxLayout(self)
     lo.setMargin(10)
     lo.setSpacing(5)
     # file selector
     self.wfile = FileSelector(self,
                               label="Filename:",
                               dialog_label="Karma annotations filename",
                               default_suffix="ann",
                               file_types="Karma annotations (*.ann)")
     lo.addWidget(self.wfile)
     # selected sources checkbox
     self.wsel = QCheckBox("selected sources only", self)
     lo.addWidget(self.wsel)
     # OK/cancel buttons
     lo.addSpacing(10)
     lo2 = QHBoxLayout()
     lo.addLayout(lo2)
     lo2.setContentsMargins(0, 0, 0, 0)
     lo2.setMargin(5)
     self.wokbtn = QPushButton("OK", self)
     self.wokbtn.setMinimumWidth(128)
     QObject.connect(self.wokbtn, SIGNAL("clicked()"), self.accept)
     self.wokbtn.setEnabled(False)
     cancelbtn = QPushButton("Cancel", self)
     cancelbtn.setMinimumWidth(128)
     QObject.connect(cancelbtn, SIGNAL("clicked()"), self.reject)
     lo2.addWidget(self.wokbtn)
     lo2.addStretch(1)
     lo2.addWidget(cancelbtn)
     self.setMinimumWidth(384)
     # signals
     QObject.connect(self.wfile, SIGNAL("valid"), self.wokbtn.setEnabled)
     # internal state
     self.qerrmsg = QErrorMessage(self)
     self._model_filename = None
Example #17
0
 def __init__(self, parent, modal=True, flags=Qt.WindowFlags()):
     QDialog.__init__(self, parent, flags)
     self.setModal(modal)
     self.setWindowTitle("Export Karma annotations")
     lo = QVBoxLayout(self)
     lo.setMargin(10)
     lo.setSpacing(5)
     # file selector
     self.wfile = FileSelector(self, label="Filename:", dialog_label="Karma annotations filename",
                               default_suffix="ann", file_types="Karma annotations (*.ann)")
     lo.addWidget(self.wfile)
     # selected sources checkbox
     self.wsel = QCheckBox("selected sources only", self)
     lo.addWidget(self.wsel)
     # OK/cancel buttons
     lo.addSpacing(10)
     lo2 = QHBoxLayout()
     lo.addLayout(lo2)
     lo2.setContentsMargins(0, 0, 0, 0)
     lo2.setMargin(5)
     self.wokbtn = QPushButton("OK", self)
     self.wokbtn.setMinimumWidth(128)
     QObject.connect(self.wokbtn, SIGNAL("clicked()"), self.accept)
     self.wokbtn.setEnabled(False)
     cancelbtn = QPushButton("Cancel", self)
     cancelbtn.setMinimumWidth(128)
     QObject.connect(cancelbtn, SIGNAL("clicked()"), self.reject)
     lo2.addWidget(self.wokbtn)
     lo2.addStretch(1)
     lo2.addWidget(cancelbtn)
     self.setMinimumWidth(384)
     # signals
     QObject.connect(self.wfile, SIGNAL("valid"), self.wokbtn.setEnabled)
     # internal state
     self.qerrmsg = QErrorMessage(self)
     self._model_filename = None
Example #18
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()
Example #19
0
    def __init__(self, parent=None,):
        QDialog.__init__(self, parent)
        self.parent = parent
        self.setWindowTitle(u"{0} {1}: Create New Barnes & Noble Key".format(PLUGIN_NAME, PLUGIN_VERSION))
        layout = QVBoxLayout(self)
        self.setLayout(layout)

        data_group_box = QGroupBox(u"", self)
        layout.addWidget(data_group_box)
        data_group_box_layout = QVBoxLayout()
        data_group_box.setLayout(data_group_box_layout)

        key_group = QHBoxLayout()
        data_group_box_layout.addLayout(key_group)
        key_group.addWidget(QLabel(u"Unique Key Name:", self))
        self.key_ledit = QLineEdit("", self)
        self.key_ledit.setToolTip(_(u"<p>Enter an identifying name for this new key.</p>" +
                                u"<p>It should be something that will help you remember " +
                                u"what personal information was used to create it."))
        key_group.addWidget(self.key_ledit)
        key_label = QLabel(_(''), self)
        key_label.setAlignment(Qt.AlignHCenter)
        data_group_box_layout.addWidget(key_label)

        name_group = QHBoxLayout()
        data_group_box_layout.addLayout(name_group)
        name_group.addWidget(QLabel(u"Your Name:", self))
        self.name_ledit = QLineEdit(u"", self)
        self.name_ledit.setToolTip(_(u"<p>Enter your name as it appears in your B&N " +
                                u"account or on your credit card.</p>" +
                                u"<p>It will only be used to generate this " +
                                u"one-time key and won\'t be stored anywhere " +
                                u"in calibre or on your computer.</p>" +
                                u"<p>(ex: Jonathan Smith)"))
        name_group.addWidget(self.name_ledit)
        name_disclaimer_label = QLabel(_(u"(Will not be saved in configuration data)"), self)
        name_disclaimer_label.setAlignment(Qt.AlignHCenter)
        data_group_box_layout.addWidget(name_disclaimer_label)

        ccn_group = QHBoxLayout()
        data_group_box_layout.addLayout(ccn_group)
        ccn_group.addWidget(QLabel(u"Credit Card#:", self))
        self.cc_ledit = QLineEdit(u"", self)
        self.cc_ledit.setToolTip(_(u"<p>Enter the full credit card number on record " +
                                u"in your B&N account.</p>" +
                                u"<p>No spaces or dashes... just the numbers. " +
                                u"This number will only be used to generate this " +
                                u"one-time key and won\'t be stored anywhere in " +
                                u"calibre or on your computer."))
        ccn_group.addWidget(self.cc_ledit)
        ccn_disclaimer_label = QLabel(_('(Will not be saved in configuration data)'), self)
        ccn_disclaimer_label.setAlignment(Qt.AlignHCenter)
        data_group_box_layout.addWidget(ccn_disclaimer_label)
        layout.addSpacing(10)

        self.button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        self.button_box.accepted.connect(self.accept)
        self.button_box.rejected.connect(self.reject)
        layout.addWidget(self.button_box)

        self.resize(self.sizeHint())
Example #20
0
    def __init__(self, parent, key_type_name, plugin_keys, create_key, keyfile_ext = u""):
        QDialog.__init__(self,parent)
        self.parent = parent
        self.key_type_name = key_type_name
        self.plugin_keys = plugin_keys
        self.create_key = create_key
        self.keyfile_ext = keyfile_ext
        self.import_key = (keyfile_ext != u"")
        self.binary_file = (key_type_name == u"Adobe Digital Editions Key")
        self.json_file = (key_type_name == u"Kindle for Mac and PC Key")

        self.setWindowTitle("{0} {1}: Manage {2}s".format(PLUGIN_NAME, PLUGIN_VERSION, self.key_type_name))

        # Start Qt Gui dialog layout
        layout = QVBoxLayout(self)
        self.setLayout(layout)

        help_layout = QHBoxLayout()
        layout.addLayout(help_layout)
        # Add hyperlink to a help file at the right. We will replace the correct name when it is clicked.
        help_label = QLabel('<a href="http://www.foo.com/">Help</a>', self)
        help_label.setTextInteractionFlags(Qt.LinksAccessibleByMouse | Qt.LinksAccessibleByKeyboard)
        help_label.setAlignment(Qt.AlignRight)
        help_label.linkActivated.connect(self.help_link_activated)
        help_layout.addWidget(help_label)

        keys_group_box = QGroupBox(_(u"{0}s".format(self.key_type_name)), self)
        layout.addWidget(keys_group_box)
        keys_group_box_layout = QHBoxLayout()
        keys_group_box.setLayout(keys_group_box_layout)

        self.listy = QListWidget(self)
        self.listy.setToolTip(u"{0}s that will be used to decrypt ebooks".format(self.key_type_name))
        self.listy.setSelectionMode(QAbstractItemView.SingleSelection)
        self.populate_list()
        keys_group_box_layout.addWidget(self.listy)

        button_layout = QVBoxLayout()
        keys_group_box_layout.addLayout(button_layout)
        self._add_key_button = QtGui.QToolButton(self)
        self._add_key_button.setToolTip(u"Create new {0}".format(self.key_type_name))
        self._add_key_button.setIcon(QIcon(I('plus.png')))
        self._add_key_button.clicked.connect(self.add_key)
        button_layout.addWidget(self._add_key_button)

        self._delete_key_button = QtGui.QToolButton(self)
        self._delete_key_button.setToolTip(_(u"Delete highlighted key"))
        self._delete_key_button.setIcon(QIcon(I('list_remove.png')))
        self._delete_key_button.clicked.connect(self.delete_key)
        button_layout.addWidget(self._delete_key_button)

        if type(self.plugin_keys) == dict:
            self._rename_key_button = QtGui.QToolButton(self)
            self._rename_key_button.setToolTip(_(u"Rename highlighted key"))
            self._rename_key_button.setIcon(QIcon(I('edit-select-all.png')))
            self._rename_key_button.clicked.connect(self.rename_key)
            button_layout.addWidget(self._rename_key_button)

            self.export_key_button = QtGui.QToolButton(self)
            self.export_key_button.setToolTip(u"Save highlighted key to a .{0} file".format(self.keyfile_ext))
            self.export_key_button.setIcon(QIcon(I('save.png')))
            self.export_key_button.clicked.connect(self.export_key)
            button_layout.addWidget(self.export_key_button)
        spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
        button_layout.addItem(spacerItem)

        layout.addSpacing(5)
        migrate_layout = QHBoxLayout()
        layout.addLayout(migrate_layout)
        if self.import_key:
            migrate_layout.setAlignment(Qt.AlignJustify)
            self.migrate_btn = QPushButton(u"Import Existing Keyfiles", self)
            self.migrate_btn.setToolTip(u"Import *.{0} files (created using other tools).".format(self.keyfile_ext))
            self.migrate_btn.clicked.connect(self.migrate_wrapper)
            migrate_layout.addWidget(self.migrate_btn)
        migrate_layout.addStretch()
        self.button_box = QDialogButtonBox(QDialogButtonBox.Close)
        self.button_box.rejected.connect(self.close)
        migrate_layout.addWidget(self.button_box)

        self.resize(self.sizeHint())
Example #21
0
    def setup_ui(self):
        set_no_activate_on_click = plugins['progress_indicator'][0].set_no_activate_on_click
        self.setWindowIcon(QIcon(I('spell-check.png')))
        self.l = l = QVBoxLayout(self)
        self.setLayout(l)
        self.stack = s = QStackedLayout()
        l.addLayout(s)
        l.addWidget(self.bb)
        self.bb.clear()
        self.bb.addButton(self.bb.Close)
        b = self.bb.addButton(_('&Refresh'), self.bb.ActionRole)
        b.setToolTip('<p>' + _('Re-scan the book for words, useful if you have edited the book since opening this dialog'))
        b.setIcon(QIcon(I('view-refresh.png')))
        b.clicked.connect(self.refresh)

        self.progress = p = QWidget(self)
        s.addWidget(p)
        p.l = l = QVBoxLayout(p)
        l.setAlignment(Qt.AlignCenter)
        self.progress_indicator = pi = ProgressIndicator(self, 256)
        l.addWidget(pi, alignment=Qt.AlignHCenter), l.addSpacing(10)
        p.la = la = QLabel(_('Checking, please wait...'))
        la.setStyleSheet('QLabel { font-size: 30pt; font-weight: bold }')
        l.addWidget(la, alignment=Qt.AlignHCenter)

        self.main = m = QWidget(self)
        s.addWidget(m)
        m.l = l = QVBoxLayout(m)
        m.h1 = h = QHBoxLayout()
        l.addLayout(h)
        self.filter_text = t = QLineEdit(self)
        t.setPlaceholderText(_('Filter the list of words'))
        t.textChanged.connect(self.do_filter)
        m.fc = b = QToolButton(m)
        b.setIcon(QIcon(I('clear_left.png'))), b.setToolTip(_('Clear filter'))
        b.clicked.connect(t.clear)
        h.addWidget(t), h.addWidget(b)

        m.h2 = h = QHBoxLayout()
        l.addLayout(h)
        self.words_view = w = WordsView(m)
        set_no_activate_on_click(w)
        w.ignore_all.connect(self.ignore_all)
        w.add_all.connect(self.add_all)
        w.activated.connect(self.word_activated)
        w.change_to.connect(self.change_to)
        w.currentChanged = self.current_word_changed
        state = tprefs.get('spell-check-table-state', None)
        hh = self.words_view.horizontalHeader()
        h.addWidget(w)
        self.words_model = m = WordsModel(self)
        w.setModel(m)
        m.dataChanged.connect(self.current_word_changed)
        m.modelReset.connect(self.current_word_changed)
        if state is not None:
            hh.restoreState(state)
            # Sort by the restored state, if any
            w.sortByColumn(hh.sortIndicatorSection(), hh.sortIndicatorOrder())
            m.show_only_misspelt = hh.isSectionHidden(3)

        self.ignore_button = b = QPushButton(_('&Ignore'))
        b.ign_text, b.unign_text = unicode(b.text()), _('Un&ignore')
        b.ign_tt = _('Ignore the current word for the rest of this session')
        b.unign_tt = _('Stop ignoring the current word')
        b.clicked.connect(self.toggle_ignore)
        l = QVBoxLayout()
        h.addLayout(l)
        h.setStretch(0, 1)
        l.addWidget(b), l.addSpacing(20)
        self.add_button = b = QPushButton(_('Add word to &dictionary:'))
        b.add_text, b.remove_text = unicode(b.text()), _('Remove from &dictionaries')
        b.add_tt = _('Add the current word to the specified user dictionary')
        b.remove_tt = _('Remove the current word from all active user dictionaries')
        b.clicked.connect(self.add_remove)
        self.user_dictionaries = d = QComboBox(self)
        self.user_dictionaries_missing_label = la = QLabel(_(
            'You have no active user dictionaries. You must'
            ' choose at least one active user dictionary via'
            ' Preferences->Editor->Manage spelling dictionaries'))
        la.setWordWrap(True)
        self.initialize_user_dictionaries()
        d.setMinimumContentsLength(25)
        l.addWidget(b), l.addWidget(d), l.addWidget(la)
        self.next_occurrence = b = QPushButton(_('Show &next occurrence'), self)
        b.setToolTip('<p>' + _(
            'Show the next occurrence of the selected word in the editor, so you can edit it manually'))
        b.clicked.connect(self.show_next_occurrence)
        l.addSpacing(20), l.addWidget(b)
        l.addStretch(1)

        self.change_button = b = QPushButton(_('&Change selected word to:'), self)
        b.clicked.connect(self.change_word)
        l.addWidget(b)
        self.suggested_word = sw = LineEdit(self)
        sw.set_separator(None)
        sw.setPlaceholderText(_('The replacement word'))
        sw.returnPressed.connect(self.change_word)
        l.addWidget(sw)
        self.suggested_list = sl = QListWidget(self)
        sl.currentItemChanged.connect(self.current_suggestion_changed)
        sl.itemActivated.connect(self.change_word)
        set_no_activate_on_click(sl)
        l.addWidget(sl)

        hh.setSectionHidden(3, m.show_only_misspelt)
        self.show_only_misspelled = om = QCheckBox(_('Show &only misspelled words'))
        om.setChecked(m.show_only_misspelt)
        om.stateChanged.connect(self.update_show_only_misspelt)
        self.case_sensitive_sort = cs = QCheckBox(_('Case &sensitive sort'))
        cs.setChecked(tprefs['spell_check_case_sensitive_sort'])
        cs.stateChanged.connect(self.sort_type_changed)
        self.hb = h = QHBoxLayout()
        self.summary = s = QLabel('')
        self.main.l.addLayout(h), h.addWidget(s), h.addWidget(om), h.addWidget(cs), h.addStretch(1)
Example #22
0
class MyBlockingBusy(QDialog): # {{{

    do_one_signal = pyqtSignal()

    phases = ['',
              _('Title/Author'),
              _('Standard metadata'),
              _('Custom metadata'),
              _('Search/Replace'),
    ]

    def __init__(self, msg, args, db, ids, cc_widgets, s_r_func,
                 parent=None, window_title=_('Working')):
        QDialog.__init__(self, parent)

        self._layout = QVBoxLayout()
        self.setLayout(self._layout)
        self.msg_text = msg
        self.msg = QLabel(msg+'        ') # Ensure dialog is wide enough
        #self.msg.setWordWrap(True)
        self.font = QFont()
        self.font.setPointSize(self.font.pointSize() + 8)
        self.msg.setFont(self.font)
        self.pi = ProgressIndicator(self)
        self.pi.setDisplaySize(100)
        self._layout.addWidget(self.pi, 0, Qt.AlignHCenter)
        self._layout.addSpacing(15)
        self._layout.addWidget(self.msg, 0, Qt.AlignHCenter)
        self.setWindowTitle(window_title)
        self.resize(self.sizeHint())
        self.start()

        self.args = args
        self.series_start_value = None
        self.db = db
        self.ids = ids
        self.error = None
        self.cc_widgets = cc_widgets
        self.s_r_func = s_r_func
        self.do_one_signal.connect(self.do_one_safe, Qt.QueuedConnection)

    def start(self):
        self.pi.startAnimation()

    def stop(self):
        self.pi.stopAnimation()

    def accept(self):
        self.stop()
        return QDialog.accept(self)

    def exec_(self):
        self.current_index = 0
        self.current_phase = 1
        self.do_one_signal.emit()
        return QDialog.exec_(self)

    def do_one_safe(self):
        try:
            if self.current_index >= len(self.ids):
                self.current_phase += 1
                self.current_index = 0
                if self.current_phase > 4:
                    self.db.commit()
                    return self.accept()
            id = self.ids[self.current_index]
            percent = int((self.current_index*100)/float(len(self.ids)))
            self.msg.setText(self.msg_text.format(self.phases[self.current_phase],
                                        percent))
            self.do_one(id)
        except Exception as err:
            import traceback
            try:
                err = unicode(err)
            except:
                err = repr(err)
            self.error = (err, traceback.format_exc())
            return self.accept()

    def do_one(self, id):
        remove_all, remove, add, au, aus, do_aus, rating, pub, do_series, \
            do_autonumber, do_remove_format, remove_format, do_swap_ta, \
            do_remove_conv, do_auto_author, series, do_series_restart, \
            series_start_value, do_title_case, cover_action, clear_series, \
            pubdate, adddate, do_title_sort, languages, clear_languages, \
            restore_original = self.args


        # first loop: All changes that modify the filesystem and commit
        # immediately. We want to
        # try hard to keep the DB and the file system in sync, even in the face
        # of exceptions or forced exits.
        if self.current_phase == 1:
            title_set = False
            if do_swap_ta:
                title = self.db.title(id, index_is_id=True)
                aum = self.db.authors(id, index_is_id=True)
                if aum:
                    aum = [a.strip().replace('|', ',') for a in aum.split(',')]
                    new_title = authors_to_string(aum)
                    if do_title_case:
                        new_title = titlecase(new_title)
                    self.db.set_title(id, new_title, notify=False)
                    title_set = True
                if title:
                    new_authors = string_to_authors(title)
                    self.db.set_authors(id, new_authors, notify=False)
            if do_title_case and not title_set:
                title = self.db.title(id, index_is_id=True)
                self.db.set_title(id, titlecase(title), notify=False)
            if do_title_sort:
                title = self.db.title(id, index_is_id=True)
                if languages:
                    lang = languages[0]
                else:
                    lang = self.db.languages(id, index_is_id=True)
                    if lang:
                        lang = lang.partition(',')[0]
                self.db.set_title_sort(id, title_sort(title, lang=lang),
                        notify=False)
            if au:
                self.db.set_authors(id, string_to_authors(au), notify=False)
            if cover_action == 'remove':
                self.db.remove_cover(id)
            elif cover_action == 'generate':
                from calibre.ebooks import calibre_cover
                from calibre.ebooks.metadata import fmt_sidx
                from calibre.gui2 import config
                mi = self.db.get_metadata(id, index_is_id=True)
                series_string = None
                if mi.series:
                    series_string = _('Book %(sidx)s of %(series)s')%dict(
                        sidx=fmt_sidx(mi.series_index,
                        use_roman=config['use_roman_numerals_for_series_number']),
                        series=mi.series)

                cdata = calibre_cover(mi.title, mi.format_field('authors')[-1],
                        series_string=series_string)
                self.db.set_cover(id, cdata)
            elif cover_action == 'fromfmt':
                fmts = self.db.formats(id, index_is_id=True, verify_formats=False)
                if fmts:
                    covers = []
                    for fmt in fmts.split(','):
                        fmtf = self.db.format(id, fmt, index_is_id=True,
                                as_file=True)
                        if fmtf is None: continue
                        cdata, area = get_cover_data(fmtf, fmt)
                        if cdata:
                            covers.append((cdata, area))
                    covers.sort(key=lambda x: x[1])
                    if covers:
                        self.db.set_cover(id, covers[-1][0])
                    covers = []

            if do_remove_format:
                self.db.remove_format(id, remove_format, index_is_id=True,
                        notify=False, commit=True)

            if restore_original:
                formats = self.db.formats(id, index_is_id=True)
                formats = formats.split(',') if formats else []
                originals = [x.upper() for x in formats if
                        x.upper().startswith('ORIGINAL_')]
                for ofmt in originals:
                    fmt = ofmt.replace('ORIGINAL_', '')
                    with SpooledTemporaryFile(SPOOL_SIZE) as stream:
                        self.db.copy_format_to(id, ofmt, stream,
                                index_is_id=True)
                        stream.seek(0)
                        self.db.add_format(id, fmt, stream, index_is_id=True,
                                notify=False)
                    self.db.remove_format(id, ofmt, index_is_id=True,
                            notify=False, commit=True)

        elif self.current_phase == 2:
            # All of these just affect the DB, so we can tolerate a total rollback
            if do_auto_author:
                x = self.db.author_sort_from_book(id, index_is_id=True)
                if x:
                    self.db.set_author_sort(id, x, notify=False, commit=False)

            if aus and do_aus:
                self.db.set_author_sort(id, aus, notify=False, commit=False)

            if rating != -1:
                self.db.set_rating(id, 2*rating, notify=False, commit=False)

            if pub:
                self.db.set_publisher(id, pub, notify=False, commit=False)

            if clear_series:
                self.db.set_series(id, '', notify=False, commit=False)

            if pubdate is not None:
                self.db.set_pubdate(id, pubdate, notify=False, commit=False)

            if adddate is not None:
                self.db.set_timestamp(id, adddate, notify=False, commit=False)

            if do_series:
                if do_series_restart:
                    if self.series_start_value is None:
                        self.series_start_value = series_start_value
                    next = self.series_start_value
                    self.series_start_value += 1
                else:
                    next = self.db.get_next_series_num_for(series)
                self.db.set_series(id, series, notify=False, commit=False)
                if not series:
                    self.db.set_series_index(id, 1.0, notify=False, commit=False)
                elif do_autonumber: # is True if do_series_restart is True
                    self.db.set_series_index(id, next, notify=False, commit=False)
                elif tweaks['series_index_auto_increment'] != 'no_change':
                    self.db.set_series_index(id, 1.0, notify=False, commit=False)

            if do_remove_conv:
                self.db.delete_conversion_options(id, 'PIPE', commit=False)

            if clear_languages:
                self.db.set_languages(id, [], notify=False, commit=False)
            elif languages:
                self.db.set_languages(id, languages, notify=False, commit=False)

        elif self.current_phase == 3:
            # both of these are fast enough to just do them all
            for w in self.cc_widgets:
                w.commit(self.ids)
            if remove_all:
                self.db.remove_all_tags(self.ids)
            self.db.bulk_modify_tags(self.ids, add=add, remove=remove,
                                         notify=False)
            self.current_index = len(self.ids)
        elif self.current_phase == 4:
            self.s_r_func(id)
        # do the next one
        self.current_index += 1
        self.do_one_signal.emit()
class MyBlockingBusy(QDialog):

    NORMAL = 0
    REQUESTED = 1
    ACKNOWLEDGED = 2

    def __init__(self, gui, msg, size=100, window_title="Marvin XD", show_cancel=False, on_top=False):
        flags = Qt.FramelessWindowHint
        if on_top:
            flags = Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint
        QDialog.__init__(self, gui, flags)

        self._layout = QVBoxLayout()
        self.setLayout(self._layout)
        self.cancel_status = 0
        self.is_running = False

        # Add the spinner
        self.pi = ProgressIndicator(self)
        self.pi.setDisplaySize(size)
        self._layout.addSpacing(15)
        self._layout.addWidget(self.pi, 0, Qt.AlignHCenter)
        self._layout.addSpacing(15)

        # Fiddle with the message
        self.msg = QLabel(msg)
        # self.msg.setWordWrap(True)
        self.font = QFont()
        self.font.setPointSize(self.font.pointSize() + 2)
        self.msg.setFont(self.font)
        self._layout.addWidget(self.msg, 0, Qt.AlignHCenter)
        sp = QSizePolicy()
        sp.setHorizontalStretch(True)
        sp.setVerticalStretch(False)
        sp.setHeightForWidth(False)
        self.msg.setSizePolicy(sp)
        self.msg.setMinimumHeight(self.font.pointSize() + 8)

        self._layout.addSpacing(15)

        if show_cancel:
            self.bb = QDialogButtonBox()
            self.cancel_button = QPushButton(QIcon(I("window-close.png")), "Cancel")
            self.bb.addButton(self.cancel_button, self.bb.RejectRole)
            self.bb.clicked.connect(self.button_handler)
            self._layout.addWidget(self.bb)

        self.setWindowTitle(window_title)
        self.resize(self.sizeHint())

    def accept(self):
        self.stop()
        return QDialog.accept(self)

    def button_handler(self, button):
        """
        Only change cancel_status from NORMAL to REQUESTED
        """
        if self.bb.buttonRole(button) == QDialogButtonBox.RejectRole:
            if self.cancel_status == self.NORMAL:
                self.cancel_status = self.REQUESTED
                self.cancel_button.setEnabled(False)

    def reject(self):
        """
        Cannot cancel this dialog manually
        """
        pass

    def set_text(self, text):
        self.msg.setText(text)

    def start(self):
        self.is_running = True
        self.pi.startAnimation()

    def stop(self):
        self.is_running = False
        self.pi.stopAnimation()
Example #24
0
class MyBlockingBusy(QDialog):

    NORMAL = 0
    REQUESTED = 1
    ACKNOWLEDGED = 2

    def __init__(self,
                 gui,
                 msg,
                 size=100,
                 window_title='Marvin XD',
                 show_cancel=False,
                 on_top=False):
        flags = Qt.FramelessWindowHint
        if on_top:
            flags = Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint
        QDialog.__init__(self, gui, flags)

        self._layout = QVBoxLayout()
        self.setLayout(self._layout)
        self.cancel_status = 0
        self.is_running = False

        # Add the spinner
        self.pi = ProgressIndicator(self)
        self.pi.setDisplaySize(size)
        self._layout.addSpacing(15)
        self._layout.addWidget(self.pi, 0, Qt.AlignHCenter)
        self._layout.addSpacing(15)

        # Fiddle with the message
        self.msg = QLabel(msg)
        #self.msg.setWordWrap(True)
        self.font = QFont()
        self.font.setPointSize(self.font.pointSize() + 2)
        self.msg.setFont(self.font)
        self._layout.addWidget(self.msg, 0, Qt.AlignHCenter)
        sp = QSizePolicy()
        sp.setHorizontalStretch(True)
        sp.setVerticalStretch(False)
        sp.setHeightForWidth(False)
        self.msg.setSizePolicy(sp)
        self.msg.setMinimumHeight(self.font.pointSize() + 8)

        self._layout.addSpacing(15)

        if show_cancel:
            self.bb = QDialogButtonBox()
            self.cancel_button = QPushButton(QIcon(I('window-close.png')),
                                             'Cancel')
            self.bb.addButton(self.cancel_button, self.bb.RejectRole)
            self.bb.clicked.connect(self.button_handler)
            self._layout.addWidget(self.bb)

        self.setWindowTitle(window_title)
        self.resize(self.sizeHint())

    def accept(self):
        self.stop()
        return QDialog.accept(self)

    def button_handler(self, button):
        '''
        Only change cancel_status from NORMAL to REQUESTED
        '''
        if self.bb.buttonRole(button) == QDialogButtonBox.RejectRole:
            if self.cancel_status == self.NORMAL:
                self.cancel_status = self.REQUESTED
                self.cancel_button.setEnabled(False)

    def reject(self):
        '''
        Cannot cancel this dialog manually
        '''
        pass

    def set_text(self, text):
        self.msg.setText(text)

    def start(self):
        self.is_running = True
        self.pi.startAnimation()

    def stop(self):
        self.is_running = False
        self.pi.stopAnimation()
Example #25
0
 def __init__(self, parent, modal=True, flags=Qt.WindowFlags()):
     QDialog.__init__(self, parent, flags)
     self.setModal(modal)
     self.setWindowTitle("Restore model into image")
     lo = QVBoxLayout(self)
     lo.setMargin(10)
     lo.setSpacing(5)
     # file selector
     self.wfile_in = FileSelector(self, label="Input FITS file:", dialog_label="Input FITS file",
                                  default_suffix="fits", file_types="FITS files (*.fits *.FITS)",
                                  file_mode=QFileDialog.ExistingFile)
     lo.addWidget(self.wfile_in)
     self.wfile_out = FileSelector(self, label="Output FITS file:", dialog_label="Output FITS file",
                                   default_suffix="fits", file_types="FITS files (*.fits *.FITS)",
                                   file_mode=QFileDialog.AnyFile)
     lo.addWidget(self.wfile_out)
     # beam size
     lo1 = QHBoxLayout()
     lo.addLayout(lo1)
     lo1.setContentsMargins(0, 0, 0, 0)
     lo1.addWidget(QLabel("Restoring beam FWHM, major axis:", self))
     self.wbmaj = QLineEdit(self)
     lo1.addWidget(self.wbmaj)
     lo1.addWidget(QLabel("\"     minor axis:", self))
     self.wbmin = QLineEdit(self)
     lo1.addWidget(self.wbmin)
     lo1.addWidget(QLabel("\"     P.A.:", self))
     self.wbpa = QLineEdit(self)
     lo1.addWidget(self.wbpa)
     lo1.addWidget(QLabel("\u00B0", self))
     for w in self.wbmaj, self.wbmin, self.wbpa:
         w.setValidator(QDoubleValidator(self))
     lo1 = QHBoxLayout()
     lo.addLayout(lo1)
     lo1.setContentsMargins(0, 0, 0, 0)
     self.wfile_psf = FileSelector(self, label="Set restoring beam by fitting PSF image:",
                                   dialog_label="PSF FITS file", default_suffix="fits",
                                   file_types="FITS files (*.fits *.FITS)", file_mode=QFileDialog.ExistingFile)
     lo1.addSpacing(32)
     lo1.addWidget(self.wfile_psf)
     # selection only
     self.wselonly = QCheckBox("restore selected model sources only", self)
     lo.addWidget(self.wselonly)
     # OK/cancel buttons
     lo.addSpacing(10)
     lo2 = QHBoxLayout()
     lo.addLayout(lo2)
     lo2.setContentsMargins(0, 0, 0, 0)
     lo2.setMargin(5)
     self.wokbtn = QPushButton("OK", self)
     self.wokbtn.setMinimumWidth(128)
     QObject.connect(self.wokbtn, SIGNAL("clicked()"), self.accept)
     self.wokbtn.setEnabled(False)
     cancelbtn = QPushButton("Cancel", self)
     cancelbtn.setMinimumWidth(128)
     QObject.connect(cancelbtn, SIGNAL("clicked()"), self.reject)
     lo2.addWidget(self.wokbtn)
     lo2.addStretch(1)
     lo2.addWidget(cancelbtn)
     self.setMinimumWidth(384)
     # signals
     QObject.connect(self.wfile_in, SIGNAL("filenameSelected"), self._fileSelected)
     QObject.connect(self.wfile_in, SIGNAL("filenameSelected"), self._inputFileSelected)
     QObject.connect(self.wfile_out, SIGNAL("filenameSelected"), self._fileSelected)
     QObject.connect(self.wfile_psf, SIGNAL("filenameSelected"), self._psfFileSelected)
     # internal state
     self.qerrmsg = QErrorMessage(self)
Example #26
0
 def __init__(self, parent, config_name=None, buttons=[], *args):
     """Creates dialog.
     'config_name' is used to get/set default window size from Config object
     'buttons' can be a list of names or (QPixmapWrapper,name[,tooltip]) tuples to provide
     custom buttons at the bottom of the dialog. When a button is clicked, the dialog
     emits SIGNAL("name").
     A "Close" button is always provided, this simply hides the dialog.
     """
     QDialog.__init__(self, parent, *args)
     self.setModal(False)
     lo = QVBoxLayout(self)
     # create viewer
     self.label = QLabel(self)
     self.label.setMargin(5)
     self.label.setWordWrap(True)
     lo.addWidget(self.label)
     self.label.hide()
     self.viewer = QTextBrowser(self)
     lo.addWidget(self.viewer)
     # self.viewer.setReadOnly(True)
     self.viewer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
     QObject.connect(self.viewer, SIGNAL("anchorClicked(const QUrl &)"),
                     self._urlClicked)
     self._source = None
     lo.addSpacing(5)
     # create button bar
     btnfr = QFrame(self)
     btnfr.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed)
     # btnfr.setMargin(5)
     lo.addWidget(btnfr)
     lo.addSpacing(5)
     btnfr_lo = QHBoxLayout(btnfr)
     btnfr_lo.setMargin(5)
     # add user buttons
     self._user_buttons = {}
     for name in buttons:
         if isinstance(name, str):
             btn = QPushButton(name, btnfr)
         elif isinstance(name, (list, tuple)):
             if len(name) < 3:
                 pixmap, name = name
                 tip = None
             else:
                 pixmap, name, tip = name
             btn = QPushButton(pixmap.icon(), name, btnfr)
             if tip:
                 btn.setToolTip(tip)
         self._user_buttons[name] = btn
         btn._clicked = Kittens.utils.curry(self.emit, SIGNAL(name))
         self.connect(btn, SIGNAL("clicked()"), btn._clicked)
         btnfr_lo.addWidget(btn, 1)
     # add a Close button
     btnfr_lo.addStretch(100)
     closebtn = QPushButton(pixmaps.grey_round_cross.icon(), "Close", btnfr)
     self.connect(closebtn, SIGNAL("clicked()"), self.hide)
     btnfr_lo.addWidget(closebtn, 1)
     # resize selves
     self.config_name = config_name or "html-viewer"
     width = Config.getint('%s-width' % self.config_name, 512)
     height = Config.getint('%s-height' % self.config_name, 512)
     self.resize(QSize(width, height))
Example #27
0
    def __init__(self, plugin_action):
        QWidget.__init__(self)
        self.plugin_action = plugin_action
        layout = QVBoxLayout(self)
        self.setLayout(layout)

        c = plugin_prefs[STORE_NAME]
        avail_columns = self.get_custom_columns()
        library_config = get_library_config(self.plugin_action.gui.current_db)
        pages_algorithm = library_config.get(KEY_PAGES_ALGORITHM, DEFAULT_LIBRARY_VALUES[KEY_PAGES_ALGORITHM])
        button_default = c.get(KEY_BUTTON_DEFAULT, DEFAULT_STORE_VALUES[KEY_BUTTON_DEFAULT])
        # Fudge the button default to cater for the options no longer supported by plugin as of 1.5
        if button_default in ['Estimate', 'EstimatePage', 'EstimateWord']:
            button_default = 'Estimate'
        else:
            button_default = 'Goodreads'
        overwrite_existing = c.get(KEY_OVERWRITE_EXISTING, DEFAULT_STORE_VALUES[KEY_OVERWRITE_EXISTING])

        # --- Pages ---
        page_group_box = QGroupBox('Page count options:', self)
        layout.addWidget(page_group_box)
        page_group_box_layout = QGridLayout()
        page_group_box.setLayout(page_group_box_layout)

        page_column_label = QLabel('&Custom column:', self)
        page_column_label.setToolTip('Leave this blank if you do not want to count pages')
        page_col = library_config.get(KEY_PAGES_CUSTOM_COLUMN, '')
        self.page_column_combo = CustomColumnComboBox(self, avail_columns, page_col)
        page_column_label.setBuddy(self.page_column_combo)
        page_group_box_layout.addWidget(page_column_label, 0, 0, 1, 1)
        page_group_box_layout.addWidget(self.page_column_combo, 0, 1, 1, 2)

        page_algorithm_label = QLabel('&Algorithm:', self)
        page_algorithm_label.setToolTip('Choose which algorithm to use if you have specified a page count column')
        self.page_algorithm_combo = AlgorithmComboBox(self, PAGE_ALGORITHMS, pages_algorithm)
        page_algorithm_label.setBuddy(self.page_algorithm_combo)
        page_group_box_layout.addWidget(page_algorithm_label, 1, 0, 1, 1)
        page_group_box_layout.addWidget(self.page_algorithm_combo, 1, 1, 1, 2)

        # --- Words ---
        layout.addSpacing(5)
        word_group_box = QGroupBox('Word count options:', self)
        layout.addWidget(word_group_box)
        word_group_box_layout = QGridLayout()
        word_group_box.setLayout(word_group_box_layout)

        word_column_label = QLabel('C&ustom column:', self)
        word_column_label.setToolTip('Leave this blank if you do not want to count words')
        word_col = library_config.get(KEY_WORDS_CUSTOM_COLUMN, '')
        self.word_column_combo = CustomColumnComboBox(self, avail_columns, word_col)
        word_column_label.setBuddy(self.word_column_combo)
        word_group_box_layout.addWidget(word_column_label, 0, 0, 1, 1)
        word_group_box_layout.addWidget(self.word_column_combo, 0, 1, 1, 2)

        # --- Readability ---
        layout.addSpacing(5)
        readability_group_box = QGroupBox('Readability options:', self)
        layout.addWidget(readability_group_box)
        readability_layout = QGridLayout()
        readability_group_box.setLayout(readability_layout)

        readability_label = QLabel('Readability statistics available are <a href="http://en.wikipedia.org/wiki/Flesch–Kincaid_readability_test">Flesch-Kincaid</a> '
                                   'or <a href="http://en.wikipedia.org/wiki/Gunning_fog_index">Gunning Fog Index</a>.', self)
        readability_layout.addWidget(readability_label, 0, 0, 1, 3)
        readability_label.linkActivated.connect(self._link_activated)

        flesch_reading_column_label = QLabel('&Flesch Reading Ease:', self)
        flesch_reading_column_label.setToolTip('Specify the custom column to store a computed Flesch Reading Ease score.\n'
                                     'Leave this blank if you do not want to calculate it')
        flesch_reading_col = library_config.get(KEY_FLESCH_READING_CUSTOM_COLUMN, '')
        self.flesch_reading_column_combo = CustomColumnComboBox(self, avail_columns, flesch_reading_col)
        flesch_reading_column_label.setBuddy(self.flesch_reading_column_combo)
        readability_layout.addWidget(flesch_reading_column_label, 1, 0, 1, 1)
        readability_layout.addWidget(self.flesch_reading_column_combo, 1, 1, 1, 2)

        flesch_grade_column_label = QLabel('Flesch-&Kincaid Grade:', self)
        flesch_grade_column_label.setToolTip('Specify the custom column to store a computed Flesch-Kincaid Grade Level score.\n'
                                     'Leave this blank if you do not want to calculate it')
        flesch_grade_col = library_config.get(KEY_FLESCH_GRADE_CUSTOM_COLUMN, '')
        self.flesch_grade_column_combo = CustomColumnComboBox(self, avail_columns, flesch_grade_col)
        flesch_grade_column_label.setBuddy(self.flesch_grade_column_combo)
        readability_layout.addWidget(flesch_grade_column_label, 2, 0, 1, 1)
        readability_layout.addWidget(self.flesch_grade_column_combo, 2, 1, 1, 2)

        gunning_fog_column_label = QLabel('&Gunning Fox Index:', self)
        gunning_fog_column_label.setToolTip('Specify the custom column to store a computed Gunning Fog Index score.\n'
                                     'Leave this blank if you do not want to calculate it')
        gunning_fog_col = library_config.get(KEY_GUNNING_FOG_CUSTOM_COLUMN, '')
        self.gunning_fog_column_combo = CustomColumnComboBox(self, avail_columns, gunning_fog_col)
        gunning_fog_column_label.setBuddy(self.gunning_fog_column_combo)
        readability_layout.addWidget(gunning_fog_column_label, 3, 0, 1, 1)
        readability_layout.addWidget(self.gunning_fog_column_combo, 3, 1, 1, 2)

        # --- Other options ---
        layout.addSpacing(5)
        other_group_box = QGroupBox('Other options:', self)
        layout.addWidget(other_group_box)
        other_group_box_layout = QGridLayout()
        other_group_box.setLayout(other_group_box_layout)

        button_default_label = QLabel('&Button default:', self)
        button_default_label.setToolTip('If plugin is placed as a toolbar button, choose a default action when clicked on')
        self.button_default_combo = KeyValueComboBox(self, BUTTON_DEFAULTS, button_default)
        button_default_label.setBuddy(self.button_default_combo)
        other_group_box_layout.addWidget(button_default_label, 0, 0, 1, 1)
        other_group_box_layout.addWidget(self.button_default_combo, 0, 1, 1, 2)

        self.overwrite_checkbox = QCheckBox('Always overwrite an existing word/page count', self)
        self.overwrite_checkbox.setToolTip('Uncheck this option if you have manually populated values in\n'
                                           'either of your page/word custom columns, and never want the\n'
                                           'plugin to overwrite it. Acts as a convenience option for users\n'
                                           'who have the toolbar button configured to populate both page\n'
                                           'and word count, but for some books have already assigned values\n'
                                           'into a column and just want the zero/blank column populated.')
        self.overwrite_checkbox.setChecked(overwrite_existing)
        other_group_box_layout.addWidget(self.overwrite_checkbox, 1, 0, 1, 3)

        keyboard_shortcuts_button = QPushButton('Keyboard shortcuts...', self)
        keyboard_shortcuts_button.setToolTip(_(
                    'Edit the keyboard shortcuts associated with this plugin'))
        keyboard_shortcuts_button.clicked.connect(self.edit_shortcuts)
        view_prefs_button = QPushButton('&View library preferences...', self)
        view_prefs_button.setToolTip(_(
                    'View data stored in the library database for this plugin'))
        view_prefs_button.clicked.connect(self.view_prefs)
        layout.addWidget(keyboard_shortcuts_button)
        layout.addWidget(view_prefs_button)
        layout.addStretch(1)
Example #28
0
    def __init__(self, parent, hide_on_close=False):
        QMainWindow.__init__(self, parent)
        self._hide_on_close = hide_on_close
        # replace the BusyIndicator class with a GUI-aware one
        Purr.BusyIndicator = BusyIndicator
        self._pounce = False
        # we keep a small stack of previously active purrers. This makes directory changes
        # faster (when going back and forth between dirs)
        # current purrer
        self.purrer = None
        self.purrer_stack = []
        # Purr pipes for receiving remote commands
        self.purrpipes = {}
        # init GUI
        self.setWindowTitle("PURR")
        self.setWindowIcon(pixmaps.purr_logo.icon())
        cw = QWidget(self)
        self.setCentralWidget(cw)
        cwlo = QVBoxLayout(cw)
        cwlo.setContentsMargins(0, 0, 0, 0)
        cwlo.setMargin(5)
        cwlo.setSpacing(0)
        toplo = QHBoxLayout();
        cwlo.addLayout(toplo)

        # About dialog
        self._about_dialog = QMessageBox(self)
        self._about_dialog.setWindowTitle("About PURR")
        self._about_dialog.setText(self.about_message + """
        <P>PURR is not watching any directories right now. You may need to restart it, and give it
  some directory names on the command line.</P>""")
        self._about_dialog.setIconPixmap(pixmaps.purr_logo.pm())
        # Log viewer dialog
        self.viewer_dialog = HTMLViewerDialog(self, config_name="log-viewer",
                                              buttons=[(pixmaps.blue_round_reload, "Regenerate",
                                                        """<P>Regenerates your log's HTML code from scratch. This can be useful if
                                                        your PURR version has changed, or if there was an error of some kind
                                                        the last time the files were generated.</P>
                                                        """)])
        self._viewer_timestamp = None
        self.connect(self.viewer_dialog, SIGNAL("Regenerate"), self._regenerateLog)
        self.connect(self.viewer_dialog, SIGNAL("viewPath"), self._viewPath)

        # Log title toolbar
        title_tb = QToolBar(cw)
        title_tb.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
        title_tb.setIconSize(QSize(16, 16))
        cwlo.addWidget(title_tb)
        title_label = QLabel("Purrlog title:", title_tb)
        title_tb.addWidget(title_label)
        self.title_editor = QLineEdit(title_tb)
        title_tb.addWidget(self.title_editor)
        self.connect(self.title_editor, SIGNAL("editingFinished()"), self._titleChanged)
        tip = """<P>This is your current log title. To rename the log, enter new name here and press Enter.</P>"""
        title_label.setToolTip(tip)
        self.title_editor.setToolTip(tip)
        self.wviewlog = title_tb.addAction(pixmaps.openbook.icon(), "View", self._showViewerDialog)
        self.wviewlog.setToolTip("Click to see an HTML rendering of your current log.")
        qa = title_tb.addAction(pixmaps.purr_logo.icon(), "About...", self._about_dialog.exec_)
        qa.setToolTip("<P>Click to see the About... dialog, which will tell you something about PURR.</P>")

        self.wdirframe = QFrame(cw)
        cwlo.addWidget(self.wdirframe)
        self.dirs_lo = QVBoxLayout(self.wdirframe)
        self.dirs_lo.setMargin(5)
        self.dirs_lo.setContentsMargins(5, 0, 5, 5)
        self.dirs_lo.setSpacing(0)
        self.wdirframe.setFrameStyle(QFrame.Box | QFrame.Raised)
        self.wdirframe.setLineWidth(1)

        ## Directories toolbar
        dirs_tb = QToolBar(self.wdirframe)
        dirs_tb.setToolButtonStyle(Qt.ToolButtonIconOnly)
        dirs_tb.setIconSize(QSize(16, 16))
        self.dirs_lo.addWidget(dirs_tb)
        label = QLabel("Monitoring directories:", dirs_tb)
        self._dirs_tip = """<P>PURR can monitor your working directories for new or updated files. If there's a checkmark
      next to the directory name in this list, PURR is monitoring it.</P>

      <P>If the checkmark is grey, PURR is monitoring things unobtrusively. When a new or updated file is detected in he monitored directory,
      it is quietly added to the list of files in the "New entry" window, even if this window is not currently visible.</P>

      <P>If the checkmark is black, PURR will be more obtrusive. Whenever a new or updated file is detected, the "New entry" window will
      pop up automatically. This is called "pouncing", and some people find it annoying.</P>
      """
        label.setToolTip(self._dirs_tip)
        label.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Minimum)
        dirs_tb.addWidget(label)

        # add directory list widget
        self.wdirlist = DirectoryListWidget(self.wdirframe)
        self.wdirlist.setToolTip(self._dirs_tip)
        QObject.connect(self.wdirlist, SIGNAL("directoryStateChanged"), self._changeWatchedDirState)
        self.dirs_lo.addWidget(self.wdirlist)
        # self.wdirlist.setMaximumSize(1000000,64)

        # add directory button
        add = dirs_tb.addAction(pixmaps.list_add.icon(), "Add", self._showAddDirectoryDialog)
        add.setToolTip("<P>Click to add another directory to be monitored.</P>")

        # remove directory button
        delbtn = dirs_tb.addAction(pixmaps.list_remove.icon(), "Remove", self.wdirlist.removeCurrent)
        delbtn.setEnabled(False)
        delbtn.setToolTip("<P>Click to removed the currently selected directory from the list.</P>")
        QObject.connect(self.wdirlist, SIGNAL("hasSelection"), delbtn.setEnabled)

        #    # qa = dirs_tb.addAction(pixmaps.blue_round_reload.icon(),"Rescan",self._forceRescan)
        #    # qa.setToolTip("Click to rescan the directories for any new or updated files.")
        #    self.wshownew = QCheckBox("show new files",dirs_tb)
        #    dirs_tb.addWidget(self.wshownew)
        #    self.wshownew.setCheckState(Qt.Checked)
        #    self.wshownew.setToolTip("""<P>If this is checked, the "New entry" window will pop up automatically whenever
        #  new or updated files are detected. If this is unchecked, the files will be added to the window quietly
        #        and unobtrusively; you can show the window manually by clicking on the "New entry..." button below.</P>""")
        #    self._dir_entries = {}

        cwlo.addSpacing(5)

        wlogframe = QFrame(cw)
        cwlo.addWidget(wlogframe)
        log_lo = QVBoxLayout(wlogframe)
        log_lo.setMargin(5)
        log_lo.setContentsMargins(5, 5, 5, 5)
        log_lo.setSpacing(0)
        wlogframe.setFrameStyle(QFrame.Box | QFrame.Raised)
        wlogframe.setLineWidth(1)

        # listview of log entries
        self.etw = LogEntryTree(cw)
        log_lo.addWidget(self.etw, 1)
        self.etw.header().setDefaultSectionSize(128)
        self.etw.header().setMovable(False)
        self.etw.setHeaderLabels(["date", "entry title", "comment"])
        if hasattr(QHeaderView, 'ResizeToContents'):
            self.etw.header().setResizeMode(0, QHeaderView.ResizeToContents)
        else:
            self.etw.header().setResizeMode(0, QHeaderView.Custom)
            self.etw.header().resizeSection(0, 120)
        self.etw.header().setResizeMode(1, QHeaderView.Interactive)
        self.etw.header().setResizeMode(2, QHeaderView.Stretch)
        self.etw.header().show()
        try:
            self.etw.setAllColumnsShowFocus(True)
        except AttributeError:
            pass;  # Qt 4.2+
        # self.etw.setShowToolTips(True)
        self.etw.setSortingEnabled(False)
        # self.etw.setColumnAlignment(2,Qt.AlignLeft|Qt.AlignTop)
        self.etw.setSelectionMode(QTreeWidget.ExtendedSelection)
        self.etw.setRootIsDecorated(True)
        self.connect(self.etw, SIGNAL("itemSelectionChanged()"), self._entrySelectionChanged)
        self.connect(self.etw, SIGNAL("itemActivated(QTreeWidgetItem*,int)"), self._viewEntryItem)
        self.connect(self.etw, SIGNAL("itemContextMenuRequested"), self._showItemContextMenu)
        # create popup menu for data products
        self._archived_dp_menu = menu = QMenu(self)
        self._archived_dp_menu_title = QLabel()
        self._archived_dp_menu_title.setMargin(5)
        self._archived_dp_menu_title_wa = wa = QWidgetAction(self)
        wa.setDefaultWidget(self._archived_dp_menu_title)
        menu.addAction(wa)
        menu.addSeparator()
        menu.addAction(pixmaps.editcopy.icon(), "Restore file(s) from archived copy", self._restoreItemFromArchive)
        menu.addAction(pixmaps.editpaste.icon(), "Copy pathname of archived copy to clipboard",
                       self._copyItemToClipboard)
        self._current_item = None
        # create popup menu for entries
        self._entry_menu = menu = QMenu(self)
        self._entry_menu_title = QLabel()
        self._entry_menu_title.setMargin(5)
        self._entry_menu_title_wa = wa = QWidgetAction(self)
        wa.setDefaultWidget(self._entry_menu_title)
        menu.addAction(wa)
        menu.addSeparator()
        menu.addAction(pixmaps.filefind.icon(), "View this log entry", self._viewEntryItem)
        menu.addAction(pixmaps.editdelete.icon(), "Delete this log entry", self._deleteSelectedEntries)
        # buttons at bottom
        log_lo.addSpacing(5)
        btnlo = QHBoxLayout()
        log_lo.addLayout(btnlo)
        self.wnewbtn = QPushButton(pixmaps.filenew.icon(), "New entry...", cw)
        self.wnewbtn.setToolTip("Click to add a new log entry.")
        # self.wnewbtn.setFlat(True)
        self.wnewbtn.setEnabled(False)
        btnlo.addWidget(self.wnewbtn)
        btnlo.addSpacing(5)
        self.weditbtn = QPushButton(pixmaps.filefind.icon(), "View entry...", cw)
        self.weditbtn.setToolTip("Click to view or edit the selected log entry/")
        # self.weditbtn.setFlat(True)
        self.weditbtn.setEnabled(False)
        self.connect(self.weditbtn, SIGNAL("clicked()"), self._viewEntryItem)
        btnlo.addWidget(self.weditbtn)
        btnlo.addSpacing(5)
        self.wdelbtn = QPushButton(pixmaps.editdelete.icon(), "Delete", cw)
        self.wdelbtn.setToolTip("Click to delete the selected log entry or entries.")
        # self.wdelbtn.setFlat(True)
        self.wdelbtn.setEnabled(False)
        self.connect(self.wdelbtn, SIGNAL("clicked()"), self._deleteSelectedEntries)
        btnlo.addWidget(self.wdelbtn)
        # enable status line
        self.statusBar().show()
        Purr.progressMessage = self.message
        self._prev_msg = None
        # editor dialog for new entry
        self.new_entry_dialog = Purr.Editors.NewLogEntryDialog(self)
        self.connect(self.new_entry_dialog, SIGNAL("newLogEntry"), self._newLogEntry)
        self.connect(self.new_entry_dialog, SIGNAL("filesSelected"), self._addDPFiles)
        self.connect(self.wnewbtn, SIGNAL("clicked()"), self.new_entry_dialog.show)
        self.connect(self.new_entry_dialog, SIGNAL("shown"), self._checkPounceStatus)
        # entry viewer dialog
        self.view_entry_dialog = Purr.Editors.ExistingLogEntryDialog(self)
        self.connect(self.view_entry_dialog, SIGNAL("previous()"), self._viewPrevEntry)
        self.connect(self.view_entry_dialog, SIGNAL("next()"), self._viewNextEntry)
        self.connect(self.view_entry_dialog, SIGNAL("viewPath"), self._viewPath)
        self.connect(self.view_entry_dialog, SIGNAL("filesSelected"), self._addDPFilesToOldEntry)
        self.connect(self.view_entry_dialog, SIGNAL("entryChanged"), self._entryChanged)
        # saving a data product to an older entry will automatically drop it from the
        # new entry dialog
        self.connect(self.view_entry_dialog, SIGNAL("creatingDataProduct"),
                     self.new_entry_dialog.dropDataProducts)
        # resize selves
        width = Config.getint('main-window-width', 512)
        height = Config.getint('main-window-height', 512)
        self.resize(QSize(width, height))
        # create timer for pouncing
        self._timer = QTimer(self)
        self.connect(self._timer, SIGNAL("timeout()"), self._rescan)
        # create dict mapping index.html paths to entry numbers
        self._index_paths = {}
Example #29
0
 def __init__(self, parent, modal=True, flags=Qt.WindowFlags()):
     QDialog.__init__(self, parent, flags)
     self.setModal(modal)
     self.setWindowTitle("Convert sources to FITS brick")
     lo = QVBoxLayout(self)
     lo.setMargin(10)
     lo.setSpacing(5)
     # file selector
     self.wfile = FileSelector(self,
                               label="FITS filename:",
                               dialog_label="Output FITS file",
                               default_suffix="fits",
                               file_types="FITS files (*.fits *.FITS)",
                               file_mode=QFileDialog.ExistingFile)
     lo.addWidget(self.wfile)
     # reference frequency
     lo1 = QHBoxLayout()
     lo.addLayout(lo1)
     lo1.setContentsMargins(0, 0, 0, 0)
     label = QLabel("Frequency, MHz:", self)
     lo1.addWidget(label)
     tip = """<P>If your sky model contains spectral information (such as spectral indices), then a brick may be generated
 for a specific frequency. If a frequency is not specified here, the reference frequency of the model sources will be assumed.</P>"""
     self.wfreq = QLineEdit(self)
     self.wfreq.setValidator(QDoubleValidator(self))
     label.setToolTip(tip)
     self.wfreq.setToolTip(tip)
     lo1.addWidget(self.wfreq)
     # beam gain
     lo1 = QHBoxLayout()
     lo.addLayout(lo1)
     lo1.setContentsMargins(0, 0, 0, 0)
     self.wpb_apply = QCheckBox("Apply primary beam expression:", self)
     self.wpb_apply.setChecked(True)
     lo1.addWidget(self.wpb_apply)
     tip = """<P>If this option is specified, a primary power beam gain will be applied to the sources before inserting
 them into the brick. This can be any valid Python expression making use of the variables 'r' (corresponding
 to distance from field centre, in radians) and 'fq' (corresponding to frequency.)</P>"""
     self.wpb_exp = QLineEdit(self)
     self.wpb_apply.setToolTip(tip)
     self.wpb_exp.setToolTip(tip)
     lo1.addWidget(self.wpb_exp)
     # overwrite or add mode
     lo1 = QHBoxLayout()
     lo.addLayout(lo1)
     lo1.setContentsMargins(0, 0, 0, 0)
     self.woverwrite = QRadioButton("overwrite image", self)
     self.woverwrite.setChecked(True)
     lo1.addWidget(self.woverwrite)
     self.waddinto = QRadioButton("add into image", self)
     lo1.addWidget(self.waddinto)
     # add to model
     self.wadd = QCheckBox(
         "Add resulting brick to sky model as a FITS image component", self)
     lo.addWidget(self.wadd)
     lo1 = QHBoxLayout()
     lo.addLayout(lo1)
     lo1.setContentsMargins(0, 0, 0, 0)
     self.wpad = QLineEdit(self)
     self.wpad.setValidator(QDoubleValidator(self))
     self.wpad.setText("1.1")
     lab = QLabel("...with padding factor:", self)
     lab.setToolTip(
         """<P>The padding factor determines the amount of null padding inserted around the image during
   the prediction stage. Padding alleviates the effects of tapering and detapering in the uv-brick, which can show
   up towards the edges of the image. For a factor of N, the image will be padded out to N times its original size.
   This increases memory use, so if you have no flux at the edges of the image anyway, then a pad factor of 1 is
   perfectly fine.</P>""")
     self.wpad.setToolTip(lab.toolTip())
     QObject.connect(self.wadd, SIGNAL("toggled(bool)"),
                     self.wpad.setEnabled)
     QObject.connect(self.wadd, SIGNAL("toggled(bool)"), lab.setEnabled)
     self.wpad.setEnabled(False)
     lab.setEnabled(False)
     lo1.addStretch(1)
     lo1.addWidget(lab, 0)
     lo1.addWidget(self.wpad, 1)
     self.wdel = QCheckBox(
         "Remove from the sky model sources that go into the brick", self)
     lo.addWidget(self.wdel)
     # OK/cancel buttons
     lo.addSpacing(10)
     lo2 = QHBoxLayout()
     lo.addLayout(lo2)
     lo2.setContentsMargins(0, 0, 0, 0)
     lo2.setMargin(5)
     self.wokbtn = QPushButton("OK", self)
     self.wokbtn.setMinimumWidth(128)
     QObject.connect(self.wokbtn, SIGNAL("clicked()"), self.accept)
     self.wokbtn.setEnabled(False)
     cancelbtn = QPushButton("Cancel", self)
     cancelbtn.setMinimumWidth(128)
     QObject.connect(cancelbtn, SIGNAL("clicked()"), self.reject)
     lo2.addWidget(self.wokbtn)
     lo2.addStretch(1)
     lo2.addWidget(cancelbtn)
     self.setMinimumWidth(384)
     # signals
     QObject.connect(self.wfile, SIGNAL("filenameSelected"),
                     self._fileSelected)
     # internal state
     self.qerrmsg = QErrorMessage(self)
Example #30
0
    def __init__(self,
                 parent,
                 key_type_name,
                 plugin_keys,
                 create_key,
                 keyfile_ext=u""):
        QDialog.__init__(self, parent)
        self.parent = parent
        self.key_type_name = key_type_name
        self.plugin_keys = plugin_keys
        self.create_key = create_key
        self.keyfile_ext = keyfile_ext
        self.import_key = (keyfile_ext != u"")
        self.binary_file = (key_type_name == u"Adobe Digital Editions Key")
        self.json_file = (key_type_name == u"Kindle for Mac and PC Key")

        self.setWindowTitle("{0} {1}: Manage {2}s".format(
            PLUGIN_NAME, PLUGIN_VERSION, self.key_type_name))

        # Start Qt Gui dialog layout
        layout = QVBoxLayout(self)
        self.setLayout(layout)

        help_layout = QHBoxLayout()
        layout.addLayout(help_layout)
        # Add hyperlink to a help file at the right. We will replace the correct name when it is clicked.
        help_label = QLabel('<a href="http://www.foo.com/">Help</a>', self)
        help_label.setTextInteractionFlags(Qt.LinksAccessibleByMouse
                                           | Qt.LinksAccessibleByKeyboard)
        help_label.setAlignment(Qt.AlignRight)
        help_label.linkActivated.connect(self.help_link_activated)
        help_layout.addWidget(help_label)

        keys_group_box = QGroupBox(_(u"{0}s".format(self.key_type_name)), self)
        layout.addWidget(keys_group_box)
        keys_group_box_layout = QHBoxLayout()
        keys_group_box.setLayout(keys_group_box_layout)

        self.listy = QListWidget(self)
        self.listy.setToolTip(
            u"{0}s that will be used to decrypt ebooks".format(
                self.key_type_name))
        self.listy.setSelectionMode(QAbstractItemView.SingleSelection)
        self.populate_list()
        keys_group_box_layout.addWidget(self.listy)

        button_layout = QVBoxLayout()
        keys_group_box_layout.addLayout(button_layout)
        self._add_key_button = QtGui.QToolButton(self)
        self._add_key_button.setToolTip(u"Create new {0}".format(
            self.key_type_name))
        self._add_key_button.setIcon(QIcon(I('plus.png')))
        self._add_key_button.clicked.connect(self.add_key)
        button_layout.addWidget(self._add_key_button)

        self._delete_key_button = QtGui.QToolButton(self)
        self._delete_key_button.setToolTip(_(u"Delete highlighted key"))
        self._delete_key_button.setIcon(QIcon(I('list_remove.png')))
        self._delete_key_button.clicked.connect(self.delete_key)
        button_layout.addWidget(self._delete_key_button)

        if type(self.plugin_keys) == dict:
            self._rename_key_button = QtGui.QToolButton(self)
            self._rename_key_button.setToolTip(_(u"Rename highlighted key"))
            self._rename_key_button.setIcon(QIcon(I('edit-select-all.png')))
            self._rename_key_button.clicked.connect(self.rename_key)
            button_layout.addWidget(self._rename_key_button)

            self.export_key_button = QtGui.QToolButton(self)
            self.export_key_button.setToolTip(
                u"Save highlighted key to a .{0} file".format(
                    self.keyfile_ext))
            self.export_key_button.setIcon(QIcon(I('save.png')))
            self.export_key_button.clicked.connect(self.export_key)
            button_layout.addWidget(self.export_key_button)
        spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum,
                                       QtGui.QSizePolicy.Expanding)
        button_layout.addItem(spacerItem)

        layout.addSpacing(5)
        migrate_layout = QHBoxLayout()
        layout.addLayout(migrate_layout)
        if self.import_key:
            migrate_layout.setAlignment(Qt.AlignJustify)
            self.migrate_btn = QPushButton(u"Import Existing Keyfiles", self)
            self.migrate_btn.setToolTip(
                u"Import *.{0} files (created using other tools).".format(
                    self.keyfile_ext))
            self.migrate_btn.clicked.connect(self.migrate_wrapper)
            migrate_layout.addWidget(self.migrate_btn)
        migrate_layout.addStretch()
        self.button_box = QDialogButtonBox(QDialogButtonBox.Close)
        self.button_box.rejected.connect(self.close)
        migrate_layout.addWidget(self.button_box)

        self.resize(self.sizeHint())
Example #31
0
    def __init__(
        self,
        parent=None,
    ):
        QDialog.__init__(self, parent)
        self.parent = parent
        self.setWindowTitle(u"{0} {1}: Create New Barnes & Noble Key".format(
            PLUGIN_NAME, PLUGIN_VERSION))
        layout = QVBoxLayout(self)
        self.setLayout(layout)

        data_group_box = QGroupBox(u"", self)
        layout.addWidget(data_group_box)
        data_group_box_layout = QVBoxLayout()
        data_group_box.setLayout(data_group_box_layout)

        key_group = QHBoxLayout()
        data_group_box_layout.addLayout(key_group)
        key_group.addWidget(QLabel(u"Unique Key Name:", self))
        self.key_ledit = QLineEdit("", self)
        self.key_ledit.setToolTip(
            _(u"<p>Enter an identifying name for this new key.</p>" +
              u"<p>It should be something that will help you remember " +
              u"what personal information was used to create it."))
        key_group.addWidget(self.key_ledit)
        key_label = QLabel(_(''), self)
        key_label.setAlignment(Qt.AlignHCenter)
        data_group_box_layout.addWidget(key_label)

        name_group = QHBoxLayout()
        data_group_box_layout.addLayout(name_group)
        name_group.addWidget(QLabel(u"Your Name:", self))
        self.name_ledit = QLineEdit(u"", self)
        self.name_ledit.setToolTip(
            _(u"<p>Enter your name as it appears in your B&N " +
              u"account or on your credit card.</p>" +
              u"<p>It will only be used to generate this " +
              u"one-time key and won\'t be stored anywhere " +
              u"in calibre or on your computer.</p>" +
              u"<p>(ex: Jonathan Smith)"))
        name_group.addWidget(self.name_ledit)
        name_disclaimer_label = QLabel(
            _(u"(Will not be saved in configuration data)"), self)
        name_disclaimer_label.setAlignment(Qt.AlignHCenter)
        data_group_box_layout.addWidget(name_disclaimer_label)

        ccn_group = QHBoxLayout()
        data_group_box_layout.addLayout(ccn_group)
        ccn_group.addWidget(QLabel(u"Credit Card#:", self))
        self.cc_ledit = QLineEdit(u"", self)
        self.cc_ledit.setToolTip(
            _(u"<p>Enter the full credit card number on record " +
              u"in your B&N account.</p>" +
              u"<p>No spaces or dashes... just the numbers. " +
              u"This number will only be used to generate this " +
              u"one-time key and won\'t be stored anywhere in " +
              u"calibre or on your computer."))
        ccn_group.addWidget(self.cc_ledit)
        ccn_disclaimer_label = QLabel(
            _('(Will not be saved in configuration data)'), self)
        ccn_disclaimer_label.setAlignment(Qt.AlignHCenter)
        data_group_box_layout.addWidget(ccn_disclaimer_label)
        layout.addSpacing(10)

        self.button_box = QDialogButtonBox(QDialogButtonBox.Ok
                                           | QDialogButtonBox.Cancel)
        self.button_box.accepted.connect(self.accept)
        self.button_box.rejected.connect(self.reject)
        layout.addWidget(self.button_box)

        self.resize(self.sizeHint())
Example #32
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'])
Example #33
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'])
Example #34
0
 def __init__(self, parent, modal=True, flags=Qt.WindowFlags()):
     QDialog.__init__(self, parent, flags)
     self.setModal(modal)
     self.setWindowTitle("Convert sources to FITS brick")
     lo = QVBoxLayout(self)
     lo.setMargin(10)
     lo.setSpacing(5)
     # file selector
     self.wfile = FileSelector(self, label="FITS filename:", dialog_label="Output FITS file", default_suffix="fits",
                               file_types="FITS files (*.fits *.FITS)", file_mode=QFileDialog.ExistingFile)
     lo.addWidget(self.wfile)
     # reference frequency
     lo1 = QHBoxLayout()
     lo.addLayout(lo1)
     lo1.setContentsMargins(0, 0, 0, 0)
     label = QLabel("Frequency, MHz:", self)
     lo1.addWidget(label)
     tip = """<P>If your sky model contains spectral information (such as spectral indices), then a brick may be generated
 for a specific frequency. If a frequency is not specified here, the reference frequency of the model sources will be assumed.</P>"""
     self.wfreq = QLineEdit(self)
     self.wfreq.setValidator(QDoubleValidator(self))
     label.setToolTip(tip)
     self.wfreq.setToolTip(tip)
     lo1.addWidget(self.wfreq)
     # beam gain
     lo1 = QHBoxLayout()
     lo.addLayout(lo1)
     lo1.setContentsMargins(0, 0, 0, 0)
     self.wpb_apply = QCheckBox("Apply primary beam expression:", self)
     self.wpb_apply.setChecked(True)
     lo1.addWidget(self.wpb_apply)
     tip = """<P>If this option is specified, a primary power beam gain will be applied to the sources before inserting
 them into the brick. This can be any valid Python expression making use of the variables 'r' (corresponding
 to distance from field centre, in radians) and 'fq' (corresponding to frequency.)</P>"""
     self.wpb_exp = QLineEdit(self)
     self.wpb_apply.setToolTip(tip)
     self.wpb_exp.setToolTip(tip)
     lo1.addWidget(self.wpb_exp)
     # overwrite or add mode
     lo1 = QHBoxLayout()
     lo.addLayout(lo1)
     lo1.setContentsMargins(0, 0, 0, 0)
     self.woverwrite = QRadioButton("overwrite image", self)
     self.woverwrite.setChecked(True)
     lo1.addWidget(self.woverwrite)
     self.waddinto = QRadioButton("add into image", self)
     lo1.addWidget(self.waddinto)
     # add to model
     self.wadd = QCheckBox("Add resulting brick to sky model as a FITS image component", self)
     lo.addWidget(self.wadd)
     lo1 = QHBoxLayout()
     lo.addLayout(lo1)
     lo1.setContentsMargins(0, 0, 0, 0)
     self.wpad = QLineEdit(self)
     self.wpad.setValidator(QDoubleValidator(self))
     self.wpad.setText("1.1")
     lab = QLabel("...with padding factor:", self)
     lab.setToolTip("""<P>The padding factor determines the amount of null padding inserted around the image during
   the prediction stage. Padding alleviates the effects of tapering and detapering in the uv-brick, which can show
   up towards the edges of the image. For a factor of N, the image will be padded out to N times its original size.
   This increases memory use, so if you have no flux at the edges of the image anyway, then a pad factor of 1 is
   perfectly fine.</P>""")
     self.wpad.setToolTip(lab.toolTip())
     QObject.connect(self.wadd, SIGNAL("toggled(bool)"), self.wpad.setEnabled)
     QObject.connect(self.wadd, SIGNAL("toggled(bool)"), lab.setEnabled)
     self.wpad.setEnabled(False)
     lab.setEnabled(False)
     lo1.addStretch(1)
     lo1.addWidget(lab, 0)
     lo1.addWidget(self.wpad, 1)
     self.wdel = QCheckBox("Remove from the sky model sources that go into the brick", self)
     lo.addWidget(self.wdel)
     # OK/cancel buttons
     lo.addSpacing(10)
     lo2 = QHBoxLayout()
     lo.addLayout(lo2)
     lo2.setContentsMargins(0, 0, 0, 0)
     lo2.setMargin(5)
     self.wokbtn = QPushButton("OK", self)
     self.wokbtn.setMinimumWidth(128)
     QObject.connect(self.wokbtn, SIGNAL("clicked()"), self.accept)
     self.wokbtn.setEnabled(False)
     cancelbtn = QPushButton("Cancel", self)
     cancelbtn.setMinimumWidth(128)
     QObject.connect(cancelbtn, SIGNAL("clicked()"), self.reject)
     lo2.addWidget(self.wokbtn)
     lo2.addStretch(1)
     lo2.addWidget(cancelbtn)
     self.setMinimumWidth(384)
     # signals
     QObject.connect(self.wfile, SIGNAL("filenameSelected"), self._fileSelected)
     # internal state
     self.qerrmsg = QErrorMessage(self)
Example #35
0
    def __init__(
        self,
        parent=None,
    ):
        QDialog.__init__(self, parent)
        self.parent = parent
        self.setWindowTitle(u"{0} {1}: Create New eReader Key".format(
            PLUGIN_NAME, PLUGIN_VERSION))
        layout = QVBoxLayout(self)
        self.setLayout(layout)

        data_group_box = QGroupBox(u"", self)
        layout.addWidget(data_group_box)
        data_group_box_layout = QVBoxLayout()
        data_group_box.setLayout(data_group_box_layout)

        key_group = QHBoxLayout()
        data_group_box_layout.addLayout(key_group)
        key_group.addWidget(QLabel(u"Unique Key Name:", self))
        self.key_ledit = QLineEdit("", self)
        self.key_ledit.setToolTip(
            u"<p>Enter an identifying name for this new key.\nIt should be something that will help you remember what personal information was used to create it."
        )
        key_group.addWidget(self.key_ledit)
        key_label = QLabel(_(''), self)
        key_label.setAlignment(Qt.AlignHCenter)
        data_group_box_layout.addWidget(key_label)

        name_group = QHBoxLayout()
        data_group_box_layout.addLayout(name_group)
        name_group.addWidget(QLabel(u"Your Name:", self))
        self.name_ledit = QLineEdit(u"", self)
        self.name_ledit.setToolTip(
            u"Enter the name for this eReader key, usually the name on your credit card.\nIt will only be used to generate this one-time key and won\'t be stored anywhere in calibre or on your computer.\n(ex: Mr Jonathan Q Smith)"
        )
        name_group.addWidget(self.name_ledit)
        name_disclaimer_label = QLabel(
            _(u"(Will not be saved in configuration data)"), self)
        name_disclaimer_label.setAlignment(Qt.AlignHCenter)
        data_group_box_layout.addWidget(name_disclaimer_label)

        ccn_group = QHBoxLayout()
        data_group_box_layout.addLayout(ccn_group)
        ccn_group.addWidget(QLabel(u"Credit Card#:", self))
        self.cc_ledit = QLineEdit(u"", self)
        self.cc_ledit.setToolTip(
            u"<p>Enter the last 8 digits of credit card number for this eReader key.\nThey will only be used to generate this one-time key and won\'t be stored anywhere in calibre or on your computer."
        )
        ccn_group.addWidget(self.cc_ledit)
        ccn_disclaimer_label = QLabel(
            _('(Will not be saved in configuration data)'), self)
        ccn_disclaimer_label.setAlignment(Qt.AlignHCenter)
        data_group_box_layout.addWidget(ccn_disclaimer_label)
        layout.addSpacing(10)

        self.button_box = QDialogButtonBox(QDialogButtonBox.Ok
                                           | QDialogButtonBox.Cancel)
        self.button_box.accepted.connect(self.accept)
        self.button_box.rejected.connect(self.reject)
        layout.addWidget(self.button_box)

        self.resize(self.sizeHint())
Example #36
0
    def __init__(self, parent, hide_on_close=False):
        QMainWindow.__init__(self, parent)
        self._hide_on_close = hide_on_close
        # replace the BusyIndicator class with a GUI-aware one
        Purr.BusyIndicator = BusyIndicator
        self._pounce = False
        # we keep a small stack of previously active purrers. This makes directory changes
        # faster (when going back and forth between dirs)
        # current purrer
        self.purrer = None
        self.purrer_stack = []
        # Purr pipes for receiving remote commands
        self.purrpipes = {}
        # init GUI
        self.setWindowTitle("PURR")
        self.setWindowIcon(pixmaps.purr_logo.icon())
        cw = QWidget(self)
        self.setCentralWidget(cw)
        cwlo = QVBoxLayout(cw)
        cwlo.setContentsMargins(0, 0, 0, 0)
        cwlo.setMargin(5)
        cwlo.setSpacing(0)
        toplo = QHBoxLayout()
        cwlo.addLayout(toplo)

        # About dialog
        self._about_dialog = QMessageBox(self)
        self._about_dialog.setWindowTitle("About PURR")
        self._about_dialog.setText(self.about_message + """
        <P>PURR is not watching any directories right now. You may need to restart it, and give it
  some directory names on the command line.</P>""")
        self._about_dialog.setIconPixmap(pixmaps.purr_logo.pm())
        # Log viewer dialog
        self.viewer_dialog = HTMLViewerDialog(
            self,
            config_name="log-viewer",
            buttons=
            [(pixmaps.blue_round_reload, "Regenerate",
              """<P>Regenerates your log's HTML code from scratch. This can be useful if
                                                        your PURR version has changed, or if there was an error of some kind
                                                        the last time the files were generated.</P>
                                                        """)])
        self._viewer_timestamp = None
        self.connect(self.viewer_dialog, SIGNAL("Regenerate"),
                     self._regenerateLog)
        self.connect(self.viewer_dialog, SIGNAL("viewPath"), self._viewPath)

        # Log title toolbar
        title_tb = QToolBar(cw)
        title_tb.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
        title_tb.setIconSize(QSize(16, 16))
        cwlo.addWidget(title_tb)
        title_label = QLabel("Purrlog title:", title_tb)
        title_tb.addWidget(title_label)
        self.title_editor = QLineEdit(title_tb)
        title_tb.addWidget(self.title_editor)
        self.connect(self.title_editor, SIGNAL("editingFinished()"),
                     self._titleChanged)
        tip = """<P>This is your current log title. To rename the log, enter new name here and press Enter.</P>"""
        title_label.setToolTip(tip)
        self.title_editor.setToolTip(tip)
        self.wviewlog = title_tb.addAction(pixmaps.openbook.icon(), "View",
                                           self._showViewerDialog)
        self.wviewlog.setToolTip(
            "Click to see an HTML rendering of your current log.")
        qa = title_tb.addAction(pixmaps.purr_logo.icon(), "About...",
                                self._about_dialog.exec_)
        qa.setToolTip(
            "<P>Click to see the About... dialog, which will tell you something about PURR.</P>"
        )

        self.wdirframe = QFrame(cw)
        cwlo.addWidget(self.wdirframe)
        self.dirs_lo = QVBoxLayout(self.wdirframe)
        self.dirs_lo.setMargin(5)
        self.dirs_lo.setContentsMargins(5, 0, 5, 5)
        self.dirs_lo.setSpacing(0)
        self.wdirframe.setFrameStyle(QFrame.Box | QFrame.Raised)
        self.wdirframe.setLineWidth(1)

        ## Directories toolbar
        dirs_tb = QToolBar(self.wdirframe)
        dirs_tb.setToolButtonStyle(Qt.ToolButtonIconOnly)
        dirs_tb.setIconSize(QSize(16, 16))
        self.dirs_lo.addWidget(dirs_tb)
        label = QLabel("Monitoring directories:", dirs_tb)
        self._dirs_tip = """<P>PURR can monitor your working directories for new or updated files. If there's a checkmark
      next to the directory name in this list, PURR is monitoring it.</P>

      <P>If the checkmark is grey, PURR is monitoring things unobtrusively. When a new or updated file is detected in he monitored directory,
      it is quietly added to the list of files in the "New entry" window, even if this window is not currently visible.</P>

      <P>If the checkmark is black, PURR will be more obtrusive. Whenever a new or updated file is detected, the "New entry" window will
      pop up automatically. This is called "pouncing", and some people find it annoying.</P>
      """
        label.setToolTip(self._dirs_tip)
        label.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Minimum)
        dirs_tb.addWidget(label)

        # add directory list widget
        self.wdirlist = DirectoryListWidget(self.wdirframe)
        self.wdirlist.setToolTip(self._dirs_tip)
        QObject.connect(self.wdirlist, SIGNAL("directoryStateChanged"),
                        self._changeWatchedDirState)
        self.dirs_lo.addWidget(self.wdirlist)
        # self.wdirlist.setMaximumSize(1000000,64)

        # add directory button
        add = dirs_tb.addAction(pixmaps.list_add.icon(), "Add",
                                self._showAddDirectoryDialog)
        add.setToolTip(
            "<P>Click to add another directory to be monitored.</P>")

        # remove directory button
        delbtn = dirs_tb.addAction(pixmaps.list_remove.icon(), "Remove",
                                   self.wdirlist.removeCurrent)
        delbtn.setEnabled(False)
        delbtn.setToolTip(
            "<P>Click to removed the currently selected directory from the list.</P>"
        )
        QObject.connect(self.wdirlist, SIGNAL("hasSelection"),
                        delbtn.setEnabled)

        #    # qa = dirs_tb.addAction(pixmaps.blue_round_reload.icon(),"Rescan",self._forceRescan)
        #    # qa.setToolTip("Click to rescan the directories for any new or updated files.")
        #    self.wshownew = QCheckBox("show new files",dirs_tb)
        #    dirs_tb.addWidget(self.wshownew)
        #    self.wshownew.setCheckState(Qt.Checked)
        #    self.wshownew.setToolTip("""<P>If this is checked, the "New entry" window will pop up automatically whenever
        #  new or updated files are detected. If this is unchecked, the files will be added to the window quietly
        #        and unobtrusively; you can show the window manually by clicking on the "New entry..." button below.</P>""")
        #    self._dir_entries = {}

        cwlo.addSpacing(5)

        wlogframe = QFrame(cw)
        cwlo.addWidget(wlogframe)
        log_lo = QVBoxLayout(wlogframe)
        log_lo.setMargin(5)
        log_lo.setContentsMargins(5, 5, 5, 5)
        log_lo.setSpacing(0)
        wlogframe.setFrameStyle(QFrame.Box | QFrame.Raised)
        wlogframe.setLineWidth(1)

        # listview of log entries
        self.etw = LogEntryTree(cw)
        log_lo.addWidget(self.etw, 1)
        self.etw.header().setDefaultSectionSize(128)
        self.etw.header().setMovable(False)
        self.etw.setHeaderLabels(["date", "entry title", "comment"])
        if hasattr(QHeaderView, 'ResizeToContents'):
            self.etw.header().setResizeMode(0, QHeaderView.ResizeToContents)
        else:
            self.etw.header().setResizeMode(0, QHeaderView.Custom)
            self.etw.header().resizeSection(0, 120)
        self.etw.header().setResizeMode(1, QHeaderView.Interactive)
        self.etw.header().setResizeMode(2, QHeaderView.Stretch)
        self.etw.header().show()
        try:
            self.etw.setAllColumnsShowFocus(True)
        except AttributeError:
            pass
            # Qt 4.2+
        # self.etw.setShowToolTips(True)
        self.etw.setSortingEnabled(False)
        # self.etw.setColumnAlignment(2,Qt.AlignLeft|Qt.AlignTop)
        self.etw.setSelectionMode(QTreeWidget.ExtendedSelection)
        self.etw.setRootIsDecorated(True)
        self.connect(self.etw, SIGNAL("itemSelectionChanged()"),
                     self._entrySelectionChanged)
        self.connect(self.etw, SIGNAL("itemActivated(QTreeWidgetItem*,int)"),
                     self._viewEntryItem)
        self.connect(self.etw, SIGNAL("itemContextMenuRequested"),
                     self._showItemContextMenu)
        # create popup menu for data products
        self._archived_dp_menu = menu = QMenu(self)
        self._archived_dp_menu_title = QLabel()
        self._archived_dp_menu_title.setMargin(5)
        self._archived_dp_menu_title_wa = wa = QWidgetAction(self)
        wa.setDefaultWidget(self._archived_dp_menu_title)
        menu.addAction(wa)
        menu.addSeparator()
        menu.addAction(pixmaps.editcopy.icon(),
                       "Restore file(s) from archived copy",
                       self._restoreItemFromArchive)
        menu.addAction(pixmaps.editpaste.icon(),
                       "Copy pathname of archived copy to clipboard",
                       self._copyItemToClipboard)
        self._current_item = None
        # create popup menu for entries
        self._entry_menu = menu = QMenu(self)
        self._entry_menu_title = QLabel()
        self._entry_menu_title.setMargin(5)
        self._entry_menu_title_wa = wa = QWidgetAction(self)
        wa.setDefaultWidget(self._entry_menu_title)
        menu.addAction(wa)
        menu.addSeparator()
        menu.addAction(pixmaps.filefind.icon(), "View this log entry",
                       self._viewEntryItem)
        menu.addAction(pixmaps.editdelete.icon(), "Delete this log entry",
                       self._deleteSelectedEntries)
        # buttons at bottom
        log_lo.addSpacing(5)
        btnlo = QHBoxLayout()
        log_lo.addLayout(btnlo)
        self.wnewbtn = QPushButton(pixmaps.filenew.icon(), "New entry...", cw)
        self.wnewbtn.setToolTip("Click to add a new log entry.")
        # self.wnewbtn.setFlat(True)
        self.wnewbtn.setEnabled(False)
        btnlo.addWidget(self.wnewbtn)
        btnlo.addSpacing(5)
        self.weditbtn = QPushButton(pixmaps.filefind.icon(), "View entry...",
                                    cw)
        self.weditbtn.setToolTip(
            "Click to view or edit the selected log entry/")
        # self.weditbtn.setFlat(True)
        self.weditbtn.setEnabled(False)
        self.connect(self.weditbtn, SIGNAL("clicked()"), self._viewEntryItem)
        btnlo.addWidget(self.weditbtn)
        btnlo.addSpacing(5)
        self.wdelbtn = QPushButton(pixmaps.editdelete.icon(), "Delete", cw)
        self.wdelbtn.setToolTip(
            "Click to delete the selected log entry or entries.")
        # self.wdelbtn.setFlat(True)
        self.wdelbtn.setEnabled(False)
        self.connect(self.wdelbtn, SIGNAL("clicked()"),
                     self._deleteSelectedEntries)
        btnlo.addWidget(self.wdelbtn)
        # enable status line
        self.statusBar().show()
        Purr.progressMessage = self.message
        self._prev_msg = None
        # editor dialog for new entry
        self.new_entry_dialog = Purr.Editors.NewLogEntryDialog(self)
        self.connect(self.new_entry_dialog, SIGNAL("newLogEntry"),
                     self._newLogEntry)
        self.connect(self.new_entry_dialog, SIGNAL("filesSelected"),
                     self._addDPFiles)
        self.connect(self.wnewbtn, SIGNAL("clicked()"),
                     self.new_entry_dialog.show)
        self.connect(self.new_entry_dialog, SIGNAL("shown"),
                     self._checkPounceStatus)
        # entry viewer dialog
        self.view_entry_dialog = Purr.Editors.ExistingLogEntryDialog(self)
        self.connect(self.view_entry_dialog, SIGNAL("previous()"),
                     self._viewPrevEntry)
        self.connect(self.view_entry_dialog, SIGNAL("next()"),
                     self._viewNextEntry)
        self.connect(self.view_entry_dialog, SIGNAL("viewPath"),
                     self._viewPath)
        self.connect(self.view_entry_dialog, SIGNAL("filesSelected"),
                     self._addDPFilesToOldEntry)
        self.connect(self.view_entry_dialog, SIGNAL("entryChanged"),
                     self._entryChanged)
        # saving a data product to an older entry will automatically drop it from the
        # new entry dialog
        self.connect(self.view_entry_dialog, SIGNAL("creatingDataProduct"),
                     self.new_entry_dialog.dropDataProducts)
        # resize selves
        width = Config.getint('main-window-width', 512)
        height = Config.getint('main-window-height', 512)
        self.resize(QSize(width, height))
        # create timer for pouncing
        self._timer = QTimer(self)
        self.connect(self._timer, SIGNAL("timeout()"), self._rescan)
        # create dict mapping index.html paths to entry numbers
        self._index_paths = {}