コード例 #1
0
class ProgressBar(QDialog, Logger):
    def __init__(self,
                 parent=None,
                 max_items=100,
                 window_title='Progress Bar',
                 label='Label goes here',
                 frameless=True,
                 on_top=False):
        if on_top:
            _flags = Qt.WindowStaysOnTopHint
            if frameless:
                _flags |= Qt.FramelessWindowHint
            QDialog.__init__(self, parent=parent, flags=_flags)
        else:
            _flags = Qt.Dialog
            if frameless:
                _flags |= Qt.FramelessWindowHint
            QDialog.__init__(self, parent=parent, flags=_flags)
        self.application = Application
        self.setWindowTitle(window_title)
        self.l = QVBoxLayout(self)
        self.setLayout(self.l)

        self.label = QLabel(label)
        self.label.setAlignment(Qt.AlignHCenter)
        self.l.addWidget(self.label)

        self.progressBar = QProgressBar(self)
        self.progressBar.setRange(0, max_items)
        self.progressBar.setMinimum(0)
        self.progressBar.setMaximum(0)
        self.progressBar.setValue(0)
        self.l.addWidget(self.progressBar)

        self.close_requested = False

    def closeEvent(self, event):
        self._log_location()
        self.close_requested = True

    def increment(self):
        self.progressBar.setValue(self.progressBar.value() + 1)
        self.refresh()

    def refresh(self):
        self.application.processEvents()

    def set_label(self, value):
        self.label.setText(value)
        self.label.repaint()
        self.refresh()

    def set_maximum(self, value):
        self.progressBar.setMaximum(value)
        self.refresh()

    def set_value(self, value):
        self.progressBar.setValue(value)
        self.progressBar.repaint()
        self.refresh()
コード例 #2
0
ファイル: dialogs.py プロジェクト: 12101/dedrm-ebook-tools
    def __init__(self, parent=None,):
        QDialog.__init__(self, parent)
        self.parent = parent
        self.setWindowTitle(u"{0} {1}: Add New Mobipocket PID".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"PID:", self))
        self.key_ledit = QLineEdit("", self)
        self.key_ledit.setToolTip(u"Enter a Mobipocket PID. Mobipocket PIDs are 8 or 10 characters long. Mobipocket PIDs are case-sensitive, so be sure to enter the upper and lower case letters unchanged.")
        key_group.addWidget(self.key_ledit)
        key_label = QLabel(_(''), self)
        key_label.setAlignment(Qt.AlignHCenter)
        data_group_box_layout.addWidget(key_label)

        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())
コード例 #3
0
ファイル: dialogs.py プロジェクト: startion2007/DeDRM.Net
    def __init__(
        self,
        parent=None,
    ):
        QDialog.__init__(self, parent)
        self.parent = parent
        self.setWindowTitle(u"{0} {1}: Add New Mobipocket PID".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"PID:", self))
        self.key_ledit = QLineEdit("", self)
        self.key_ledit.setToolTip(
            u"Enter a Mobipocket PID. Mobipocket PIDs are 8 or 10 characters long. Mobipocket PIDs are case-sensitive, so be sure to enter the upper and lower case letters unchanged."
        )
        key_group.addWidget(self.key_ledit)
        key_label = QLabel(_(''), self)
        key_label.setAlignment(Qt.AlignHCenter)
        data_group_box_layout.addWidget(key_label)

        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())
コード例 #4
0
ファイル: dialogs.py プロジェクト: 12101/dedrm-ebook-tools
    def __init__(self, parent=None,):
        QDialog.__init__(self, parent)
        self.parent = parent
        self.setWindowTitle(u"{0} {1}: Add New EInk Kindle Serial Number".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"EInk Kindle Serial Number:", self))
        self.key_ledit = QLineEdit("", self)
        self.key_ledit.setToolTip(u"Enter an eInk Kindle serial number. EInk Kindle serial numbers are 16 characters long and usually start with a 'B' or a '9'. Kindle Serial Numbers are case-sensitive, so be sure to enter the upper and lower case letters unchanged.")
        key_group.addWidget(self.key_ledit)
        key_label = QLabel(_(''), self)
        key_label.setAlignment(Qt.AlignHCenter)
        data_group_box_layout.addWidget(key_label)

        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())
コード例 #5
0
class BarTitle(QWidget): # {{{

    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self._layout = QHBoxLayout()
        self.setLayout(self._layout)
        self._layout.addStretch(10)
        self.icon = QLabel('')
        self._layout.addWidget(self.icon)
        self.title = QLabel('')
        self.title.setStyleSheet('QLabel { font-weight: bold }')
        self.title.setAlignment(Qt.AlignLeft | Qt.AlignCenter)
        self._layout.addWidget(self.title)
        self._layout.addStretch(10)

    def show_plugin(self, plugin):
        self.pmap = QPixmap(plugin.icon).scaled(ICON_SIZE, ICON_SIZE,
                Qt.KeepAspectRatio, Qt.SmoothTransformation)
        self.icon.setPixmap(self.pmap)
        self.title.setText(plugin.gui_name)
        tt = plugin.description
        self.setStatusTip(tt)
        tt = textwrap.fill(tt)
        self.setToolTip(tt)
        self.setWhatsThis(tt)
コード例 #6
0
class ProgressIndicator(QWidget):  # {{{

    def __init__(self, *args):
        QWidget.__init__(self, *args)
        self.setGeometry(0, 0, 300, 350)
        self.pi = _ProgressIndicator(self)
        self.status = QLabel(self)
        self.status.setWordWrap(True)
        self.status.setAlignment(Qt.AlignHCenter|Qt.AlignTop)
        self.setVisible(False)
        self.pos = None

    def start(self, msg=''):
        view = self.parent()
        pwidth, pheight = view.size().width(), view.size().height()
        self.resize(pwidth, min(pheight, 250))
        if self.pos is None:
            self.move(0, (pheight-self.size().height())/2.)
        else:
            self.move(self.pos[0], self.pos[1])
        self.pi.resize(self.pi.sizeHint())
        self.pi.move(int((self.size().width()-self.pi.size().width())/2.), 0)
        self.status.resize(self.size().width(), self.size().height()-self.pi.size().height()-10)
        self.status.move(0, self.pi.size().height()+10)
        self.status.setText('<h1>'+msg+'</h1>')
        self.setVisible(True)
        self.pi.startAnimation()

    def stop(self):
        self.pi.stopAnimation()
        self.setVisible(False)
コード例 #7
0
ファイル: Tab_page.py プロジェクト: mathlover777/OpenSoft2013
class MoviePlayer(QWidget): 
    def __init__(self, parent=None): 
        QWidget.__init__(self, parent) 
        # setGeometry(x_pos, y_pos, width, height)
        self.setGeometry(200, 200, 400, 400)
        self.setWindowTitle("QMovie to show animated gif")
        
        # set up the movie screen on a label
        self.movie_screen = QLabel()
        # expand and center the label 
        self.movie_screen.setSizePolicy(QSizePolicy.Expanding, 
            QSizePolicy.Expanding)        
        self.movie_screen.setAlignment(Qt.AlignCenter) 
        main_layout = QVBoxLayout() 
        main_layout.addWidget(self.movie_screen)
        self.setLayout(main_layout) 
                
        # use an animated gif file you have in the working folder
        # or give the full file path
        
        #self.movie.start()
    def start(self,path):
        """sart animnation"""
        self.movie = QMovie(path, QByteArray(), self) 
        self.movie.setCacheMode(QMovie.CacheAll) 
        self.movie.setSpeed(100) 
        self.movie_screen.setMovie(self.movie) 
        self.movie.start()
コード例 #8
0
    def __init__(self, process, calculation):
        """
        """
        QDialog.__init__(self, None, None, True)

        self.process = process

        self.setCaption("Please Wait")

        pbVBLayout = QVBoxLayout(self, 11, 6, "ProgressBarDialogLayout")

        msgLabel = QLabel(self, "msgLabel")
        msgLabel.setAlignment(QLabel.AlignCenter)

        if calculation == 'Energy':
            msgLabel.setText("Calculating Energy ...")
        else:
            msgLabel.setText("Optimizing ...")

        pbVBLayout.addWidget(msgLabel)

        self.msgLabel2 = QLabel(self, "msgLabel2")
        self.msgLabel2.setAlignment(QLabel.AlignCenter)
        self.msgLabel2.setText('')

        pbVBLayout.addWidget(self.msgLabel2)

        cancelButton = QPushButton(self, "canel")
        cancelButton.setText("Cancel")

        pbVBLayout.addWidget(cancelButton)

        self.resize(QSize(248, 146).expandedTo(self.minimumSizeHint()))
        self.connect(cancelButton, SIGNAL("clicked()"), self.reject)
        return
コード例 #9
0
ファイル: GamessJob.py プロジェクト: ematvey/NanoEngineer-1
    def __init__(self, process, calculation):
        """
        """
        QDialog.__init__(self, None, None, True) 
        
        self.process = process
        
        self.setCaption("Please Wait")
        
        pbVBLayout = QVBoxLayout(self,11,6,"ProgressBarDialogLayout")

        msgLabel = QLabel(self,"msgLabel")
        msgLabel.setAlignment(QLabel.AlignCenter)
        
        if calculation == 'Energy':
            msgLabel.setText("Calculating Energy ...")
        else:
            msgLabel.setText("Optimizing ...")
        
        pbVBLayout.addWidget(msgLabel)
                      
        self.msgLabel2 = QLabel(self,"msgLabel2")
        self.msgLabel2.setAlignment(QLabel.AlignCenter)
        self.msgLabel2.setText('')
        
        pbVBLayout.addWidget(self.msgLabel2)
        
        cancelButton = QPushButton(self,"canel")
        cancelButton.setText("Cancel")
        
        pbVBLayout.addWidget(cancelButton)
        
        self.resize(QSize(248,146).expandedTo(self.minimumSizeHint()))
        self.connect(cancelButton, SIGNAL("clicked()"), self.reject)
        return
コード例 #10
0
ファイル: widgets.py プロジェクト: kernsuite-debian/kittens
def addMenuLabel(menu, text):
    """Adds a QLabel contaning text to the given menu"""
    qaw = QWidgetAction(menu)
    lab = QLabel(text, menu)
    qaw.setDefaultWidget(lab)
    lab.setAlignment(Qt.AlignCenter)
    lab.setFrameShape(QFrame.StyledPanel)
    lab.setFrameShadow(QFrame.Sunken)
    menu.addAction(qaw)
    return lab
コード例 #11
0
def addMenuLabel(menu, text):
    """Adds a QLabel contaning text to the given menu"""
    qaw = QWidgetAction(menu)
    lab = QLabel(text, menu)
    qaw.setDefaultWidget(lab)
    lab.setAlignment(Qt.AlignCenter)
    lab.setFrameShape(QFrame.StyledPanel)
    lab.setFrameShadow(QFrame.Sunken)
    menu.addAction(qaw)
    return lab
コード例 #12
0
ファイル: config.py プロジェクト: 12101/dedrm-ebook-tools
    def __init__(self, parent=None,):
        QDialog.__init__(self, parent)
        self.parent = parent
        self.setWindowTitle(u"{0} {1}: Getting Default Kindle for Mac/PC Key".format(PLUGIN_NAME, PLUGIN_VERSION))
        layout = QVBoxLayout(self)
        self.setLayout(layout)

        try:
            if iswindows or isosx:
                from calibre_plugins.dedrm.kindlekey import kindlekeys

                defaultkeys = kindlekeys()
            else: # linux
                from wineutils import WineGetKeys

                scriptpath = os.path.join(parent.parent.alfdir,u"kindlekey.py")
                defaultkeys = WineGetKeys(scriptpath, u".k4i",parent.getwineprefix())

            self.default_key = defaultkeys[0]
        except:
            traceback.print_exc()
            self.default_key = u""

        self.button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)

        if len(self.default_key)>0:
            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(u"default_key", self)
            self.key_ledit.setToolTip(u"<p>Enter an identifying name for the current default Kindle for Mac/PC key.")
            key_group.addWidget(self.key_ledit)
            key_label = QLabel(_(''), self)
            key_label.setAlignment(Qt.AlignHCenter)
            data_group_box_layout.addWidget(key_label)
            self.button_box.accepted.connect(self.accept)
        else:
            default_key_error = QLabel(u"The default encryption key for Kindle for Mac/PC could not be found.", self)
            default_key_error.setAlignment(Qt.AlignHCenter)
            layout.addWidget(default_key_error)
            # if no default, bot buttons do the same
            self.button_box.accepted.connect(self.reject)

        self.button_box.rejected.connect(self.reject)
        layout.addWidget(self.button_box)

        self.resize(self.sizeHint())
コード例 #13
0
ファイル: dialogs.py プロジェクト: startion2007/DeDRM.Net
    def __init__(
        self,
        parent=None,
    ):
        QDialog.__init__(self, parent)
        self.parent = parent
        self.setWindowTitle(
            u"{0} {1}: Getting Default Kindle for Mac/PC Key".format(
                PLUGIN_NAME, PLUGIN_VERSION))
        layout = QVBoxLayout(self)
        self.setLayout(layout)

        try:
            self.default_key = retrieve_kindle_keys()[0]
        except:
            self.default_key = u""

        self.button_box = QDialogButtonBox(QDialogButtonBox.Ok
                                           | QDialogButtonBox.Cancel)

        if len(self.default_key) > 0:
            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 the current default Kindle for Mac/PC key."
            )
            key_group.addWidget(self.key_ledit)
            key_label = QLabel(_(''), self)
            key_label.setAlignment(Qt.AlignHCenter)
            data_group_box_layout.addWidget(key_label)
            self.button_box.accepted.connect(self.accept)
        else:
            default_key_error = QLabel(
                u"The default encryption key for Kindle for Mac/PC could not be found.",
                self)
            default_key_error.setAlignment(Qt.AlignHCenter)
            layout.addWidget(default_key_error)
            # if no default, bot buttons do the same
            self.button_box.accepted.connect(self.reject)

        self.button_box.rejected.connect(self.reject)
        layout.addWidget(self.button_box)

        self.resize(self.sizeHint())
コード例 #14
0
ファイル: dialogs.py プロジェクト: 12101/dedrm-ebook-tools
    def __init__(self, parent=None,):
        QDialog.__init__(self, parent)
        self.parent = parent
        self.setWindowTitle(u"{0} {1}: Getting Default Kindle for Mac/PC Key".format(PLUGIN_NAME, PLUGIN_VERSION))
        layout = QVBoxLayout(self)
        self.setLayout(layout)

        try:
            self.default_key = retrieve_kindle_keys()[0]
        except:
            self.default_key = u""

        self.button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)

        if len(self.default_key)>0:
            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 the current default Kindle for Mac/PC key.")
            key_group.addWidget(self.key_ledit)
            key_label = QLabel(_(''), self)
            key_label.setAlignment(Qt.AlignHCenter)
            data_group_box_layout.addWidget(key_label)
            self.button_box.accepted.connect(self.accept)
        else:
            default_key_error = QLabel(u"The default encryption key for Kindle for Mac/PC could not be found.", self)
            default_key_error.setAlignment(Qt.AlignHCenter)
            layout.addWidget(default_key_error)
            # if no default, bot buttons do the same
            self.button_box.accepted.connect(self.reject)

        self.button_box.rejected.connect(self.reject)
        layout.addWidget(self.button_box)

        self.resize(self.sizeHint())
コード例 #15
0
ファイル: dialogs.py プロジェクト: startion2007/DeDRM.Net
    def __init__(
        self,
        parent=None,
    ):
        QDialog.__init__(self, parent)
        self.parent = parent
        self.setWindowTitle(
            u"{0} {1}: Add New EInk Kindle Serial Number".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"EInk Kindle Serial Number:", self))
        self.key_ledit = QLineEdit("", self)
        self.key_ledit.setToolTip(
            u"Enter an eInk Kindle serial number. EInk Kindle serial numbers are 16 characters long and usually start with a 'B' or a '9'. Kindle Serial Numbers are case-sensitive, so be sure to enter the upper and lower case letters unchanged."
        )
        key_group.addWidget(self.key_ledit)
        key_label = QLabel(_(''), self)
        key_label.setAlignment(Qt.AlignHCenter)
        data_group_box_layout.addWidget(key_label)

        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())
コード例 #16
0
ファイル: dialogs.py プロジェクト: 12101/dedrm-ebook-tools
    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())
コード例 #17
0
ファイル: controller.py プロジェクト: chester5009/finder
 def addToTable(self, isfound, header, tab):
     rowPosition = tab.rowCount()
     tab.insertRow(rowPosition)
     item1 = QTableWidgetItem()
     # item1.setBackground(QtGui.QColor(144, 16, 65))
     lb = QLabel()
     lb.setAlignment(QtCore.Qt.AlignCenter)
     lb.setPixmap(self.picClose)
     
     lb2 = QLabel()
     # lb2.setAlignment(QtCore.Qt.AlignCenter)
    
     lb2.setText(header.decode("cp1251"))
     
     lb3 = QLabel()
     lb3.setAlignment(QtCore.Qt.AlignCenter)
     lb3.setPixmap(self.picSetting)
     
     lb4 = QLabel()
     lb4.setAlignment(QtCore.Qt.AlignCenter)
     if isfound == True :
         lb4.setPixmap(self.picGood)
     else:
         lb4.setPixmap(self.picBad)
         
     
    
     # tab.setItem(0, 0, item1)
     tab.setCellWidget(tab.rowCount() - 1, 0, lb)
     tab.setCellWidget(tab.rowCount() - 1, 1, lb2)
     tab.setCellWidget(tab.rowCount() - 1, 2, lb3)
     tab.setCellWidget(tab.rowCount() - 1, 3, lb4)
     # tab.resizeColumnsToContents()
     tab.setColumnWidth(0, 50)
     tab.setColumnWidth(1, 100)
     tab.setColumnWidth(2, 50)
     tab.setColumnWidth(3, 80)
     tab.setRowHeight(tab.rowCount() - 1, 70)
     pass
コード例 #18
0
ファイル: dialogs.py プロジェクト: startion2007/DeDRM.Net
    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())
コード例 #19
0
ファイル: AboutDialog.py プロジェクト: ska-sa/tigger
class AboutDialog(QDialog):
    def __init__(self, parent=None, name=None, modal=0, fl=None):
        if fl is None:
            fl = Qt.Dialog | Qt.WindowTitleHint
        QDialog.__init__(self, parent, Qt.Dialog | Qt.WindowTitleHint)
        self.setModal(modal)

        image0 = pixmaps.tigger_logo.pm()

        # self.setSizeGripEnabled(0)
        LayoutWidget = QWidget(self)
        LayoutWidget.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)

        lo_top = QVBoxLayout(LayoutWidget)

        lo_title = QHBoxLayout(None)

        self.title_icon = QLabel(LayoutWidget)
        self.title_icon.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        self.title_icon.setPixmap(image0)
        self.title_icon.setAlignment(Qt.AlignCenter)
        lo_title.addWidget(self.title_icon)

        self.title_label = QLabel(LayoutWidget)
        self.title_label.setWordWrap(True)
        lo_title.addWidget(self.title_label)
        lo_top.addLayout(lo_title)

        lo_logos = QHBoxLayout(None)
        lo_top.addLayout(lo_logos)
        # for logo in ("astron",):
        #   icon = QLabel(LayoutWidget)
        #   icon.setSizePolicy(QSizePolicy.Fixed,QSizePolicy.Fixed)
        #   icon.setPixmap(getattr(pixmaps,logo+"_logo").pm())
        #   icon.setAlignment(Qt.AlignCenter)
        #   lo_logos.addWidget(icon)

        lo_mainbtn = QHBoxLayout(None)
        lo_mainbtn.addItem(QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum))
        lo_top.addLayout(lo_mainbtn)

        self.btn_ok = QPushButton(LayoutWidget)
        self.btn_ok.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        self.btn_ok.setMinimumSize(QSize(60, 0))
        self.btn_ok.setAutoDefault(1)
        self.btn_ok.setDefault(1)
        lo_mainbtn.addWidget(self.btn_ok)
        lo_mainbtn.addItem(QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum))

        self.languageChange()

        LayoutWidget.adjustSize()

        # LayoutWidget.resize(QSize(489,330).expandedTo(LayoutWidget.minimumSizeHint()))
        # self.resize(QSize(489,330).expandedTo(self.minimumSizeHint()))
        # self.clearWState(Qt.WState_Polished)

        self.connect(self.btn_ok, SIGNAL("clicked()"), self.accept)

    def languageChange(self):
        self.setWindowTitle(self.__tr("About Tigger"))
        self.title_label.setText(self.__tr( \
            """<h3>Tigger %s</h3>
            <p>(C) 2010-2017 Oleg Smirnov & Rhodes University & SKA SA<br>
            <br>Please direct feedback and bug reports at https://github.com/ska-sa/tigger</p>
            """ % (release_string) \
            ))

        self.btn_ok.setText(self.__tr("&OK"))

    def __tr(self, s, c=None):
        return qApp.translate("About", s, c)
コード例 #20
0
    def __init__(self, parent = None, desc = None, name = None, modal = 0, fl = 0, env = None, type = "QDialog"):
        if env is None:
            import foundation.env as env # this is a little weird... probably it'll be ok, and logically it seems correct.
        
        self.desc = desc

        self.typ = type
        if type == "QDialog":
            QDialog.__init__(self,parent,name,modal,fl)
        elif type == "QTextEdit":
            QTextEdit.__init__(self, parent, name)
        elif type == "QFrame":
            QFrame.__init__(self,parent,name)
        else:
            print "don't know about type == %r" % (type,)
        
        self.image1 = QPixmap()
        self.image1.loadFromData(image1_data,"PNG") # should be: title_icon ####
        self.image3 = QPixmap()
        self.image3.loadFromData(image3_data,"PNG")
        self.image4 = QPixmap()
        self.image4.loadFromData(image4_data,"PNG")
        self.image5 = QPixmap()
        self.image5.loadFromData(image5_data,"PNG")
        self.image6 = QPixmap()
        self.image6.loadFromData(image6_data,"PNG")
        self.image7 = QPixmap()
        self.image7.loadFromData(image7_data,"PNG")
        self.image0 = QPixmap(image0_data) # should be: border_icon ####
        self.image2 = QPixmap(image2_data) # should be: sponsor_pixmap ####

        try:
            ####@@@@
            title_icon_name = self.desc.options.get('title_icon')
            border_icon_name = self.desc.options.get('border_icon')
            if title_icon_name:
                self.image1 = imagename_to_pixmap(title_icon_name) ###@@@ pass icon_path
                    ###@@@ import imagename_to_pixmap or use env function
                    # or let that func itself be an arg, or have an env arg for it
                    ###e rename it icon_name_to_pixmap, or find_icon? (the latter only if it's ok if it returns an iconset)
                    ###e use iconset instead?
            if border_icon_name:
                self.image0 = imagename_to_pixmap(border_icon_name)
        except:
            print_compact_traceback("bug in icon-setting code, using fallback icons: ")
            pass

        if not name:
            self.setName("parameter_dialog_or_frame") ###

        ###k guess this will need: if type == 'QDialog'
        self.setIcon(self.image0) # should be: border_icon ####

        nanotube_dialogLayout = QVBoxLayout(self,0,0,"nanotube_dialogLayout")

        self.heading_frame = QFrame(self,"heading_frame")
        self.heading_frame.setPaletteBackgroundColor(QColor(122,122,122))
        self.heading_frame.setFrameShape(QFrame.NoFrame)
        self.heading_frame.setFrameShadow(QFrame.Plain)
        heading_frameLayout = QHBoxLayout(self.heading_frame,0,3,"heading_frameLayout")

        self.heading_pixmap = QLabel(self.heading_frame,"heading_pixmap")
        self.heading_pixmap.setSizePolicy(QSizePolicy(QSizePolicy.Fixed,QSizePolicy.Fixed,0,0,self.heading_pixmap.sizePolicy().hasHeightForWidth()))
        self.heading_pixmap.setPixmap(self.image1) # should be: title_icon ####
        self.heading_pixmap.setScaledContents(1)
        heading_frameLayout.addWidget(self.heading_pixmap)

        self.heading_label = QLabel(self.heading_frame,"heading_label")
        self.heading_label.setPaletteForegroundColor(QColor(255,255,255))
        heading_label_font = QFont(self.heading_label.font())
        heading_label_font.setPointSize(12)
        heading_label_font.setBold(1)
        self.heading_label.setFont(heading_label_font)
        heading_frameLayout.addWidget(self.heading_label)
        nanotube_dialogLayout.addWidget(self.heading_frame)

        self.body_frame = QFrame(self,"body_frame")
        self.body_frame.setFrameShape(QFrame.StyledPanel)
        self.body_frame.setFrameShadow(QFrame.Raised)
        body_frameLayout = QVBoxLayout(self.body_frame,3,3,"body_frameLayout")

        self.sponsor_frame = QFrame(self.body_frame,"sponsor_frame")
        self.sponsor_frame.setPaletteBackgroundColor(QColor(255,255,255))
        self.sponsor_frame.setFrameShape(QFrame.StyledPanel)
        self.sponsor_frame.setFrameShadow(QFrame.Raised)
        sponsor_frameLayout = QHBoxLayout(self.sponsor_frame,0,0,"sponsor_frameLayout")

        self.sponsor_btn = QPushButton(self.sponsor_frame,"sponsor_btn")
        self.sponsor_btn.setAutoDefault(0) #bruce 060703 bugfix
        self.sponsor_btn.setSizePolicy(QSizePolicy(QSizePolicy.Preferred,QSizePolicy.Preferred,0,0,self.sponsor_btn.sizePolicy().hasHeightForWidth()))
        self.sponsor_btn.setPaletteBackgroundColor(QColor(255,255,255))
        self.sponsor_btn.setPixmap(self.image2) # should be: sponsor_pixmap #### [also we'll need to support >1 sponsor]
        self.sponsor_btn.setFlat(1)
        sponsor_frameLayout.addWidget(self.sponsor_btn)
        body_frameLayout.addWidget(self.sponsor_frame)

        layout59 = QHBoxLayout(None,0,6,"layout59")
        left_spacer = QSpacerItem(20,20,QSizePolicy.Expanding,QSizePolicy.Minimum)
        layout59.addItem(left_spacer)

        self.done_btn = QToolButton(self.body_frame,"done_btn")
        self.done_btn.setIcon(QIcon(self.image3))
        layout59.addWidget(self.done_btn)

        self.abort_btn = QToolButton(self.body_frame,"abort_btn")
        self.abort_btn.setIcon(QIcon(self.image4))
        layout59.addWidget(self.abort_btn)

        self.preview_btn = QToolButton(self.body_frame,"preview_btn")
        self.preview_btn.setIcon(QIcon(self.image5))
        layout59.addWidget(self.preview_btn)

        self.whatsthis_btn = QToolButton(self.body_frame,"whatsthis_btn")
        self.whatsthis_btn.setIcon(QIcon(self.image6))
        layout59.addWidget(self.whatsthis_btn)
        right_spacer = QSpacerItem(20,20,QSizePolicy.Expanding,QSizePolicy.Minimum)
        layout59.addItem(right_spacer)
        body_frameLayout.addLayout(layout59)

        self.groups = []
        self.param_getters = {} # map from param name to get-function (which gets current value out of its widget or controller)

        for group_desc in self.desc.kids('group'):
            
            # == start parameters_grpbox ### this will differ for Windows style

            header_refs = [] # keep python refcounted refs to all objects we make (at least the ones pyuic stored in self attrs)
            
            self.parameters_grpbox = QGroupBox(self.body_frame,"parameters_grpbox")
            self.parameters_grpbox.setFrameShape(QGroupBox.StyledPanel)
            self.parameters_grpbox.setFrameShadow(QGroupBox.Sunken)
            self.parameters_grpbox.setMargin(0)
            self.parameters_grpbox.setColumnLayout(0,Qt.Vertical)
            self.parameters_grpbox.layout().setSpacing(1)
            self.parameters_grpbox.layout().setMargin(4)
            parameters_grpboxLayout = QVBoxLayout(self.parameters_grpbox.layout())
            parameters_grpboxLayout.setAlignment(Qt.AlignTop)

            layout20 = QHBoxLayout(None,0,6,"layout20")

            self.nt_parameters_grpbtn = QPushButton(self.parameters_grpbox,"nt_parameters_grpbtn")
            self.nt_parameters_grpbtn.setSizePolicy(QSizePolicy(QSizePolicy.Minimum,QSizePolicy.Fixed,0,0,self.nt_parameters_grpbtn.sizePolicy().hasHeightForWidth()))
            self.nt_parameters_grpbtn.setMaximumSize(QSize(16,16))
            self.nt_parameters_grpbtn.setAutoDefault(0)
            self.nt_parameters_grpbtn.setIcon(QIcon(self.image7)) ### not always right, but doesn't matter
            self.nt_parameters_grpbtn.setFlat(1)
            layout20.addWidget(self.nt_parameters_grpbtn)

            self.parameters_grpbox_label = QLabel(self.parameters_grpbox,"parameters_grpbox_label")
            self.parameters_grpbox_label.setSizePolicy(QSizePolicy(QSizePolicy.Preferred,QSizePolicy.Minimum,0,0,self.parameters_grpbox_label.sizePolicy().hasHeightForWidth()))
            self.parameters_grpbox_label.setAlignment(QLabel.AlignVCenter)
            layout20.addWidget(self.parameters_grpbox_label)
            gbx_spacer1 = QSpacerItem(67,16,QSizePolicy.Expanding,QSizePolicy.Minimum)
            layout20.addItem(gbx_spacer1)
            parameters_grpboxLayout.addLayout(layout20)

            nt_parameters_body_layout = QGridLayout(None,1,1,0,6,"nt_parameters_body_layout") ### what is 6 -- is it related to number of items???
                # is it 6 in all the ones we got, but that could be a designer error so i better look it up sometime.

            # == start its kids

            # will use from above: self.parameters_grpbox, nt_parameters_body_layout
            
            nextrow = 0 # which row of the QGridLayout to start filling next (loop variable)
            hidethese = [] # set of objects to hide or show, when this group is closed or opened
            
            for param in group_desc.kids('parameter'):
                # param (a group subobj desc) is always a parameter, but we already plan to extend this beyond that,
                # so we redundantly test for this here.
                getter = None
                paramname = None
                # set these for use by uniform code at the end (e.g. for tooltips)
                editfield = None
                label = None
                if param.isa('parameter'):
                    label = QLabel(self.parameters_grpbox,"members_label")
                    label.setAlignment(QLabel.AlignVCenter | QLabel.AlignRight)
                    nt_parameters_body_layout.addWidget(label,nextrow,0)
                    hidethese.append(label)
                    thisrow = nextrow
                    nextrow += 1
                    #e following should be known in a place that knows the input language, not here
                    paramname = param.options.get('name') or (param.args and param.args[0]) or "?"
                    paramlabel = param.options.get('label') or paramname ##e wrong, label "" or none ought to be possible
                    # QtGui.QApplication.translate(self.__class__.__name__, "xyz")
                    label.setText(QtGui.QApplication.translate(self.__class__.__name__, paramlabel))
                    
                if param.isa('parameter', widget = 'combobox', type = ('str',None)):
                    self.members_combox = QComboBox(0,self.parameters_grpbox,"members_combox") ###k  what's 0?
                    editfield = self.members_combox
                    #### it probably needs a handler class, and then that could do this setup
                    self.members_combox.clear()
                    default = param.options.get('default', None) # None is not equal to any string
                    thewidgetkid = param.kids('widget')[-1] # kluge; need to think what the desc method for this should be
                    for item in thewidgetkid.kids('item'):
                        itemval = item.args[0]
                        itemtext = itemval
                        self.members_combox.insertItem(QtGui.QApplication.translate(self.__class__.__name__, itemtext)) #k __tr ok??
                        if itemval == default: #k or itemtext?
                            pass ##k i find no setItem in our py code, so not sure yet what to do for this.
                    nt_parameters_body_layout.addWidget(self.members_combox,thisrow,1)
                    hidethese.append(self.members_combox)
                    getter = (lambda combobox = self.members_combox: str(combobox.currentText()))
                        ##e due to __tr or non-str values, it might be better to use currentIndex and look it up in a table
                        # (though whether __tr is good here might depend on what it's used for)
                                    
                elif param.isa('parameter', widget = ('lineedit', None), type = ('str',None)):
                    # this covers explicit str|lineedit, and 3 default cases str, lineedit, neither.
                    # (i.e. if you say parameter and nothing else, it's str lineedit by default.)
                    self.length_linedit = QLineEdit(self.parameters_grpbox,"length_linedit")
                    editfield = self.length_linedit
                    nt_parameters_body_layout.addWidget(self.length_linedit,thisrow,1)
                    hidethese.append(self.length_linedit)
                    default = str(param.options.get('default', ""))
                    self.length_linedit.setText(QtGui.QApplication.translate(self.__class__.__name__, default)) # __tr ok?
                    getter = (lambda lineedit = self.length_linedit: str(lineedit.text()))
                    
                elif param.isa('parameter', widget = ('lineedit', None), type = 'float'):
                    self.length_linedit = QLineEdit(self.parameters_grpbox,"length_linedit")
                    editfield = self.length_linedit
                    nt_parameters_body_layout.addWidget(self.length_linedit,thisrow,1)
                    hidethese.append(self.length_linedit)
                    controller = FloatLineeditController_Qt(self, param, self.length_linedit)
                    header_refs.append(controller)
                    getter = controller.get_value
                    
                elif param.isa('parameter', widget = ('spinbox', None), type = 'int') or \
                     param.isa('parameter', widget = ('spinbox'), type = None):
                    self.chirality_N_spinbox = QSpinBox(self.parameters_grpbox,"chirality_N_spinbox") # was chirality_m_spinbox, now chirality_N_spinbox
                    editfield = self.chirality_N_spinbox
                    ### seems like Qt defaults for min and max are 0,100 -- way too small a range!
                    if param.options.has_key('min') or 1:
                        self.chirality_N_spinbox.setMinimum(param.options.get('min', -999999999)) # was 0
                    if param.options.has_key('max') or 1:
                        self.chirality_N_spinbox.setMaximum(param.options.get('max', +999999999)) # wasn't in egcode, but needed
                    self.chirality_N_spinbox.setValue(param.options.get('default', 0)) # was 5
                        ##e note: i suspect this default 0 should come from something that knows this desc grammar.
                    suffix = param.options.get('suffix', '')
                    if suffix:
                        self.chirality_N_spinbox.setSuffix(QtGui.QApplication.translate(self.__class__.__name__, suffix))
                    else:
                        self.chirality_N_spinbox.setSuffix(QString.null) # probably not needed
                    nt_parameters_body_layout.addWidget(self.chirality_N_spinbox,thisrow,1)
                    hidethese.append(self.chirality_N_spinbox)
                    getter = self.chirality_N_spinbox.value # note: it also has .text, which includes suffix
                    
                else:
                    print "didn't match:",param ###e improve this

                # things done the same way for all kinds of param-editing widgets
                if 1: #bruce 060703 moved this down here, as bugfix
                    # set tooltip (same one for editfield and label)
                    tooltip = param.options.get('tooltip', '')
                    ###e do it for more kinds of params; share the code somehow; do it in controller, or setup-aid?
                    ###k QToolTip appropriateness; tooltip option might be entirely untested
                    if tooltip and label:
                        QToolTip.add(label, QtGui.QApplication.translate(self.__class__.__name__, tooltip))
                    if tooltip and editfield:
                        QToolTip.add(editfield, QtGui.QApplication.translate(self.__class__.__name__, tooltip)) ##k ok?? review once not all params have same-row labels.
                
                if getter and paramname and paramname != '?':
                    self.param_getters[paramname] = getter
                ### also bind these params to actions...
                continue # next param

            header_refs.extend( [self.parameters_grpbox, self.nt_parameters_grpbtn, self.parameters_grpbox_label] )
            
            # now create the logic/control object for the group
            group = CollapsibleGroupController_Qt(self, group_desc, header_refs, hidethese, self.nt_parameters_grpbtn)
                ### maybe ask env for the class to use for this?
            self.groups.append(group) ### needed?? only for scanning the params, AFAIK -- oh, and to maintain a python refcount.

            # from languageChange:
            if 1: # i don't know if these are needed:
                self.parameters_grpbox.setTitle(QString.null)
                self.nt_parameters_grpbtn.setText(QString.null)
            self.parameters_grpbox_label.setText(QtGui.QApplication.translate(self.__class__.__name__, group_desc.args[0])) # was "Nanotube Parameters"
                ##e note that it's questionable in the syntax design for this property of a group (overall group label)
                # to be in that position (desc arg 0).
        
            # == end its kids
            
            parameters_grpboxLayout.addLayout(nt_parameters_body_layout)
            body_frameLayout.addWidget(self.parameters_grpbox)

            # == end parameters groupbox
            
            continue # next group

        nanotube_dialogLayout.addWidget(self.body_frame)
        spacer14 = QSpacerItem(20,20,QSizePolicy.Minimum,QSizePolicy.Expanding)
        nanotube_dialogLayout.addItem(spacer14)

        layout42 = QHBoxLayout(None,4,6,"layout42")
        btm_spacer = QSpacerItem(59,20,QSizePolicy.Expanding,QSizePolicy.Minimum)
        layout42.addItem(btm_spacer)

        self.cancel_btn = QPushButton(self,"cancel_btn")
        self.cancel_btn.setAutoDefault(0) #bruce 060703 bugfix
        layout42.addWidget(self.cancel_btn)

        self.ok_btn = QPushButton(self,"ok_btn")
        self.ok_btn.setAutoDefault(0) #bruce 060703 bugfix
        layout42.addWidget(self.ok_btn)
        nanotube_dialogLayout.addLayout(layout42)

        self.languageChange()

        self.resize(QSize(246,618).expandedTo(self.minimumSizeHint())) ### this size will need to be adjusted (guess -- it's only place overall size is set)
        qt4todo('self.clearWState(Qt.WState_Polished)')

        ## self.connect(self.nt_parameters_grpbtn,SIGNAL("clicked()"),self.toggle_nt_parameters_grpbtn) ####

        # new:
        for button, methodname in ((self.sponsor_btn, 'do_sponsor_btn'),  #e generalize to more than one sponsor button
                                   (self.done_btn, 'do_done_btn'),
                                   (self.abort_btn, 'do_abort_btn'),
                                   (self.preview_btn, 'do_preview_btn'),
                                   (self.whatsthis_btn, 'do_whatsthis_btn'),
                                   (self.cancel_btn, 'do_cancel_btn'),
                                   (self.ok_btn, 'do_ok_btn')):
            if hasattr(self, methodname):
                self.connect(button, SIGNAL("clicked()"), getattr(self, methodname))
        return
コード例 #21
0
    def __init__(
        self,
        parent=None,
    ):
        QDialog.__init__(self, parent)
        self.parent = parent
        self.setWindowTitle(
            u"{0} {1}: Getting Default Kindle for Mac/PC Key".format(
                PLUGIN_NAME, PLUGIN_VERSION))
        layout = QVBoxLayout(self)
        self.setLayout(layout)

        try:
            if iswindows or isosx:
                from calibre_plugins.dedrm.kindlekey import kindlekeys

                defaultkeys = kindlekeys()
            else:  # linux
                from wineutils import WineGetKeys

                scriptpath = os.path.join(parent.parent.alfdir,
                                          u"kindlekey.py")
                defaultkeys = WineGetKeys(scriptpath, u".k4i",
                                          parent.getwineprefix())

            self.default_key = defaultkeys[0]
        except:
            traceback.print_exc()
            self.default_key = u""

        self.button_box = QDialogButtonBox(QDialogButtonBox.Ok
                                           | QDialogButtonBox.Cancel)

        if len(self.default_key) > 0:
            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(u"default_key", self)
            self.key_ledit.setToolTip(
                u"<p>Enter an identifying name for the current default Kindle for Mac/PC key."
            )
            key_group.addWidget(self.key_ledit)
            key_label = QLabel(_(''), self)
            key_label.setAlignment(Qt.AlignHCenter)
            data_group_box_layout.addWidget(key_label)
            self.button_box.accepted.connect(self.accept)
        else:
            default_key_error = QLabel(
                u"The default encryption key for Kindle for Mac/PC could not be found.",
                self)
            default_key_error.setAlignment(Qt.AlignHCenter)
            layout.addWidget(default_key_error)
            # if no default, bot buttons do the same
            self.button_box.accepted.connect(self.reject)

        self.button_box.rejected.connect(self.reject)
        layout.addWidget(self.button_box)

        self.resize(self.sizeHint())
コード例 #22
0
ファイル: config.py プロジェクト: kbw1/calibre-marvin-manager
class ConfigWidget(QWidget, Logger):
    '''
    Config dialog for Marvin Manager
    '''

    WIZARD_PROFILES = {
        'Annotations': {
            'label': 'mm_annotations',
            'datatype': 'comments',
            'display': {},
            'is_multiple': False
        },
        'Collections': {
            'label': 'mm_collections',
            'datatype': 'text',
            'display': {
                u'is_names': False
            },
            'is_multiple': True
        },
        'Last read': {
            'label': 'mm_date_read',
            'datatype': 'datetime',
            'display': {},
            'is_multiple': False
        },
        'Progress': {
            'label': 'mm_progress',
            'datatype': 'float',
            'display': {
                u'number_format': u'{0:.0f}%'
            },
            'is_multiple': False
        },
        'Read': {
            'label': 'mm_read',
            'datatype': 'bool',
            'display': {},
            'is_multiple': False
        },
        'Reading list': {
            'label': 'mm_reading_list',
            'datatype': 'bool',
            'display': {},
            'is_multiple': False
        },
        'Word count': {
            'label': 'mm_word_count',
            'datatype': 'int',
            'display': {
                u'number_format': u'{0:n}'
            },
            'is_multiple': False
        }
    }

    def __init__(self, plugin_action):
        QWidget.__init__(self)
        self.parent = plugin_action

        self.gui = get_gui()
        self.icon = plugin_action.icon
        self.opts = plugin_action.opts
        self.prefs = plugin_prefs
        self.resources_path = plugin_action.resources_path
        self.verbose = plugin_action.verbose

        self.restart_required = False

        self._log_location()

        self.l = QGridLayout()
        self.setLayout(self.l)
        self.column1_layout = QVBoxLayout()
        self.l.addLayout(self.column1_layout, 0, 0)
        self.column2_layout = QVBoxLayout()
        self.l.addLayout(self.column2_layout, 0, 1)

        # ----------------------------- Column 1 -----------------------------
        # ~~~~~~~~ Create the Custom fields options group box ~~~~~~~~
        self.cfg_custom_fields_gb = QGroupBox(self)
        self.cfg_custom_fields_gb.setTitle('Custom column assignments')
        self.column1_layout.addWidget(self.cfg_custom_fields_gb)

        self.cfg_custom_fields_qgl = QGridLayout(self.cfg_custom_fields_gb)
        current_row = 0

        # ++++++++ Labels + HLine ++++++++
        self.marvin_source_label = QLabel("Marvin source")
        self.cfg_custom_fields_qgl.addWidget(self.marvin_source_label,
                                             current_row, 0)
        self.calibre_destination_label = QLabel("calibre destination")
        self.cfg_custom_fields_qgl.addWidget(self.calibre_destination_label,
                                             current_row, 1)
        current_row += 1
        self.sd_hl = QFrame(self.cfg_custom_fields_gb)
        self.sd_hl.setFrameShape(QFrame.HLine)
        self.sd_hl.setFrameShadow(QFrame.Raised)
        self.cfg_custom_fields_qgl.addWidget(self.sd_hl, current_row, 0, 1, 3)
        current_row += 1

        # ++++++++ Annotations ++++++++
        self.cfg_annotations_label = QLabel('Annotations')
        self.cfg_annotations_label.setAlignment(Qt.AlignLeft)
        self.cfg_custom_fields_qgl.addWidget(self.cfg_annotations_label,
                                             current_row, 0)

        self.annotations_field_comboBox = QComboBox(self.cfg_custom_fields_gb)
        self.annotations_field_comboBox.setObjectName(
            'annotations_field_comboBox')
        self.annotations_field_comboBox.setToolTip(
            'Select a custom column to store Marvin annotations')
        self.cfg_custom_fields_qgl.addWidget(self.annotations_field_comboBox,
                                             current_row, 1)

        self.cfg_highlights_wizard = QToolButton()
        self.cfg_highlights_wizard.setIcon(QIcon(I('wizard.png')))
        self.cfg_highlights_wizard.setToolTip(
            "Create a custom column to store Marvin annotations")
        self.cfg_highlights_wizard.clicked.connect(
            partial(self.launch_cc_wizard, 'Annotations'))
        self.cfg_custom_fields_qgl.addWidget(self.cfg_highlights_wizard,
                                             current_row, 2)
        current_row += 1

        # ++++++++ Collections ++++++++
        self.cfg_collections_label = QLabel('Collections')
        self.cfg_collections_label.setAlignment(Qt.AlignLeft)
        self.cfg_custom_fields_qgl.addWidget(self.cfg_collections_label,
                                             current_row, 0)

        self.collection_field_comboBox = QComboBox(self.cfg_custom_fields_gb)
        self.collection_field_comboBox.setObjectName(
            'collection_field_comboBox')
        self.collection_field_comboBox.setToolTip(
            'Select a custom column to store Marvin collection assignments')
        self.cfg_custom_fields_qgl.addWidget(self.collection_field_comboBox,
                                             current_row, 1)

        self.cfg_collections_wizard = QToolButton()
        self.cfg_collections_wizard.setIcon(QIcon(I('wizard.png')))
        self.cfg_collections_wizard.setToolTip(
            "Create a custom column for Marvin collection assignments")
        self.cfg_collections_wizard.clicked.connect(
            partial(self.launch_cc_wizard, 'Collections'))
        self.cfg_custom_fields_qgl.addWidget(self.cfg_collections_wizard,
                                             current_row, 2)
        current_row += 1

        # ++++++++ Last read ++++++++
        self.cfg_date_read_label = QLabel("Last read")
        self.cfg_date_read_label.setAlignment(Qt.AlignLeft)
        self.cfg_custom_fields_qgl.addWidget(self.cfg_date_read_label,
                                             current_row, 0)

        self.date_read_field_comboBox = QComboBox(self.cfg_custom_fields_gb)
        self.date_read_field_comboBox.setObjectName('date_read_field_comboBox')
        self.date_read_field_comboBox.setToolTip(
            'Select a custom column to store Last read date')
        self.cfg_custom_fields_qgl.addWidget(self.date_read_field_comboBox,
                                             current_row, 1)

        self.cfg_collections_wizard = QToolButton()
        self.cfg_collections_wizard.setIcon(QIcon(I('wizard.png')))
        self.cfg_collections_wizard.setToolTip(
            "Create a custom column to store Last read date")
        self.cfg_collections_wizard.clicked.connect(
            partial(self.launch_cc_wizard, 'Last read'))
        self.cfg_custom_fields_qgl.addWidget(self.cfg_collections_wizard,
                                             current_row, 2)
        current_row += 1

        # ++++++++ Progress ++++++++
        self.cfg_progress_label = QLabel('Progress')
        self.cfg_progress_label.setAlignment(Qt.AlignLeft)
        self.cfg_custom_fields_qgl.addWidget(self.cfg_progress_label,
                                             current_row, 0)

        self.progress_field_comboBox = QComboBox(self.cfg_custom_fields_gb)
        self.progress_field_comboBox.setObjectName('progress_field_comboBox')
        self.progress_field_comboBox.setToolTip(
            'Select a custom column to store Marvin reading progress')
        self.cfg_custom_fields_qgl.addWidget(self.progress_field_comboBox,
                                             current_row, 1)

        self.cfg_progress_wizard = QToolButton()
        self.cfg_progress_wizard.setIcon(QIcon(I('wizard.png')))
        self.cfg_progress_wizard.setToolTip(
            "Create a custom column to store Marvin reading progress")
        self.cfg_progress_wizard.clicked.connect(
            partial(self.launch_cc_wizard, 'Progress'))
        self.cfg_custom_fields_qgl.addWidget(self.cfg_progress_wizard,
                                             current_row, 2)
        current_row += 1

        # ++++++++ Read flag ++++++++
        self.cfg_read_label = QLabel('Read')
        self.cfg_read_label.setAlignment(Qt.AlignLeft)
        self.cfg_custom_fields_qgl.addWidget(self.cfg_read_label, current_row,
                                             0)

        self.read_field_comboBox = QComboBox(self.cfg_custom_fields_gb)
        self.read_field_comboBox.setObjectName('read_field_comboBox')
        self.read_field_comboBox.setToolTip(
            'Select a custom column to store Marvin Read status')
        self.cfg_custom_fields_qgl.addWidget(self.read_field_comboBox,
                                             current_row, 1)

        self.cfg_read_wizard = QToolButton()
        self.cfg_read_wizard.setIcon(QIcon(I('wizard.png')))
        self.cfg_read_wizard.setToolTip(
            "Create a custom column to store Marvin Read status")
        self.cfg_read_wizard.clicked.connect(
            partial(self.launch_cc_wizard, 'Read'))
        self.cfg_custom_fields_qgl.addWidget(self.cfg_read_wizard, current_row,
                                             2)
        current_row += 1

        # ++++++++ Reading list flag ++++++++
        self.cfg_reading_list_label = QLabel('Reading list')
        self.cfg_reading_list_label.setAlignment(Qt.AlignLeft)
        self.cfg_custom_fields_qgl.addWidget(self.cfg_reading_list_label,
                                             current_row, 0)

        self.reading_list_field_comboBox = QComboBox(self.cfg_custom_fields_gb)
        self.reading_list_field_comboBox.setObjectName(
            'reading_list_field_comboBox')
        self.reading_list_field_comboBox.setToolTip(
            'Select a custom column to store Marvin Reading list status')
        self.cfg_custom_fields_qgl.addWidget(self.reading_list_field_comboBox,
                                             current_row, 1)

        self.cfg_reading_list_wizard = QToolButton()
        self.cfg_reading_list_wizard.setIcon(QIcon(I('wizard.png')))
        self.cfg_reading_list_wizard.setToolTip(
            "Create a custom column to store Marvin Reading list status")
        self.cfg_reading_list_wizard.clicked.connect(
            partial(self.launch_cc_wizard, 'Reading list'))
        self.cfg_custom_fields_qgl.addWidget(self.cfg_reading_list_wizard,
                                             current_row, 2)
        current_row += 1

        # ++++++++ Word count ++++++++
        self.cfg_word_count_label = QLabel('Word count')
        self.cfg_word_count_label.setAlignment(Qt.AlignLeft)
        self.cfg_custom_fields_qgl.addWidget(self.cfg_word_count_label,
                                             current_row, 0)

        self.word_count_field_comboBox = QComboBox(self.cfg_custom_fields_gb)
        self.word_count_field_comboBox.setObjectName(
            'word_count_field_comboBox')
        self.word_count_field_comboBox.setToolTip(
            'Select a custom column to store Marvin word counts')
        self.cfg_custom_fields_qgl.addWidget(self.word_count_field_comboBox,
                                             current_row, 1)

        self.cfg_word_count_wizard = QToolButton()
        self.cfg_word_count_wizard.setIcon(QIcon(I('wizard.png')))
        self.cfg_word_count_wizard.setToolTip(
            "Create a custom column to store Marvin word counts")
        self.cfg_word_count_wizard.clicked.connect(
            partial(self.launch_cc_wizard, 'Word count'))
        self.cfg_custom_fields_qgl.addWidget(self.cfg_word_count_wizard,
                                             current_row, 2)
        current_row += 1

        self.spacerItem1 = QSpacerItem(20, 20, QSizePolicy.Minimum,
                                       QSizePolicy.Expanding)
        self.column1_layout.addItem(self.spacerItem1)

        # ----------------------------- Column 2 -----------------------------
        # ~~~~~~~~ Create the CSS group box ~~~~~~~~
        self.cfg_css_options_gb = QGroupBox(self)
        self.cfg_css_options_gb.setTitle('CSS')
        self.column2_layout.addWidget(self.cfg_css_options_gb)
        self.cfg_css_options_qgl = QGridLayout(self.cfg_css_options_gb)

        current_row = 0

        # ++++++++ Annotations appearance ++++++++
        self.annotations_icon = QIcon(
            os.path.join(self.resources_path, 'icons',
                         'annotations_hiliter.png'))
        self.cfg_annotations_appearance_toolbutton = QToolButton()
        self.cfg_annotations_appearance_toolbutton.setIcon(
            self.annotations_icon)
        self.cfg_annotations_appearance_toolbutton.clicked.connect(
            self.configure_appearance)
        self.cfg_css_options_qgl.addWidget(
            self.cfg_annotations_appearance_toolbutton, current_row, 0)
        self.cfg_annotations_label = ClickableQLabel("Annotations")
        self.connect(self.cfg_annotations_label, SIGNAL('clicked()'),
                     self.configure_appearance)
        self.cfg_css_options_qgl.addWidget(self.cfg_annotations_label,
                                           current_row, 1)
        current_row += 1

        # ++++++++ Injected CSS ++++++++
        self.css_editor_icon = QIcon(I('format-text-heading.png'))
        self.cfg_css_editor_toolbutton = QToolButton()
        self.cfg_css_editor_toolbutton.setIcon(self.css_editor_icon)
        self.cfg_css_editor_toolbutton.clicked.connect(self.edit_css)
        self.cfg_css_options_qgl.addWidget(self.cfg_css_editor_toolbutton,
                                           current_row, 0)
        self.cfg_css_editor_label = ClickableQLabel("Articles, Vocabulary")
        self.connect(self.cfg_css_editor_label, SIGNAL('clicked()'),
                     self.edit_css)
        self.cfg_css_options_qgl.addWidget(self.cfg_css_editor_label,
                                           current_row, 1)
        """
        # ~~~~~~~~ Create the Dropbox syncing group box ~~~~~~~~
        self.cfg_dropbox_syncing_gb = QGroupBox(self)
        self.cfg_dropbox_syncing_gb.setTitle('Dropbox')
        self.column2_layout.addWidget(self.cfg_dropbox_syncing_gb)
        self.cfg_dropbox_syncing_qgl = QGridLayout(self.cfg_dropbox_syncing_gb)
        current_row = 0

        # ++++++++ Syncing enabled checkbox ++++++++
        self.dropbox_syncing_checkbox = QCheckBox('Enable Dropbox updates')
        self.dropbox_syncing_checkbox.setObjectName('dropbox_syncing')
        self.dropbox_syncing_checkbox.setToolTip('Refresh custom column content from Marvin metadata')
        self.cfg_dropbox_syncing_qgl.addWidget(self.dropbox_syncing_checkbox,
            current_row, 0, 1, 3)
        current_row += 1

        # ++++++++ Dropbox folder picker ++++++++
        self.dropbox_folder_icon = QIcon(os.path.join(self.resources_path, 'icons', 'dropbox.png'))
        self.cfg_dropbox_folder_toolbutton = QToolButton()
        self.cfg_dropbox_folder_toolbutton.setIcon(self.dropbox_folder_icon)
        self.cfg_dropbox_folder_toolbutton.setToolTip("Specify Dropbox folder location on your computer")
        self.cfg_dropbox_folder_toolbutton.clicked.connect(self.select_dropbox_folder)
        self.cfg_dropbox_syncing_qgl.addWidget(self.cfg_dropbox_folder_toolbutton,
            current_row, 1)

        # ++++++++ Dropbox location lineedit ++++++++
        self.dropbox_location_lineedit = QLineEdit()
        self.dropbox_location_lineedit.setPlaceholderText("Dropbox folder location")
        self.cfg_dropbox_syncing_qgl.addWidget(self.dropbox_location_lineedit,
            current_row, 2)
        """

        # ~~~~~~~~ Create the General options group box ~~~~~~~~
        self.cfg_runtime_options_gb = QGroupBox(self)
        self.cfg_runtime_options_gb.setTitle('General options')
        self.column2_layout.addWidget(self.cfg_runtime_options_gb)
        self.cfg_runtime_options_qvl = QVBoxLayout(self.cfg_runtime_options_gb)

        # ++++++++ Auto refresh checkbox ++++++++
        self.auto_refresh_checkbox = QCheckBox(
            'Automatically refresh custom column content')
        self.auto_refresh_checkbox.setObjectName('auto_refresh_at_startup')
        self.auto_refresh_checkbox.setToolTip(
            'Update calibre custom column when Marvin XD is opened')
        self.cfg_runtime_options_qvl.addWidget(self.auto_refresh_checkbox)

        # ++++++++ Progress as percentage checkbox ++++++++
        self.reading_progress_checkbox = QCheckBox(
            'Show reading progress as percentage')
        self.reading_progress_checkbox.setObjectName(
            'show_progress_as_percentage')
        self.reading_progress_checkbox.setToolTip(
            'Display percentage in Progress column')
        self.cfg_runtime_options_qvl.addWidget(self.reading_progress_checkbox)

        # ~~~~~~~~ Create the Debug options group box ~~~~~~~~
        self.cfg_debug_options_gb = QGroupBox(self)
        self.cfg_debug_options_gb.setTitle('Debug options')
        self.column2_layout.addWidget(self.cfg_debug_options_gb)
        self.cfg_debug_options_qvl = QVBoxLayout(self.cfg_debug_options_gb)

        # ++++++++ Debug logging checkboxes ++++++++
        self.debug_plugin_checkbox = QCheckBox(
            'Enable debug logging for Marvin XD')
        self.debug_plugin_checkbox.setObjectName('debug_plugin_checkbox')
        self.debug_plugin_checkbox.setToolTip(
            'Print plugin diagnostic messages to console')
        self.cfg_debug_options_qvl.addWidget(self.debug_plugin_checkbox)

        self.debug_libimobiledevice_checkbox = QCheckBox(
            'Enable debug logging for libiMobileDevice')
        self.debug_libimobiledevice_checkbox.setObjectName(
            'debug_libimobiledevice_checkbox')
        self.debug_libimobiledevice_checkbox.setToolTip(
            'Print libiMobileDevice diagnostic messages to console')
        self.cfg_debug_options_qvl.addWidget(
            self.debug_libimobiledevice_checkbox)

        self.spacerItem2 = QSpacerItem(20, 20, QSizePolicy.Minimum,
                                       QSizePolicy.Expanding)
        self.column2_layout.addItem(self.spacerItem2)

        # ~~~~~~~~ End of construction zone ~~~~~~~~
        self.resize(self.sizeHint())

        # ~~~~~~~~ Populate/restore config options ~~~~~~~~
        #  Annotations comboBox
        self.populate_annotations()
        self.populate_collections()
        self.populate_date_read()
        self.populate_progress()
        self.populate_read()
        self.populate_reading_list()
        self.populate_word_count()
        """
        # Restore Dropbox settings, hook changes
        dropbox_syncing = self.prefs.get('dropbox_syncing', False)
        self.dropbox_syncing_checkbox.setChecked(dropbox_syncing)
        self.set_dropbox_syncing(dropbox_syncing)
        self.dropbox_syncing_checkbox.clicked.connect(partial(self.set_dropbox_syncing))
        self.dropbox_location_lineedit.setText(self.prefs.get('dropbox_folder', ''))
        """

        # Restore general settings
        self.auto_refresh_checkbox.setChecked(
            self.prefs.get('auto_refresh_at_startup', False))
        self.reading_progress_checkbox.setChecked(
            self.prefs.get('show_progress_as_percentage', False))

        # Restore debug settings, hook changes
        self.debug_plugin_checkbox.setChecked(
            self.prefs.get('debug_plugin', False))
        self.debug_plugin_checkbox.stateChanged.connect(
            self.set_restart_required)
        self.debug_libimobiledevice_checkbox.setChecked(
            self.prefs.get('debug_libimobiledevice', False))
        self.debug_libimobiledevice_checkbox.stateChanged.connect(
            self.set_restart_required)

        # Hook changes to Annotations comboBox
        #         self.annotations_field_comboBox.currentIndexChanged.connect(
        #             partial(self.save_combobox_setting, 'annotations_field_comboBox'))
        self.connect(self.annotations_field_comboBox,
                     SIGNAL('currentIndexChanged(const QString &)'),
                     self.annotations_destination_changed)

        # Launch the annotated_books_scanner
        field = get_cc_mapping('annotations', 'field', None)
        self.annotated_books_scanner = InventoryAnnotatedBooks(self.gui, field)
        self.connect(self.annotated_books_scanner,
                     self.annotated_books_scanner.signal,
                     self.inventory_complete)
        QTimer.singleShot(1, self.start_inventory)

    def annotations_destination_changed(self, qs_new_destination_name):
        '''
        If the destination field changes, move all existing annotations from old to new
        '''
        self._log_location(str(qs_new_destination_name))
        #self._log("self.eligible_annotations_fields: %s" % self.eligible_annotations_fields)

        old_destination_field = get_cc_mapping('annotations', 'field', None)
        old_destination_name = get_cc_mapping('annotations', 'combobox', None)

        self._log("old_destination_field: %s" % old_destination_field)
        self._log("old_destination_name: %s" % old_destination_name)

        new_destination_name = unicode(qs_new_destination_name)
        self._log("new_destination_name: %s" % new_destination_name)

        if old_destination_name == new_destination_name:
            self._log_location(
                "old_destination_name = new_destination_name, no changes")
            return

        new_destination_field = self.eligible_annotations_fields[
            new_destination_name]

        if existing_annotations(self.parent, old_destination_field):
            command = self.launch_new_destination_dialog(
                old_destination_name, new_destination_name)

            if command == 'move':
                set_cc_mapping('annotations',
                               field=new_destination_field,
                               combobox=new_destination_name)

                if self.annotated_books_scanner.isRunning():
                    self.annotated_books_scanner.wait()
                move_annotations(self,
                                 self.annotated_books_scanner.annotation_map,
                                 old_destination_field, new_destination_field)

            elif command == 'change':
                # Keep the updated destination field, but don't move annotations
                pass

            elif command == 'cancel':
                # Restore previous destination
                self.annotations_field_comboBox.blockSignals(True)
                old_index = self.annotations_field_comboBox.findText(
                    old_destination_name)
                self.annotations_field_comboBox.setCurrentIndex(old_index)
                self.annotations_field_comboBox.blockSignals(False)

        else:
            # No existing annotations, just update prefs
            self._log("no existing annotations, updating destination to '{0}'".
                      format(new_destination_name))
            set_cc_mapping('annotations',
                           field=new_destination_field,
                           combobox=new_destination_name)

    def configure_appearance(self):
        '''
        '''
        self._log_location()
        appearance_settings = {
            'appearance_css': default_elements,
            'appearance_hr_checkbox': False,
            'appearance_timestamp_format': default_timestamp
        }

        # Save, hash the original settings
        original_settings = {}
        osh = hashlib.md5()
        for setting in appearance_settings:
            original_settings[setting] = plugin_prefs.get(
                setting, appearance_settings[setting])
            osh.update(
                repr(plugin_prefs.get(setting, appearance_settings[setting])))

        # Display the Annotations appearance dialog
        aa = AnnotationsAppearance(self, self.annotations_icon, plugin_prefs)
        cancelled = False
        if aa.exec_():
            # appearance_hr_checkbox and appearance_timestamp_format changed live to prefs during previews
            plugin_prefs.set('appearance_css', aa.elements_table.get_data())
            # Generate a new hash
            nsh = hashlib.md5()
            for setting in appearance_settings:
                nsh.update(
                    repr(
                        plugin_prefs.get(setting,
                                         appearance_settings[setting])))
        else:
            for setting in appearance_settings:
                plugin_prefs.set(setting, original_settings[setting])
            nsh = osh

        # If there were changes, and there are existing annotations,
        # and there is an active Annotations field, offer to re-render
        field = get_cc_mapping('annotations', 'field', None)
        if osh.digest() != nsh.digest() and existing_annotations(
                self.parent, field):
            title = 'Update annotations?'
            msg = '<p>Update existing annotations to new appearance settings?</p>'
            d = MessageBox(MessageBox.QUESTION,
                           title,
                           msg,
                           show_copy_button=False)
            self._log_location("QUESTION: %s" % msg)
            if d.exec_():
                self._log_location(
                    "Updating existing annotations to modified appearance")

                # Wait for indexing to complete
                while not self.annotated_books_scanner.isFinished():
                    Application.processEvents()

                move_annotations(self,
                                 self.annotated_books_scanner.annotation_map,
                                 field,
                                 field,
                                 window_title="Updating appearance")

    def edit_css(self):
        '''
        '''
        self._log_location()
        from calibre_plugins.marvin_manager.book_status import dialog_resources_path
        klass = os.path.join(dialog_resources_path, 'css_editor.py')
        if os.path.exists(klass):
            sys.path.insert(0, dialog_resources_path)
            this_dc = importlib.import_module('css_editor')
            sys.path.remove(dialog_resources_path)
            dlg = this_dc.CSSEditorDialog(self, 'css_editor')
            dlg.initialize(self)
            dlg.exec_()

    def get_eligible_custom_fields(self, eligible_types=[], is_multiple=None):
        '''
        Discover qualifying custom fields for eligible_types[]
        '''
        #self._log_location(eligible_types)

        eligible_custom_fields = {}
        for cf in self.gui.current_db.custom_field_keys():
            cft = self.gui.current_db.metadata_for_field(cf)['datatype']
            cfn = self.gui.current_db.metadata_for_field(cf)['name']
            cfim = self.gui.current_db.metadata_for_field(cf)['is_multiple']
            #self._log("cf: %s  cft: %s  cfn: %s cfim: %s" % (cf, cft, cfn, cfim))
            if cft in eligible_types:
                if is_multiple is not None:
                    if bool(cfim) == is_multiple:
                        eligible_custom_fields[cfn] = cf
                else:
                    eligible_custom_fields[cfn] = cf
        return eligible_custom_fields

    def inventory_complete(self, msg):
        self._log_location(msg)

    def launch_cc_wizard(self, column_type):
        '''
        '''
        def _update_combo_box(comboBox, destination, previous):
            '''
            '''
            cb = getattr(self, comboBox)
            cb.blockSignals(True)
            all_items = [str(cb.itemText(i)) for i in range(cb.count())]
            if previous and previous in all_items:
                all_items.remove(previous)
            all_items.append(destination)

            cb.clear()
            cb.addItems(sorted(all_items, key=lambda s: s.lower()))

            # Select the new destination in the comboBox
            idx = cb.findText(destination)
            if idx > -1:
                cb.setCurrentIndex(idx)

            cb.blockSignals(False)

        from calibre_plugins.marvin_manager.book_status import dialog_resources_path

        klass = os.path.join(dialog_resources_path, 'cc_wizard.py')
        if os.path.exists(klass):
            #self._log("importing CC Wizard dialog from '%s'" % klass)
            sys.path.insert(0, dialog_resources_path)
            this_dc = importlib.import_module('cc_wizard')
            sys.path.remove(dialog_resources_path)
            dlg = this_dc.CustomColumnWizard(self,
                                             column_type,
                                             self.WIZARD_PROFILES[column_type],
                                             verbose=True)
            dlg.exec_()

            if dlg.modified_column:
                self._log("modified_column: %s" % dlg.modified_column)

                self.restart_required = True

                destination = dlg.modified_column['destination']
                label = dlg.modified_column['label']
                previous = dlg.modified_column['previous']
                source = dlg.modified_column['source']

                if source == "Annotations":
                    _update_combo_box("annotations_field_comboBox",
                                      destination, previous)

                    # Add/update the new destination so save_settings() can find it
                    self.eligible_annotations_fields[destination] = label

                    # Save manually in case user cancels
                    set_cc_mapping('annotations',
                                   combobox=destination,
                                   field=label)

                elif source == 'Collections':
                    _update_combo_box("collection_field_comboBox", destination,
                                      previous)

                    # Add/update the new destination so save_settings() can find it
                    self.eligible_collection_fields[destination] = label

                    # Save manually in case user cancels
                    set_cc_mapping('collections',
                                   combobox=destination,
                                   field=label)

                elif source == 'Last read':
                    _update_combo_box("date_read_field_comboBox", destination,
                                      previous)

                    # Add/update the new destination so save_settings() can find it
                    self.eligible_date_read_fields[destination] = label

                    # Save manually in case user cancels
                    set_cc_mapping('date_read',
                                   combobox=destination,
                                   field=label)

                elif source == "Progress":
                    _update_combo_box("progress_field_comboBox", destination,
                                      previous)

                    # Add/update the new destination so save_settings() can find it
                    self.eligible_progress_fields[destination] = label

                    # Save manually in case user cancels
                    set_cc_mapping('progress',
                                   combobox=destination,
                                   field=label)

                elif source == "Read":
                    _update_combo_box("read_field_comboBox", destination,
                                      previous)

                    # Add/update the new destination so save_settings() can find it
                    self.eligible_read_fields[destination] = label

                    # Save manually in case user cancels
                    set_cc_mapping('read', combobox=destination, field=label)

                elif source == "Reading list":
                    _update_combo_box("reading_list_field_comboBox",
                                      destination, previous)

                    # Add/update the new destination so save_settings() can find it
                    self.eligible_reading_list_fields[destination] = label

                    # Save manually in case user cancels
                    set_cc_mapping('reading_list',
                                   combobox=destination,
                                   field=label)

                elif source == "Word count":
                    _update_combo_box("word_count_field_comboBox", destination,
                                      previous)

                    # Add/update the new destination so save_settings() can find it
                    self.eligible_word_count_fields[destination] = label

                    # Save manually in case user cancels
                    set_cc_mapping('word_count',
                                   combobox=destination,
                                   field=label)
        else:
            self._log("ERROR: Can't import from '%s'" % klass)

    def launch_new_destination_dialog(self, old, new):
        '''
        Return 'move', 'change' or 'cancel'
        '''
        from calibre_plugins.marvin_manager.book_status import dialog_resources_path
        self._log_location()
        klass = os.path.join(dialog_resources_path, 'new_destination.py')
        if os.path.exists(klass):
            self._log("importing new destination dialog from '%s'" % klass)
            sys.path.insert(0, dialog_resources_path)
            this_dc = importlib.import_module('new_destination')
            sys.path.remove(dialog_resources_path)
            dlg = this_dc.NewDestinationDialog(self, old, new)
            dlg.exec_()
            return dlg.command

    def populate_annotations(self):
        datatype = self.WIZARD_PROFILES['Annotations']['datatype']
        self.eligible_annotations_fields = self.get_eligible_custom_fields(
            [datatype])
        self.annotations_field_comboBox.addItems([''])
        ecf = sorted(self.eligible_annotations_fields.keys(),
                     key=lambda s: s.lower())
        self.annotations_field_comboBox.addItems(ecf)

        # Retrieve stored value
        existing = get_cc_mapping('annotations', 'combobox')
        if existing:
            ci = self.annotations_field_comboBox.findText(existing)
            self.annotations_field_comboBox.setCurrentIndex(ci)

    def populate_collections(self):
        datatype = self.WIZARD_PROFILES['Collections']['datatype']
        self.eligible_collection_fields = self.get_eligible_custom_fields(
            [datatype], is_multiple=True)
        self.collection_field_comboBox.addItems([''])
        ecf = sorted(self.eligible_collection_fields.keys(),
                     key=lambda s: s.lower())
        self.collection_field_comboBox.addItems(ecf)

        # Retrieve stored value
        existing = get_cc_mapping('collections', 'combobox')
        if existing:
            ci = self.collection_field_comboBox.findText(existing)
            self.collection_field_comboBox.setCurrentIndex(ci)

    def populate_date_read(self):
        #self.eligible_date_read_fields = self.get_eligible_custom_fields(['datetime'])
        datatype = self.WIZARD_PROFILES['Last read']['datatype']
        self.eligible_date_read_fields = self.get_eligible_custom_fields(
            [datatype])
        self.date_read_field_comboBox.addItems([''])
        ecf = sorted(self.eligible_date_read_fields.keys(),
                     key=lambda s: s.lower())
        self.date_read_field_comboBox.addItems(ecf)

        # Retrieve stored value
        existing = get_cc_mapping('date_read', 'combobox')
        if existing:
            ci = self.date_read_field_comboBox.findText(existing)
            self.date_read_field_comboBox.setCurrentIndex(ci)

    def populate_progress(self):
        #self.eligible_progress_fields = self.get_eligible_custom_fields(['float'])
        datatype = self.WIZARD_PROFILES['Progress']['datatype']
        self.eligible_progress_fields = self.get_eligible_custom_fields(
            [datatype])
        self.progress_field_comboBox.addItems([''])
        ecf = sorted(self.eligible_progress_fields.keys(),
                     key=lambda s: s.lower())
        self.progress_field_comboBox.addItems(ecf)

        # Retrieve stored value
        existing = get_cc_mapping('progress', 'combobox')
        if existing:
            ci = self.progress_field_comboBox.findText(existing)
            self.progress_field_comboBox.setCurrentIndex(ci)

    def populate_read(self):
        datatype = self.WIZARD_PROFILES['Read']['datatype']
        self.eligible_read_fields = self.get_eligible_custom_fields([datatype])
        self.read_field_comboBox.addItems([''])
        ecf = sorted(self.eligible_read_fields.keys(), key=lambda s: s.lower())
        self.read_field_comboBox.addItems(ecf)

        # Retrieve stored value
        existing = get_cc_mapping('read', 'combobox')
        if existing:
            ci = self.read_field_comboBox.findText(existing)
            self.read_field_comboBox.setCurrentIndex(ci)

    def populate_reading_list(self):
        datatype = self.WIZARD_PROFILES['Reading list']['datatype']
        self.eligible_reading_list_fields = self.get_eligible_custom_fields(
            [datatype])
        self.reading_list_field_comboBox.addItems([''])
        ecf = sorted(self.eligible_reading_list_fields.keys(),
                     key=lambda s: s.lower())
        self.reading_list_field_comboBox.addItems(ecf)

        # Retrieve stored value
        existing = get_cc_mapping('reading_list', 'combobox')
        if existing:
            ci = self.reading_list_field_comboBox.findText(existing)
            self.reading_list_field_comboBox.setCurrentIndex(ci)

    def populate_word_count(self):
        #self.eligible_word_count_fields = self.get_eligible_custom_fields(['int'])
        datatype = self.WIZARD_PROFILES['Word count']['datatype']
        self.eligible_word_count_fields = self.get_eligible_custom_fields(
            [datatype])
        self.word_count_field_comboBox.addItems([''])
        ecf = sorted(self.eligible_word_count_fields.keys(),
                     key=lambda s: s.lower())
        self.word_count_field_comboBox.addItems(ecf)

        # Retrieve stored value
        existing = get_cc_mapping('word_count', 'combobox')
        if existing:
            ci = self.word_count_field_comboBox.findText(existing)
            self.word_count_field_comboBox.setCurrentIndex(ci)

    """
    def select_dropbox_folder(self):
        '''
        '''
        self._log_location()
        dropbox_location = QFileDialog.getExistingDirectory(
            self,
            "Dropbox folder",
            os.path.expanduser("~"),
            QFileDialog.ShowDirsOnly | QFileDialog.DontResolveSymlinks)
        self.dropbox_location_lineedit.setText(unicode(dropbox_location))

    def set_dropbox_syncing(self, state):
        '''
        Called when checkbox changes state, or when restoring state
        Set enabled state of Dropbox folder picker to match
        '''
        self.cfg_dropbox_folder_toolbutton.setEnabled(state)
        self.dropbox_location_lineedit.setEnabled(state)
    """

    def set_restart_required(self, state):
        '''
        Set restart_required flag to show show dialog when closing dialog
        '''
        self.restart_required = True

    """
    def save_combobox_setting(self, cb, index):
        '''
        Apply changes immediately
        '''
        cf = str(getattr(self, cb).currentText())
        self._log_location("%s => %s" % (cb, repr(cf)))

        if cb == 'annotations_field_comboBox':
            field = None
            if cf:
                field = self.eligible_annotations_fields[cf]
            set_cc_mapping('annotations', combobox=cf, field=field)
    """

    def save_settings(self):
        self._log_location()

        # Annotations
        cf = unicode(self.annotations_field_comboBox.currentText())
        field = None
        if cf:
            field = self.eligible_annotations_fields[cf]
        set_cc_mapping('annotations', combobox=cf, field=field)

        # Collections
        cf = unicode(self.collection_field_comboBox.currentText())
        field = None
        if cf:
            field = self.eligible_collection_fields[cf]
        set_cc_mapping('collections', combobox=cf, field=field)

        # Save Date read field
        cf = unicode(self.date_read_field_comboBox.currentText())
        field = None
        if cf:
            field = self.eligible_date_read_fields[cf]
        set_cc_mapping('date_read', combobox=cf, field=field)

        # Save Progress field
        cf = unicode(self.progress_field_comboBox.currentText())
        field = None
        if cf:
            field = self.eligible_progress_fields[cf]
        set_cc_mapping('progress', combobox=cf, field=field)

        # Save Read field
        cf = unicode(self.read_field_comboBox.currentText())
        field = None
        if cf:
            field = self.eligible_read_fields[cf]
        set_cc_mapping('read', combobox=cf, field=field)

        # Save Reading list field
        cf = unicode(self.reading_list_field_comboBox.currentText())
        field = None
        if cf:
            field = self.eligible_reading_list_fields[cf]
        set_cc_mapping('reading_list', combobox=cf, field=field)

        # Save Word count field
        cf = unicode(self.word_count_field_comboBox.currentText())
        field = None
        if cf:
            field = self.eligible_word_count_fields[cf]
        set_cc_mapping('word_count', combobox=cf, field=field)
        '''
        # Save Dropbox settings
        self.prefs.set('dropbox_syncing', self.dropbox_syncing_checkbox.isChecked())
        self.prefs.set('dropbox_folder', unicode(self.dropbox_location_lineedit.text()))
        '''

        # Save general settings
        self.prefs.set('auto_refresh_at_startup',
                       self.auto_refresh_checkbox.isChecked())
        self.prefs.set('show_progress_as_percentage',
                       self.reading_progress_checkbox.isChecked())

        # Save debug settings
        self.prefs.set('debug_plugin', self.debug_plugin_checkbox.isChecked())
        self.prefs.set('debug_libimobiledevice',
                       self.debug_libimobiledevice_checkbox.isChecked())

        # If restart needed, inform user
        if self.restart_required:
            do_restart = show_restart_warning(
                'Restart calibre for the changes to be applied.',
                parent=self.gui)
            if do_restart:
                self.gui.quit(restart=True)

    def start_inventory(self):
        self._log_location()
        self.annotated_books_scanner.start()
コード例 #23
0
ファイル: polish.py プロジェクト: mrmac123/calibre
    def __init__(self, db, book_id_map, parent=None):
        from calibre.ebooks.oeb.polish.main import HELP
        QDialog.__init__(self, parent)
        self.db, self.book_id_map = weakref.ref(db), book_id_map
        self.setWindowIcon(QIcon(I('polish.png')))
        title = _('Polish book')
        if len(book_id_map) > 1:
            title = _('Polish %d books')%len(book_id_map)
        self.setWindowTitle(title)

        self.help_text = {
            'polish': _('<h3>About Polishing books</h3>%s')%HELP['about'].format(
                _('''<p>If you have both EPUB and ORIGINAL_EPUB in your book,
                  then polishing will run on ORIGINAL_EPUB (the same for other
                  ORIGINAL_* formats).  So if you
                  want Polishing to not run on the ORIGINAL_* format, delete the
                  ORIGINAL_* format before running it.</p>''')
            ),

            'embed':_('<h3>Embed referenced fonts</h3>%s')%HELP['embed'],
            'subset':_('<h3>Subsetting fonts</h3>%s')%HELP['subset'],

            'smarten_punctuation':
            _('<h3>Smarten punctuation</h3>%s')%HELP['smarten_punctuation'],

            'metadata':_('<h3>Updating metadata</h3>'
                         '<p>This will update all metadata <i>except</i> the cover in the'
                         ' ebook files to match the current metadata in the'
                         ' calibre library.</p>'
                         ' <p>Note that most ebook'
                         ' formats are not capable of supporting all the'
                         ' metadata in calibre.</p><p>There is a separate option to'
                         ' update the cover.</p>'),
            'do_cover': _('<h3>Update cover</h3><p>Update the covers in the ebook files to match the'
                        ' current cover in the calibre library.</p>'
                        '<p>If the ebook file does not have'
                        ' an identifiable cover, a new cover is inserted.</p>'
                        ),
            'jacket':_('<h3>Book Jacket</h3>%s')%HELP['jacket'],
            'remove_jacket':_('<h3>Remove Book Jacket</h3>%s')%HELP['remove_jacket'],
            'remove_unused_css':_('<h3>Remove unused CSS rules</h3>%s')%HELP['remove_unused_css'],
        }

        self.l = l = QGridLayout()
        self.setLayout(l)

        self.la = la = QLabel('<b>'+_('Select actions to perform:'))
        l.addWidget(la, 0, 0, 1, 2)

        count = 0
        self.all_actions = OrderedDict([
            ('embed', _('&Embed all referenced fonts')),
            ('subset', _('&Subset all embedded fonts')),
            ('smarten_punctuation', _('Smarten &punctuation')),
            ('metadata', _('Update &metadata in the book files')),
            ('do_cover', _('Update the &cover in the book files')),
            ('jacket', _('Add metadata as a "book &jacket" page')),
            ('remove_jacket', _('&Remove a previously inserted book jacket')),
            ('remove_unused_css', _('Remove &unused CSS rules from the book')),
        ])
        prefs = gprefs.get('polishing_settings', {})
        for name, text in self.all_actions.iteritems():
            count += 1
            x = QCheckBox(text, self)
            x.setChecked(prefs.get(name, False))
            x.stateChanged.connect(partial(self.option_toggled, name))
            l.addWidget(x, count, 0, 1, 1)
            setattr(self, 'opt_'+name, x)
            la = QLabel(' <a href="#%s">%s</a>'%(name, _('About')))
            setattr(self, 'label_'+name, x)
            la.linkActivated.connect(self.help_link_activated)
            l.addWidget(la, count, 1, 1, 1)

        count += 1
        l.addItem(QSpacerItem(10, 10, vPolicy=QSizePolicy.Expanding), count, 1, 1, 2)

        la = self.help_label = QLabel('')
        self.help_link_activated('#polish')
        la.setWordWrap(True)
        la.setTextFormat(Qt.RichText)
        la.setFrameShape(QFrame.StyledPanel)
        la.setAlignment(Qt.AlignLeft|Qt.AlignTop)
        la.setLineWidth(2)
        la.setStyleSheet('QLabel { margin-left: 75px }')
        l.addWidget(la, 0, 2, count+1, 1)
        l.setColumnStretch(2, 1)

        self.show_reports = sr = QCheckBox(_('Show &report'), self)
        sr.setChecked(gprefs.get('polish_show_reports', True))
        sr.setToolTip(textwrap.fill(_('Show a report of all the actions performed'
                        ' after polishing is completed')))
        l.addWidget(sr, count+1, 0, 1, 1)
        self.bb = bb = QDialogButtonBox(QDialogButtonBox.Ok|QDialogButtonBox.Cancel)
        bb.accepted.connect(self.accept)
        bb.rejected.connect(self.reject)
        self.save_button = sb = bb.addButton(_('&Save Settings'), bb.ActionRole)
        sb.clicked.connect(self.save_settings)
        self.load_button = lb = bb.addButton(_('&Load Settings'), bb.ActionRole)
        self.load_menu = QMenu(lb)
        lb.setMenu(self.load_menu)
        self.all_button = b = bb.addButton(_('Select &all'), bb.ActionRole)
        b.clicked.connect(partial(self.select_all, True))
        self.none_button = b = bb.addButton(_('Select &none'), bb.ActionRole)
        b.clicked.connect(partial(self.select_all, False))
        l.addWidget(bb, count+1, 1, 1, -1)
        self.setup_load_button()

        self.resize(QSize(950, 600))
コード例 #24
0
    def __init__(self, parent, db, id_to_select, select_sort, select_link):
        QDialog.__init__(self, parent)
        Ui_EditAuthorsDialog.__init__(self)
        self.setupUi(self)
        # Remove help icon on title bar
        icon = self.windowIcon()
        self.setWindowFlags(self.windowFlags()
                            & (~Qt.WindowContextHelpButtonHint))
        self.setWindowIcon(icon)

        try:
            self.table_column_widths = \
                        gprefs.get('manage_authors_table_widths', None)
            geom = gprefs.get('manage_authors_dialog_geometry', bytearray(''))
            self.restoreGeometry(QByteArray(geom))
        except:
            pass

        self.buttonBox.accepted.connect(self.accepted)

        # Set up the column headings
        self.table.setSelectionMode(QAbstractItemView.SingleSelection)
        self.table.setColumnCount(3)
        self.down_arrow_icon = QIcon(I('arrow-down.png'))
        self.up_arrow_icon = QIcon(I('arrow-up.png'))
        self.blank_icon = QIcon(I('blank.png'))
        self.auth_col = QTableWidgetItem(_('Author'))
        self.table.setHorizontalHeaderItem(0, self.auth_col)
        self.auth_col.setIcon(self.blank_icon)
        self.aus_col = QTableWidgetItem(_('Author sort'))
        self.table.setHorizontalHeaderItem(1, self.aus_col)
        self.aus_col.setIcon(self.up_arrow_icon)
        self.aul_col = QTableWidgetItem(_('Link'))
        self.table.setHorizontalHeaderItem(2, self.aul_col)
        self.aus_col.setIcon(self.blank_icon)

        # Add the data
        self.authors = {}
        auts = db.get_authors_with_ids()
        self.table.setRowCount(len(auts))
        select_item = None
        for row, (id, author, sort, link) in enumerate(auts):
            author = author.replace('|', ',')
            self.authors[id] = (author, sort, link)
            aut = tableItem(author)
            aut.setData(Qt.UserRole, id)
            sort = tableItem(sort)
            link = tableItem(link)
            self.table.setItem(row, 0, aut)
            self.table.setItem(row, 1, sort)
            self.table.setItem(row, 2, link)
            if id == id_to_select:
                if select_sort:
                    select_item = sort
                elif select_link:
                    select_item = link
                else:
                    select_item = aut
        self.table.resizeColumnsToContents()
        if self.table.columnWidth(2) < 200:
            self.table.setColumnWidth(2, 200)

        # set up the cellChanged signal only after the table is filled
        self.table.cellChanged.connect(self.cell_changed)

        # set up sort buttons
        self.sort_by_author.setCheckable(True)
        self.sort_by_author.setChecked(False)
        self.sort_by_author.clicked.connect(self.do_sort_by_author)
        self.author_order = 1

        self.table.sortByColumn(1, Qt.AscendingOrder)
        self.sort_by_author_sort.clicked.connect(self.do_sort_by_author_sort)
        self.sort_by_author_sort.setCheckable(True)
        self.sort_by_author_sort.setChecked(True)
        self.author_sort_order = 1

        self.recalc_author_sort.clicked.connect(self.do_recalc_author_sort)
        self.auth_sort_to_author.clicked.connect(self.do_auth_sort_to_author)

        # Position on the desired item
        if select_item is not None:
            self.table.setCurrentItem(select_item)
            self.table.editItem(select_item)
            self.start_find_pos = select_item.row() * 2 + select_item.column()
        else:
            self.table.setCurrentCell(0, 0)
            self.start_find_pos = -1

        # set up the search box
        self.find_box.initialize('manage_authors_search')
        self.find_box.lineEdit().returnPressed.connect(self.do_find)
        self.find_box.editTextChanged.connect(self.find_text_changed)
        self.find_button.clicked.connect(self.do_find)

        l = QLabel(self.table)
        self.not_found_label = l
        l.setFrameStyle(QFrame.StyledPanel)
        l.setAutoFillBackground(True)
        l.setText(_('No matches found'))
        l.setAlignment(Qt.AlignVCenter)
        l.resize(l.sizeHint())
        l.move(10, 20)
        l.setVisible(False)
        self.not_found_label.move(40, 40)
        self.not_found_label_timer = QTimer()
        self.not_found_label_timer.setSingleShot(True)
        self.not_found_label_timer.timeout.connect(
            self.not_found_label_timer_event, type=Qt.QueuedConnection)

        self.table.setContextMenuPolicy(Qt.CustomContextMenu)
        self.table.customContextMenuRequested.connect(self.show_context_menu)
コード例 #25
0
ファイル: jobs.py プロジェクト: 089git/calibre
class JobsButton(QFrame):  # {{{

    def __init__(self, horizontal=False, size=48, parent=None):
        QFrame.__init__(self, parent)
        if horizontal:
            size = 24
        self.pi = ProgressIndicator(self, size)
        self._jobs = QLabel('<b>'+_('Jobs:')+' 0')
        self._jobs.mouseReleaseEvent = self.mouseReleaseEvent
        self.shortcut = _('Shift+Alt+J')

        if horizontal:
            self.setLayout(QHBoxLayout())
            self.layout().setDirection(self.layout().RightToLeft)
        else:
            self.setLayout(QVBoxLayout())
            self._jobs.setAlignment(Qt.AlignHCenter|Qt.AlignBottom)

        self.layout().addWidget(self.pi)
        self.layout().addWidget(self._jobs)
        if not horizontal:
            self.layout().setAlignment(self._jobs, Qt.AlignHCenter)
        self._jobs.setMargin(0)
        self.layout().setMargin(0)
        self._jobs.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
        self.setCursor(Qt.PointingHandCursor)
        b = _('Click to see list of jobs')
        self.setToolTip(b + u' (%s)'%self.shortcut)
        self.action_toggle = QAction(b, parent)
        parent.addAction(self.action_toggle)
        self.action_toggle.setShortcut(self.shortcut)
        self.action_toggle.triggered.connect(self.toggle)

    def initialize(self, jobs_dialog, job_manager):
        self.jobs_dialog = jobs_dialog
        job_manager.job_added.connect(self.job_added)
        job_manager.job_done.connect(self.job_done)
        self.jobs_dialog.addAction(self.action_toggle)

    def mouseReleaseEvent(self, event):
        self.toggle()

    def toggle(self, *args):
        if self.jobs_dialog.isVisible():
            self.jobs_dialog.hide()
        else:
            self.jobs_dialog.show()

    @property
    def is_running(self):
        return self.pi.isAnimated()

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

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

    def jobs(self):
        src = unicode(self._jobs.text())
        return int(re.search(r'\d+', src).group())

    def job_added(self, nnum):
        jobs = self._jobs
        src = unicode(jobs.text())
        num = self.jobs()
        text = src.replace(str(num), str(nnum))
        jobs.setText(text)
        self.start()

    def job_done(self, nnum):
        jobs = self._jobs
        src = unicode(jobs.text())
        num = self.jobs()
        text = src.replace(str(num), str(nnum))
        jobs.setText(text)
        if nnum == 0:
            self.no_more_jobs()

    def no_more_jobs(self):
        if self.is_running:
            self.stop()
            QCoreApplication.instance().alert(self, 5000)
コード例 #26
0
ファイル: polish.py プロジェクト: badwtg1111/calibre
    def __init__(self, db, book_id_map, parent=None):
        from calibre.ebooks.oeb.polish.main import HELP
        QDialog.__init__(self, parent)
        self.db, self.book_id_map = weakref.ref(db), book_id_map
        self.setWindowIcon(QIcon(I('polish.png')))
        title = _('Polish book')
        if len(book_id_map) > 1:
            title = _('Polish %d books')%len(book_id_map)
        self.setWindowTitle(title)

        self.help_text = {
            'polish': _('<h3>About Polishing books</h3>%s')%HELP['about'].format(
                _('''<p>If you have both EPUB and ORIGINAL_EPUB in your book,
                  then polishing will run on ORIGINAL_EPUB (the same for other
                  ORIGINAL_* formats).  So if you
                  want Polishing to not run on the ORIGINAL_* format, delete the
                  ORIGINAL_* format before running it.</p>''')
            ),

            'embed':_('<h3>Embed referenced fonts</h3>%s')%HELP['embed'],
            'subset':_('<h3>Subsetting fonts</h3>%s')%HELP['subset'],

            'smarten_punctuation':
            _('<h3>Smarten punctuation</h3>%s')%HELP['smarten_punctuation'],

            'metadata':_('<h3>Updating metadata</h3>'
                         '<p>This will update all metadata <i>except</i> the cover in the'
                         ' ebook files to match the current metadata in the'
                         ' calibre library.</p>'
                         ' <p>Note that most ebook'
                         ' formats are not capable of supporting all the'
                         ' metadata in calibre.</p><p>There is a separate option to'
                         ' update the cover.</p>'),
            'do_cover': _('<p>Update the covers in the ebook files to match the'
                        ' current cover in the calibre library.</p>'
                        '<p>If the ebook file does not have'
                        ' an identifiable cover, a new cover is inserted.</p>'
                        ),
            'jacket':_('<h3>Book Jacket</h3>%s')%HELP['jacket'],
            'remove_jacket':_('<h3>Remove Book Jacket</h3>%s')%HELP['remove_jacket'],
        }

        self.l = l = QGridLayout()
        self.setLayout(l)

        self.la = la = QLabel('<b>'+_('Select actions to perform:'))
        l.addWidget(la, 0, 0, 1, 2)

        count = 0
        self.all_actions = OrderedDict([
            ('embed', _('&Embed all referenced fonts')),
            ('subset', _('&Subset all embedded fonts')),
            ('smarten_punctuation', _('Smarten &punctuation')),
            ('metadata', _('Update &metadata in the book files')),
            ('do_cover', _('Update the &cover in the book files')),
            ('jacket', _('Add metadata as a "book &jacket" page')),
            ('remove_jacket', _('&Remove a previously inserted book jacket')),
        ])
        prefs = gprefs.get('polishing_settings', {})
        for name, text in self.all_actions.iteritems():
            count += 1
            x = QCheckBox(text, self)
            x.setChecked(prefs.get(name, False))
            x.stateChanged.connect(partial(self.option_toggled, name))
            l.addWidget(x, count, 0, 1, 1)
            setattr(self, 'opt_'+name, x)
            la = QLabel(' <a href="#%s">%s</a>'%(name, _('About')))
            setattr(self, 'label_'+name, x)
            la.linkActivated.connect(self.help_link_activated)
            l.addWidget(la, count, 1, 1, 1)

        count += 1
        l.addItem(QSpacerItem(10, 10, vPolicy=QSizePolicy.Expanding), count, 1, 1, 2)

        la = self.help_label = QLabel('')
        self.help_link_activated('#polish')
        la.setWordWrap(True)
        la.setTextFormat(Qt.RichText)
        la.setFrameShape(QFrame.StyledPanel)
        la.setAlignment(Qt.AlignLeft|Qt.AlignTop)
        la.setLineWidth(2)
        la.setStyleSheet('QLabel { margin-left: 75px }')
        l.addWidget(la, 0, 2, count+1, 1)
        l.setColumnStretch(2, 1)

        self.show_reports = sr = QCheckBox(_('Show &report'), self)
        sr.setChecked(gprefs.get('polish_show_reports', True))
        sr.setToolTip(textwrap.fill(_('Show a report of all the actions performed'
                        ' after polishing is completed')))
        l.addWidget(sr, count+1, 0, 1, 1)
        self.bb = bb = QDialogButtonBox(QDialogButtonBox.Ok|QDialogButtonBox.Cancel)
        bb.accepted.connect(self.accept)
        bb.rejected.connect(self.reject)
        self.save_button = sb = bb.addButton(_('&Save Settings'), bb.ActionRole)
        sb.clicked.connect(self.save_settings)
        self.load_button = lb = bb.addButton(_('&Load Settings'), bb.ActionRole)
        self.load_menu = QMenu(lb)
        lb.setMenu(self.load_menu)
        self.all_button = b = bb.addButton(_('Select &all'), bb.ActionRole)
        b.clicked.connect(partial(self.select_all, True))
        self.none_button = b = bb.addButton(_('Select &none'), bb.ActionRole)
        b.clicked.connect(partial(self.select_all, False))
        l.addWidget(bb, count+1, 1, 1, -1)
        self.setup_load_button()

        self.resize(QSize(950, 600))
コード例 #27
0
class PluginUpdaterDialog(SizePersistedDialog):

    initial_extra_size = QSize(350, 100)

    def __init__(self, gui, initial_filter=FILTER_UPDATE_AVAILABLE):
        SizePersistedDialog.__init__(self, gui, 'Plugin Updater plugin:plugin updater dialog')
        self.gui = gui
        self.forum_link = None
        self.model = None
        self._initialize_controls()
        self._create_context_menu()

        display_plugins = read_available_plugins()

        if display_plugins:
            self.model = DisplayPluginModel(display_plugins)
            self.proxy_model = DisplayPluginSortFilterModel(self)
            self.proxy_model.setSourceModel(self.model)
            self.plugin_view.setModel(self.proxy_model)
            self.plugin_view.resizeColumnsToContents()
            self.plugin_view.selectionModel().currentRowChanged.connect(self._plugin_current_changed)
            self.plugin_view.doubleClicked.connect(self.install_button.click)
            self.filter_combo.setCurrentIndex(initial_filter)
            self._select_and_focus_view()
        else:
            error_dialog(self.gui, _('Update Check Failed'),
                        _('Unable to reach the MobileRead plugins forum index page.'),
                        det_msg=MR_INDEX_URL, show=True)
            self.filter_combo.setEnabled(False)
        # Cause our dialog size to be restored from prefs or created on first usage
        self.resize_dialog()

    def _initialize_controls(self):
        self.setWindowTitle(_('User plugins'))
        self.setWindowIcon(QIcon(I('plugins/plugin_updater.png')))
        layout = QVBoxLayout(self)
        self.setLayout(layout)
        title_layout = ImageTitleLayout(self, 'plugins/plugin_updater.png',
                _('User Plugins'))
        layout.addLayout(title_layout)

        header_layout = QHBoxLayout()
        layout.addLayout(header_layout)
        self.filter_combo = PluginFilterComboBox(self)
        self.filter_combo.setMinimumContentsLength(20)
        self.filter_combo.currentIndexChanged[int].connect(self._filter_combo_changed)
        header_layout.addWidget(QLabel(_('Filter list of plugins')+':', self))
        header_layout.addWidget(self.filter_combo)
        header_layout.addStretch(10)

        self.plugin_view = QTableView(self)
        self.plugin_view.horizontalHeader().setStretchLastSection(True)
        self.plugin_view.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.plugin_view.setSelectionMode(QAbstractItemView.SingleSelection)
        self.plugin_view.setAlternatingRowColors(True)
        self.plugin_view.setSortingEnabled(True)
        self.plugin_view.setIconSize(QSize(28, 28))
        layout.addWidget(self.plugin_view)

        details_layout = QHBoxLayout()
        layout.addLayout(details_layout)
        forum_label = QLabel('<a href="http://www.foo.com/">Plugin Forum Thread</a>', self)
        forum_label.setTextInteractionFlags(Qt.LinksAccessibleByMouse | Qt.LinksAccessibleByKeyboard)
        forum_label.linkActivated.connect(self._forum_label_activated)
        details_layout.addWidget(QLabel(_('Description')+':', self), 0, Qt.AlignLeft)
        details_layout.addWidget(forum_label, 1, Qt.AlignRight)

        self.description = QLabel(self)
        self.description.setFrameStyle(QFrame.Panel | QFrame.Sunken)
        self.description.setAlignment(Qt.AlignTop | Qt.AlignLeft)
        self.description.setMinimumHeight(40)
        layout.addWidget(self.description)

        self.button_box = QDialogButtonBox(QDialogButtonBox.Close)
        self.button_box.rejected.connect(self.reject)
        self.finished.connect(self._finished)
        self.install_button = self.button_box.addButton(_('&Install'), QDialogButtonBox.AcceptRole)
        self.install_button.setToolTip(_('Install the selected plugin'))
        self.install_button.clicked.connect(self._install_clicked)
        self.install_button.setEnabled(False)
        self.configure_button = self.button_box.addButton(' '+_('&Customize plugin ')+' ', QDialogButtonBox.ResetRole)
        self.configure_button.setToolTip(_('Customize the options for this plugin'))
        self.configure_button.clicked.connect(self._configure_clicked)
        self.configure_button.setEnabled(False)
        layout.addWidget(self.button_box)

    def _create_context_menu(self):
        self.plugin_view.setContextMenuPolicy(Qt.ActionsContextMenu)
        self.install_action = QAction(QIcon(I('plugins/plugin_upgrade_ok.png')), _('&Install'), self)
        self.install_action.setToolTip(_('Install the selected plugin'))
        self.install_action.triggered.connect(self._install_clicked)
        self.install_action.setEnabled(False)
        self.plugin_view.addAction(self.install_action)
        self.history_action = QAction(QIcon(I('chapters.png')), _('Version &History'), self)
        self.history_action.setToolTip(_('Show history of changes to this plugin'))
        self.history_action.triggered.connect(self._history_clicked)
        self.history_action.setEnabled(False)
        self.plugin_view.addAction(self.history_action)
        self.forum_action = QAction(QIcon(I('plugins/mobileread.png')), _('Plugin &Forum Thread'), self)
        self.forum_action.triggered.connect(self._forum_label_activated)
        self.forum_action.setEnabled(False)
        self.plugin_view.addAction(self.forum_action)

        sep1 = QAction(self)
        sep1.setSeparator(True)
        self.plugin_view.addAction(sep1)

        self.toggle_enabled_action = QAction(_('Enable/&Disable plugin'), self)
        self.toggle_enabled_action.setToolTip(_('Enable or disable this plugin'))
        self.toggle_enabled_action.triggered.connect(self._toggle_enabled_clicked)
        self.toggle_enabled_action.setEnabled(False)
        self.plugin_view.addAction(self.toggle_enabled_action)
        self.uninstall_action = QAction(_('&Remove plugin'), self)
        self.uninstall_action.setToolTip(_('Uninstall the selected plugin'))
        self.uninstall_action.triggered.connect(self._uninstall_clicked)
        self.uninstall_action.setEnabled(False)
        self.plugin_view.addAction(self.uninstall_action)

        sep2 = QAction(self)
        sep2.setSeparator(True)
        self.plugin_view.addAction(sep2)

        self.donate_enabled_action = QAction(QIcon(I('donate.png')), _('Donate to developer'), self)
        self.donate_enabled_action.setToolTip(_('Donate to the developer of this plugin'))
        self.donate_enabled_action.triggered.connect(self._donate_clicked)
        self.donate_enabled_action.setEnabled(False)
        self.plugin_view.addAction(self.donate_enabled_action)

        sep3 = QAction(self)
        sep3.setSeparator(True)
        self.plugin_view.addAction(sep3)

        self.configure_action = QAction(QIcon(I('config.png')), _('&Customize plugin'), self)
        self.configure_action.setToolTip(_('Customize the options for this plugin'))
        self.configure_action.triggered.connect(self._configure_clicked)
        self.configure_action.setEnabled(False)
        self.plugin_view.addAction(self.configure_action)

    def _finished(self, *args):
        if self.model:
            update_plugins = filter(filter_upgradeable_plugins, self.model.display_plugins)
            self.gui.recalc_update_label(len(update_plugins))

    def _plugin_current_changed(self, current, previous):
        if current.isValid():
            actual_idx = self.proxy_model.mapToSource(current)
            display_plugin = self.model.display_plugins[actual_idx.row()]
            self.description.setText(display_plugin.description)
            self.forum_link = display_plugin.forum_link
            self.forum_action.setEnabled(bool(self.forum_link))
            self.install_button.setEnabled(display_plugin.is_valid_to_install())
            self.install_action.setEnabled(self.install_button.isEnabled())
            self.uninstall_action.setEnabled(display_plugin.is_installed())
            self.history_action.setEnabled(display_plugin.has_changelog)
            self.configure_button.setEnabled(display_plugin.is_installed())
            self.configure_action.setEnabled(self.configure_button.isEnabled())
            self.toggle_enabled_action.setEnabled(display_plugin.is_installed())
            self.donate_enabled_action.setEnabled(bool(display_plugin.donation_link))
        else:
            self.description.setText('')
            self.forum_link = None
            self.forum_action.setEnabled(False)
            self.install_button.setEnabled(False)
            self.install_action.setEnabled(False)
            self.uninstall_action.setEnabled(False)
            self.history_action.setEnabled(False)
            self.configure_button.setEnabled(False)
            self.configure_action.setEnabled(False)
            self.toggle_enabled_action.setEnabled(False)
            self.donate_enabled_action.setEnabled(False)

    def _donate_clicked(self):
        plugin = self._selected_display_plugin()
        if plugin and plugin.donation_link:
            open_url(QUrl(plugin.donation_link))

    def _select_and_focus_view(self, change_selection=True):
        if change_selection and self.plugin_view.model().rowCount() > 0:
            self.plugin_view.selectRow(0)
        else:
            idx = self.plugin_view.selectionModel().currentIndex()
            self._plugin_current_changed(idx, 0)
        self.plugin_view.setFocus()

    def _filter_combo_changed(self, idx):
        self.proxy_model.set_filter_criteria(idx)
        if idx == FILTER_NOT_INSTALLED:
            self.plugin_view.sortByColumn(5, Qt.DescendingOrder)
        else:
            self.plugin_view.sortByColumn(0, Qt.AscendingOrder)
        self._select_and_focus_view()

    def _forum_label_activated(self):
        if self.forum_link:
            open_url(QUrl(self.forum_link))

    def _selected_display_plugin(self):
        idx = self.plugin_view.selectionModel().currentIndex()
        actual_idx = self.proxy_model.mapToSource(idx)
        return self.model.display_plugins[actual_idx.row()]

    def _uninstall_plugin(self, name_to_remove):
        if DEBUG:
            prints('Removing plugin: ', name_to_remove)
        remove_plugin(name_to_remove)
        # Make sure that any other plugins that required this plugin
        # to be uninstalled first have the requirement removed
        for display_plugin in self.model.display_plugins:
            # Make sure we update the status and display of the
            # plugin we just uninstalled
            if name_to_remove in display_plugin.uninstall_plugins:
                if DEBUG:
                    prints('Removing uninstall dependency for: ', display_plugin.name)
                display_plugin.uninstall_plugins.remove(name_to_remove)
            if display_plugin.name == name_to_remove:
                if DEBUG:
                    prints('Resetting plugin to uninstalled status: ', display_plugin.name)
                display_plugin.installed_version = None
                display_plugin.plugin = None
                display_plugin.uninstall_plugins = []
                if self.proxy_model.filter_criteria not in [FILTER_INSTALLED, FILTER_UPDATE_AVAILABLE]:
                    self.model.refresh_plugin(display_plugin)

    def _uninstall_clicked(self):
        display_plugin = self._selected_display_plugin()
        if not question_dialog(self, _('Are you sure?'), '<p>'+
                   _('Are you sure you want to uninstall the <b>%s</b> plugin?')%display_plugin.name,
                   show_copy_button=False):
            return
        self._uninstall_plugin(display_plugin.name)
        if self.proxy_model.filter_criteria in [FILTER_INSTALLED, FILTER_UPDATE_AVAILABLE]:
            self.model.reset()
            self._select_and_focus_view()
        else:
            self._select_and_focus_view(change_selection=False)

    def _install_clicked(self):
        display_plugin = self._selected_display_plugin()
        if not question_dialog(self, _('Install %s')%display_plugin.name, '<p>' + \
                _('Installing plugins is a <b>security risk</b>. '
                'Plugins can contain a virus/malware. '
                    'Only install it if you got it from a trusted source.'
                    ' Are you sure you want to proceed?'),
                show_copy_button=False):
            return

        if display_plugin.uninstall_plugins:
            uninstall_names = list(display_plugin.uninstall_plugins)
            if DEBUG:
                prints('Uninstalling plugin: ', ', '.join(uninstall_names))
            for name_to_remove in uninstall_names:
                self._uninstall_plugin(name_to_remove)

        if DEBUG:
            prints('Locating zip file for %s: %s'% (display_plugin.name, display_plugin.forum_link))
        self.gui.status_bar.showMessage(
                _('Locating zip file for %(name)s: %(link)s') % dict(
                    name=display_plugin.name, link=display_plugin.forum_link))
        plugin_zip_url = self._read_zip_attachment_url(display_plugin.forum_link)
        if not plugin_zip_url:
            return error_dialog(self.gui, _('Install Plugin Failed'),
                        _('Unable to locate a plugin zip file for <b>%s</b>') % display_plugin.name,
                        det_msg=display_plugin.forum_link, show=True)

        if DEBUG:
            prints('Downloading plugin zip attachment: ', plugin_zip_url)
        self.gui.status_bar.showMessage(_('Downloading plugin zip attachment: %s') % plugin_zip_url)
        zip_path = self._download_zip(plugin_zip_url)

        if DEBUG:
            prints('Installing plugin: ', zip_path)
        self.gui.status_bar.showMessage(_('Installing plugin: %s') % zip_path)

        try:
            try:
                plugin = add_plugin(zip_path)
            except NameConflict as e:
                return error_dialog(self.gui, _('Already exists'),
                        unicode(e), show=True)
            # Check for any toolbars to add to.
            widget = ConfigWidget(self.gui)
            widget.gui = self.gui
            widget.check_for_add_to_toolbars(plugin)
            self.gui.status_bar.showMessage(_('Plugin installed: %s') % display_plugin.name)
            info_dialog(self.gui, _('Success'),
                    _('Plugin <b>{0}</b> successfully installed under <b>'
                        ' {1} plugins</b>. You may have to restart calibre '
                        'for the plugin to take effect.').format(plugin.name, plugin.type),
                    show=True, show_copy_button=False)

            display_plugin.plugin = plugin
            # We cannot read the 'actual' version information as the plugin will not be loaded yet
            display_plugin.installed_version = display_plugin.available_version
        except:
            if DEBUG:
                prints('ERROR occurred while installing plugin: %s'%display_plugin.name)
                traceback.print_exc()
            error_dialog(self.gui, _('Install Plugin Failed'),
                         _('A problem occurred while installing this plugin.'
                           ' This plugin will now be uninstalled.'
                           ' Please post the error message in details below into'
                           ' the forum thread for this plugin and restart Calibre.'),
                         det_msg=traceback.format_exc(), show=True)
            if DEBUG:
                prints('Due to error now uninstalling plugin: %s'%display_plugin.name)
                remove_plugin(display_plugin.name)
                display_plugin.plugin = None

        display_plugin.uninstall_plugins = []
        if self.proxy_model.filter_criteria in [FILTER_NOT_INSTALLED, FILTER_UPDATE_AVAILABLE]:
            self.model.reset()
            self._select_and_focus_view()
        else:
            self.model.refresh_plugin(display_plugin)
            self._select_and_focus_view(change_selection=False)

    def _history_clicked(self):
        display_plugin = self._selected_display_plugin()
        text = self._read_version_history_html(display_plugin.forum_link)
        if text:
            dlg = VersionHistoryDialog(self, display_plugin.name, text)
            dlg.exec_()
        else:
            return error_dialog(self, _('Version history missing'),
                _('Unable to find the version history for %s')%display_plugin.name,
                show=True)

    def _configure_clicked(self):
        display_plugin = self._selected_display_plugin()
        plugin = display_plugin.plugin
        if not plugin.is_customizable():
            return info_dialog(self, _('Plugin not customizable'),
                _('Plugin: %s does not need customization')%plugin.name, show=True)
        from calibre.customize import InterfaceActionBase
        if isinstance(plugin, InterfaceActionBase) and not getattr(plugin,
                'actual_iaction_plugin_loaded', False):
            return error_dialog(self, _('Must restart'),
                    _('You must restart calibre before you can'
                        ' configure the <b>%s</b> plugin')%plugin.name, show=True)
        plugin.do_user_config(self.parent())

    def _toggle_enabled_clicked(self):
        display_plugin = self._selected_display_plugin()
        plugin = display_plugin.plugin
        if not plugin.can_be_disabled:
            return error_dialog(self,_('Plugin cannot be disabled'),
                         _('The plugin: %s cannot be disabled')%plugin.name, show=True)
        if is_disabled(plugin):
            enable_plugin(plugin)
        else:
            disable_plugin(plugin)
        self.model.refresh_plugin(display_plugin)

    def _read_version_history_html(self, forum_link):
        br = browser()
        br.set_handle_gzip(True)
        try:
            raw = br.open_novisit(forum_link).read()
            if not raw:
                return None
        except:
            traceback.print_exc()
            return None
        raw = raw.decode('utf-8', errors='replace')
        root = html.fromstring(raw)
        spoiler_nodes = root.xpath('//div[@class="smallfont" and strong="Spoiler"]')
        for spoiler_node in spoiler_nodes:
            try:
                if spoiler_node.getprevious() is None:
                    # This is a spoiler node that has been indented using [INDENT]
                    # Need to go up to parent div, then previous node to get header
                    heading_node = spoiler_node.getparent().getprevious()
                else:
                    # This is a spoiler node after a BR tag from the heading
                    heading_node = spoiler_node.getprevious().getprevious()
                if heading_node is None:
                    continue
                if heading_node.text_content().lower().find('version history') != -1:
                    div_node = spoiler_node.xpath('div')[0]
                    text = html.tostring(div_node, method='html', encoding=unicode)
                    return re.sub('<div\s.*?>', '<div>', text)
            except:
                if DEBUG:
                    prints('======= MobileRead Parse Error =======')
                    traceback.print_exc()
                    prints(html.tostring(spoiler_node))
        return None

    def _read_zip_attachment_url(self, forum_link):
        br = browser()
        br.set_handle_gzip(True)
        try:
            raw = br.open_novisit(forum_link).read()
            if not raw:
                return None
        except:
            traceback.print_exc()
            return None
        raw = raw.decode('utf-8', errors='replace')
        root = html.fromstring(raw)
        attachment_nodes = root.xpath('//fieldset/table/tr/td/a')
        for attachment_node in attachment_nodes:
            try:
                filename = attachment_node.text_content().lower()
                if filename.find('.zip') != -1:
                    full_url = MR_URL + attachment_node.attrib['href']
                    return full_url
            except:
                if DEBUG:
                    prints('======= MobileRead Parse Error =======')
                    traceback.print_exc()
                    prints(html.tostring(attachment_node))
        return None

    def _download_zip(self, plugin_zip_url):
        from calibre.ptempfile import PersistentTemporaryFile
        br = browser()
        br.set_handle_gzip(True)
        raw = br.open_novisit(plugin_zip_url).read()
        pt = PersistentTemporaryFile('.zip')
        pt.write(raw)
        pt.close()
        return pt.name
コード例 #28
0
ファイル: config.py プロジェクト: 12101/dedrm-ebook-tools
    def __init__(self, plugin_path, alfdir):
        QWidget.__init__(self)

        self.plugin_path = plugin_path
        self.alfdir = alfdir

        # get the prefs
        self.dedrmprefs = prefs.DeDRM_Prefs()

        # make a local copy
        self.tempdedrmprefs = {}
        self.tempdedrmprefs['bandnkeys'] = self.dedrmprefs['bandnkeys'].copy()
        self.tempdedrmprefs['adeptkeys'] = self.dedrmprefs['adeptkeys'].copy()
        self.tempdedrmprefs['ereaderkeys'] = self.dedrmprefs['ereaderkeys'].copy()
        self.tempdedrmprefs['kindlekeys'] = self.dedrmprefs['kindlekeys'].copy()
        self.tempdedrmprefs['pids'] = list(self.dedrmprefs['pids'])
        self.tempdedrmprefs['serials'] = list(self.dedrmprefs['serials'])
        self.tempdedrmprefs['adobewineprefix'] = self.dedrmprefs['adobewineprefix']
        self.tempdedrmprefs['kindlewineprefix'] = self.dedrmprefs['kindlewineprefix']

        # 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/">Plugin 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(_('Configuration:'), self)
        layout.addWidget(keys_group_box)
        keys_group_box_layout = QHBoxLayout()
        keys_group_box.setLayout(keys_group_box_layout)


        button_layout = QVBoxLayout()
        keys_group_box_layout.addLayout(button_layout)
        self.bandn_button = QtGui.QPushButton(self)
        self.bandn_button.setToolTip(_(u"Click to manage keys for Barnes and Noble ebooks"))
        self.bandn_button.setText(u"Barnes and Noble ebooks")
        self.bandn_button.clicked.connect(self.bandn_keys)
        self.kindle_serial_button = QtGui.QPushButton(self)
        self.kindle_serial_button.setToolTip(_(u"Click to manage eInk Kindle serial numbers for Kindle ebooks"))
        self.kindle_serial_button.setText(u"eInk Kindle ebooks")
        self.kindle_serial_button.clicked.connect(self.kindle_serials)
        self.kindle_key_button = QtGui.QPushButton(self)
        self.kindle_key_button.setToolTip(_(u"Click to manage keys for Kindle for Mac/PC ebooks"))
        self.kindle_key_button.setText(u"Kindle for Mac/PC ebooks")
        self.kindle_key_button.clicked.connect(self.kindle_keys)
        self.adept_button = QtGui.QPushButton(self)
        self.adept_button.setToolTip(_(u"Click to manage keys for Adobe Digital Editions ebooks"))
        self.adept_button.setText(u"Adobe Digital Editions ebooks")
        self.adept_button.clicked.connect(self.adept_keys)
        self.mobi_button = QtGui.QPushButton(self)
        self.mobi_button.setToolTip(_(u"Click to manage PIDs for Mobipocket ebooks"))
        self.mobi_button.setText(u"Mobipocket ebooks")
        self.mobi_button.clicked.connect(self.mobi_keys)
        self.ereader_button = QtGui.QPushButton(self)
        self.ereader_button.setToolTip(_(u"Click to manage keys for eReader ebooks"))
        self.ereader_button.setText(u"eReader ebooks")
        self.ereader_button.clicked.connect(self.ereader_keys)
        button_layout.addWidget(self.kindle_serial_button)
        button_layout.addWidget(self.bandn_button)
        button_layout.addWidget(self.mobi_button)
        button_layout.addWidget(self.ereader_button)
        button_layout.addWidget(self.adept_button)
        button_layout.addWidget(self.kindle_key_button)

        self.resize(self.sizeHint())
コード例 #29
0
    def __init__(self, parent):
        QWidget.__init__(self, parent)
        self.parent = parent
        self._layout = QVBoxLayout()
        self.setLayout(self._layout)
        self._layout.setContentsMargins(0,0,0,0)

        # Set up the find box & button
        search_layout = QHBoxLayout()
        self._layout.addLayout(search_layout)
        self.item_search = HistoryLineEdit(parent)
        self.item_search.setMinimumContentsLength(5)
        self.item_search.setSizeAdjustPolicy(self.item_search.AdjustToMinimumContentsLengthWithIcon)
        try:
            self.item_search.lineEdit().setPlaceholderText(
                                                _('Find item in tag browser'))
        except:
            pass             # Using Qt < 4.7
        self.item_search.setToolTip(_(
        'Search for items. This is a "contains" search; items containing the\n'
        'text anywhere in the name will be found. You can limit the search\n'
        'to particular categories using syntax similar to search. For example,\n'
        'tags:foo will find foo in any tag, but not in authors etc. Entering\n'
        '*foo will filter all categories at once, showing only those items\n'
        'containing the text "foo"'))
        search_layout.addWidget(self.item_search)
        # Not sure if the shortcut should be translatable ...
        sc = QShortcut(QKeySequence(_('ALT+f')), parent)
        sc.activated.connect(self.set_focus_to_find_box)

        self.search_button = QToolButton()
        self.search_button.setText(_('F&ind'))
        self.search_button.setToolTip(_('Find the first/next matching item'))
        search_layout.addWidget(self.search_button)

        self.expand_button = QToolButton()
        self.expand_button.setText('-')
        self.expand_button.setToolTip(_('Collapse all categories'))
        search_layout.addWidget(self.expand_button)
        search_layout.setStretch(0, 10)
        search_layout.setStretch(1, 1)
        search_layout.setStretch(2, 1)

        self.current_find_position = None
        self.search_button.clicked.connect(self.find)
        self.item_search.initialize('tag_browser_search')
        self.item_search.lineEdit().returnPressed.connect(self.do_find)
        self.item_search.lineEdit().textEdited.connect(self.find_text_changed)
        self.item_search.activated[QString].connect(self.do_find)
        self.item_search.completer().setCaseSensitivity(Qt.CaseSensitive)

        parent.tags_view = TagsView(parent)
        self.tags_view = parent.tags_view
        self.expand_button.clicked.connect(self.tags_view.collapseAll)
        self._layout.addWidget(parent.tags_view)

        # Now the floating 'not found' box
        l = QLabel(self.tags_view)
        self.not_found_label = l
        l.setFrameStyle(QFrame.StyledPanel)
        l.setAutoFillBackground(True)
        l.setText('<p><b>'+_('No More Matches.</b><p> Click Find again to go to first match'))
        l.setAlignment(Qt.AlignVCenter)
        l.setWordWrap(True)
        l.resize(l.sizeHint())
        l.move(10,20)
        l.setVisible(False)
        self.not_found_label_timer = QTimer()
        self.not_found_label_timer.setSingleShot(True)
        self.not_found_label_timer.timeout.connect(self.not_found_label_timer_event,
                                                   type=Qt.QueuedConnection)

        parent.alter_tb = l = QPushButton(parent)
        l.setText(_('Alter Tag Browser'))
        l.setIcon(QIcon(I('tags.png')))
        l.m = QMenu()
        l.setMenu(l.m)
        self._layout.addWidget(l)

        sb = l.m.addAction(_('Sort by'))
        sb.m = l.sort_menu = QMenu(l.m)
        sb.setMenu(sb.m)
        sb.bg = QActionGroup(sb)

        # Must be in the same order as db2.CATEGORY_SORTS
        for i, x in enumerate((_('Sort by name'), _('Sort by number of books'),
                  _('Sort by average rating'))):
            a = sb.m.addAction(x)
            sb.bg.addAction(a)
            a.setCheckable(True)
            if i == 0:
                a.setChecked(True)
        sb.setToolTip(
                _('Set the sort order for entries in the Tag Browser'))
        sb.setStatusTip(sb.toolTip())

        ma = l.m.addAction(_('Search type when selecting multiple items'))
        ma.m = l.match_menu = QMenu(l.m)
        ma.setMenu(ma.m)
        ma.ag = QActionGroup(ma)

        # Must be in the same order as db2.MATCH_TYPE
        for i, x in enumerate((_('Match any of the items'), _('Match all of the items'))):
            a = ma.m.addAction(x)
            ma.ag.addAction(a)
            a.setCheckable(True)
            if i == 0:
                a.setChecked(True)
        ma.setToolTip(
                _('When selecting multiple entries in the Tag Browser '
                    'match any or all of them'))
        ma.setStatusTip(ma.toolTip())

        mt = l.m.addAction(_('Manage authors, tags, etc'))
        mt.setToolTip(_('All of these category_managers are available by right-clicking '
                       'on items in the tag browser above'))
        mt.m = l.manage_menu = QMenu(l.m)
        mt.setMenu(mt.m)
コード例 #30
0
class PM_GroupBox( QGroupBox ):
    """
    The PM_GroupBox widget provides a group box container with a 
    collapse/expand button and a title button.
    
    PM group boxes can be nested by supplying an existing PM_GroupBox as the 
    parentWidget of a new PM_GroupBox (as an argument to its constructor).
    If the parentWidget is a PM_GroupBox, no title button will be created
    for the new group box.
    
    @cvar setAsDefault: Determines whether to reset the value of all
                        widgets in the group box when the user clicks
                        the "Restore Defaults" button. If set to False,
                        no widgets will be reset regardless thier own 
                        I{setAsDefault} value.
    @type setAsDefault: bool
       
    @cvar labelWidget: The Qt label widget of this group box.
    @type labelWidget: U{B{QLabel}<http://doc.trolltech.com/4/qlabel.html>}
    
    @cvar expanded: Expanded flag.
    @type expanded: bool
    
    @cvar _title: The group box title.
    @type _title: str
    
    @cvar _widgetList: List of widgets in the group box 
                      (except the title button).
    @type _widgetList: list
    
    @cvar _rowCount: Number of rows in the group box.
    @type _rowCount: int
    
    @cvar _groupBoxCount: Number of group boxes in this group box.
    @type _groupBoxCount: int
    
    @cvar _lastGroupBox: The last group box in this group box (i.e. the
                         most recent PM group box added).
    @type _lastGroupBox: PM_GroupBox
    """
    
    setAsDefault = True
    labelWidget  = None
    expanded     = True
    
    _title         = ""
    _widgetList    = []
    _rowCount      = 0
    _groupBoxCount = 0
    _lastGroupBox  = None
    titleButtonRequested = True
    
    def __init__(self, 
                 parentWidget, 
                 title          = '', 
                 connectTitleButton = True,
                 setAsDefault   = True
                 ):
        """
        Appends a PM_GroupBox widget to I{parentWidget}, a L{PM_Dialog} or a 
        L{PM_GroupBox}.
        
        If I{parentWidget} is a L{PM_Dialog}, the group box will have a title 
        button at the top for collapsing and expanding the group box. If 
        I{parentWidget} is a PM_GroupBox, the title will simply be a text 
        label at the top of the group box.
        
        @param parentWidget: The parent dialog or group box containing this
                             widget.
        @type  parentWidget: L{PM_Dialog} or L{PM_GroupBox}
        
        @param title: The title (button) text. If empty, no title is added.
        @type  title: str
        
        @param connectTitleButton: If True, this class will automatically 
                      connect the title button of the groupbox to send signal
                      to expand or collapse the groupbox. Otherwise, the caller
                      has to connect this signal by itself. See:
                      B{Ui_MovePropertyManager.addGroupBoxes} and 
                      B{MovePropertyManager.connect_or_disconnect_signals} for
                      examples where the client connects this slot. 
        @type  connectTitleButton: bool
               
        
        @param setAsDefault: If False, no widgets in this group box will have 
                             thier default values restored when the B{Restore 
                             Defaults} button is clicked, regardless thier own 
                             I{setAsDefault} value.
        @type  setAsDefault: bool
        
        @see: U{B{QGroupBox}<http://doc.trolltech.com/4/qgroupbox.html>}
        """
      
        QGroupBox.__init__(self)
        
        self.parentWidget = parentWidget
        
        # Calling addWidget() here is important. If done at the end,
        # the title button does not get assigned its palette for some 
        # unknown reason. Mark 2007-05-20.
        # Add self to PropMgr's vBoxLayout
        if parentWidget:
            parentWidget._groupBoxCount += 1
            parentWidget.vBoxLayout.addWidget(self)
            parentWidget._widgetList.append(self)
            
        _groupBoxCount = 0
        self._widgetList = []
        self._title = title
        self.setAsDefault = setAsDefault
        
        self.setAutoFillBackground(True)
        self.setStyleSheet(self._getStyleSheet())
        
        # Create vertical box layout which will contain two widgets:
        # - the group box title button (or title) on row 0.
        # - the container widget for all PM widgets on row 1.
        self._vBoxLayout = QVBoxLayout(self)
        self._vBoxLayout.setMargin(0)
        self._vBoxLayout.setSpacing(0)
        
        # _containerWidget contains all PM widgets in this group box.
        # Its sole purpose is to easily support the collapsing and
        # expanding of a group box by calling this widget's hide()
        # and show() methods.
        self._containerWidget = QWidget()
        
        self._vBoxLayout.insertWidget(0, self._containerWidget)
        
        # Create vertical box layout
        self.vBoxLayout = QVBoxLayout(self._containerWidget)
        self.vBoxLayout.setMargin(PM_GROUPBOX_VBOXLAYOUT_MARGIN)
        self.vBoxLayout.setSpacing(PM_GROUPBOX_VBOXLAYOUT_SPACING)
        
        # Create grid layout
        self.gridLayout = QGridLayout()
        self.gridLayout.setMargin(PM_GRIDLAYOUT_MARGIN)
        self.gridLayout.setSpacing(PM_GRIDLAYOUT_SPACING)
        
        # Insert grid layout in its own vBoxLayout
        self.vBoxLayout.addLayout(self.gridLayout)
        
        # Add title button (or just a title if the parent is not a PM_Dialog).
        if not parentWidget or isinstance(parentWidget, PM_GroupBox):
            self.setTitle(title)
        else: # Parent is a PM_Dialog, so add a title button.
            if not self.titleButtonRequested:
                self.setTitle(title)
            else:
                self.titleButton = self._getTitleButton(self, title)
                self._vBoxLayout.insertWidget(0, self.titleButton)
                if connectTitleButton:
                    self.connect( self.titleButton, 
                                  SIGNAL("clicked()"),
                                  self.toggleExpandCollapse)
                self._insertMacSpacer()
            
        # Fixes the height of the group box. Very important. Mark 2007-05-29
        self.setSizePolicy(
            QSizePolicy(QSizePolicy.Policy(QSizePolicy.Preferred),
                        QSizePolicy.Policy(QSizePolicy.Fixed)))
        
        self._addBottomSpacer()
        return
    
    def _insertMacSpacer(self, spacerHeight = 6):
        """
        This addresses a Qt 4.3.5 layout bug on Mac OS X in which the 
        title button will overlap with and cover the first widget in 
        the group box. This workaround inserts a I{spacerHeight} tall
        spacer between the group box's title button and container widget.
        """
        if sys.platform != "darwin":
            return
        
        self._macVerticalSpacer = QSpacerItem(10, spacerHeight, 
                                        QSizePolicy.MinimumExpanding,
                                        QSizePolicy.Fixed)
        self._vBoxLayout.insertItem(1, self._macVerticalSpacer)
        return
        
    def _addBottomSpacer(self):
        """
        Add a vertical spacer below this group box.
        
        Method: Assume this is going to be the last group box in the PM, so set
        its spacer's vertical sizePolicy to MinimumExpanding. We then set the 
        vertical sizePolicy of the last group box's spacer to Fixed and set its
        height to PM_GROUPBOX_SPACING.
        """
        # Spacers are only added to groupboxes in the PropMgr, not
        # nested groupboxes.
        
##        from PM.PM_Dialog import PM_Dialog
##        if not isinstance(self.parentWidget, PM_Dialog):
        
        if not self.parentWidget or isinstance(self.parentWidget, PM_GroupBox):
            #bruce 071103 revised test to remove import cycle; I assume that
            # self.parentWidget is either a PM_GroupBox or a PM_Dialog, since
            # comments about similar code in __init__ imply that.
            #
            # A cleaner fix would involve asking self.parentWidget whether to
            # do this, with instances of PM_GroupBox and PM_Dialog giving
            # different answers, and making them both inherit an API class
            # which documents the method or attr with which we ask them that
            # question; the API class would be inherited by any object to
            # which PM_GroupBox's such as self can be added.
            #
            # Or, an even cleaner fix would just call a method in
            # self.parentWidget to do what this code does now (implemented
            # differently in PM_GroupBox and PM_Dialog).
            self.verticalSpacer = None
            return
        
        if self.parentWidget._lastGroupBox:
            # _lastGroupBox is no longer the last one. <self> will be the
            # _lastGroupBox, so we must change the verticalSpacer height 
            # and sizePolicy of _lastGroupBox to be a fixed
            # spacer between it and <self>.
            defaultHeight = PM_GROUPBOX_SPACING
            self.parentWidget._lastGroupBox.verticalSpacer.changeSize(
                10, defaultHeight, 
                QSizePolicy.Fixed,
                QSizePolicy.Fixed)
            self.parentWidget._lastGroupBox.verticalSpacer.defaultHeight = \
                defaultHeight
            
        # Add a 1 pixel high, MinimumExpanding VSpacer below this group box.
        # This keeps all group boxes in the PM layout squeezed together as 
        # group boxes  are expanded, collapsed, hidden and shown again.
        defaultHeight = 1
        self.verticalSpacer = QSpacerItem(10, defaultHeight, 
                                        QSizePolicy.Fixed,
                                        QSizePolicy.MinimumExpanding)
        
        self.verticalSpacer.defaultHeight = defaultHeight
        
        self.parentWidget.vBoxLayout.addItem(self.verticalSpacer)
        
        # This groupbox is now the last one in the PropMgr.
        self.parentWidget._lastGroupBox = self
        return
        
    def restoreDefault (self):
        """
        Restores the default values for all widgets in this group box.
        """
        for widget in self._widgetList:
            if debug_flags.atom_debug:
                print "PM_GroupBox.restoreDefault(): widget =", \
                      widget.objectName()
            widget.restoreDefault()
            
        return
    
    def getTitle(self):
        """
        Returns the group box title.
        
        @return: The group box title.
        @rtype:  str
        """
        return self._title
    
    def setTitle(self, title):
        """
        Sets the groupbox title to <title>.
        
        @param title: The group box title.
        @type  title: str
        
        @attention: This overrides QGroupBox's setTitle() method.
        """
        
        if not title:
            return
        
        # Create QLabel widget.
        if not self.labelWidget:
            self.labelWidget = QLabel()
            self.vBoxLayout.insertWidget(0, self.labelWidget)
            labelAlignment = PM_LABEL_LEFT_ALIGNMENT
            self.labelWidget.setAlignment(labelAlignment)
        
        self._title = title
        self.labelWidget.setText(title)
        return
        
    def getPmWidgetPlacementParameters(self, pmWidget):
        """
        Returns all the layout parameters needed to place 
        a PM_Widget in the group box grid layout.
        
        @param pmWidget: The PM widget.
        @type  pmWidget: PM_Widget
        """
        
        row = self._rowCount
        
        #PM_CheckBox doesn't have a label. So do the following to decide the 
        #placement of the checkbox. (can be placed either in column 0 or 1 , 
        #This also needs to be implemented for PM_RadioButton, but at present 
        #the following code doesn't support PM_RadioButton. 
        if isinstance(pmWidget, PM_CheckBox):
            spanWidth = pmWidget.spanWidth
            
            if not spanWidth:
                # Set the widget's row and column parameters.
                widgetRow      = row
                widgetColumn   = pmWidget.widgetColumn
                widgetSpanCols = 1
                widgetAlignment = PM_LABEL_LEFT_ALIGNMENT
                rowIncrement   = 1
                #set a virtual label
                labelRow       = row
                labelSpanCols  = 1
                labelAlignment = PM_LABEL_RIGHT_ALIGNMENT
                            
                if widgetColumn == 0:
                    labelColumn   = 1                              
                elif widgetColumn == 1:
                    labelColumn   = 0
            else:                
                # Set the widget's row and column parameters.
                widgetRow      = row
                widgetColumn   = pmWidget.widgetColumn
                widgetSpanCols = 2
                widgetAlignment = PM_LABEL_LEFT_ALIGNMENT
                rowIncrement   = 1
                #no label 
                labelRow       = 0
                labelColumn    = 0
                labelSpanCols  = 0
                labelAlignment = PM_LABEL_RIGHT_ALIGNMENT
                
            
            return widgetRow, \
               widgetColumn, \
               widgetSpanCols, \
               widgetAlignment, \
               rowIncrement, \
               labelRow, \
               labelColumn, \
               labelSpanCols, \
               labelAlignment
        
       
        label       = pmWidget.label            
        labelColumn = pmWidget.labelColumn
        spanWidth   = pmWidget.spanWidth
        
        if not spanWidth: 
            # This widget and its label are on the same row
            labelRow       = row
            labelSpanCols  = 1
            labelAlignment = PM_LABEL_RIGHT_ALIGNMENT
            # Set the widget's row and column parameters.
            widgetRow      = row
            widgetColumn   = 1
            widgetSpanCols = 1
            widgetAlignment = PM_LABEL_LEFT_ALIGNMENT
            rowIncrement   = 1
            
            if labelColumn == 1:
                widgetColumn   = 0
                labelAlignment = PM_LABEL_LEFT_ALIGNMENT
                widgetAlignment = PM_LABEL_RIGHT_ALIGNMENT
                        
        else: 
                      
            # This widget spans the full width of the groupbox           
            if label: 
                # The label and widget are on separate rows.
                # Set the label's row, column and alignment.
                labelRow       = row
                labelColumn    = 0
                labelSpanCols  = 2
                    
                # Set this widget's row and column parameters.
                widgetRow      = row + 1 # Widget is below the label.
                widgetColumn   = 0
                widgetSpanCols = 2
                
                rowIncrement   = 2
            else:  # No label. Just the widget.
                labelRow       = 0
                labelColumn    = 0
                labelSpanCols  = 0

                # Set the widget's row and column parameters.
                widgetRow      = row
                widgetColumn   = 0
                widgetSpanCols = 2
                rowIncrement   = 1
                
            labelAlignment = PM_LABEL_LEFT_ALIGNMENT
            widgetAlignment = PM_LABEL_LEFT_ALIGNMENT
                
        return widgetRow, \
               widgetColumn, \
               widgetSpanCols, \
               widgetAlignment, \
               rowIncrement, \
               labelRow, \
               labelColumn, \
               labelSpanCols, \
               labelAlignment
    
    def addPmWidget(self, pmWidget):
        """
        Add a PM widget and its label to this group box.
        
        @param pmWidget: The PM widget to add.
        @type  pmWidget: PM_Widget
        """
        
        # Get all the widget and label layout parameters.
        widgetRow, \
        widgetColumn, \
        widgetSpanCols, \
        widgetAlignment, \
        rowIncrement, \
        labelRow, \
        labelColumn, \
        labelSpanCols, \
        labelAlignment = \
            self.getPmWidgetPlacementParameters(pmWidget)
        
        if pmWidget.labelWidget: 
            #Create Label as a pixmap (instead of text) if a valid icon path 
            #is provided
            labelPath = str(pmWidget.label)
            if labelPath and labelPath.startswith("ui/"): #bruce 080325 revised
                labelPixmap = getpixmap(labelPath)
                if not labelPixmap.isNull():
                    pmWidget.labelWidget.setPixmap(labelPixmap)
                    pmWidget.labelWidget.setText('')
               
            self.gridLayout.addWidget( pmWidget.labelWidget,
                                       labelRow, 
                                       labelColumn,
                                       1, 
                                       labelSpanCols,
                                       labelAlignment )
            
        
        # The following is a workaround for a Qt bug. If addWidth()'s 
        # <alignment> argument is not supplied, the widget spans the full 
        # column width of the grid cell containing it. If <alignment> 
        # is supplied, this desired behavior is lost and there is no 
        # value that can be supplied to maintain the behavior (0 doesn't 
        # work). The workaround is to call addWidget() without the <alignment>
        # argument. Mark 2007-07-27.

        if widgetAlignment == PM_LABEL_LEFT_ALIGNMENT:
            self.gridLayout.addWidget( pmWidget,
                                       widgetRow, 
                                       widgetColumn,
                                       1, 
                                       widgetSpanCols) 
                                       # aligment = 0 doesn't work.
        else:
            self.gridLayout.addWidget( pmWidget,
                                       widgetRow, 
                                       widgetColumn,
                                       1, 
                                       widgetSpanCols,
                                       widgetAlignment
                                     )

        self._widgetList.append(pmWidget)
        
        self._rowCount += rowIncrement
        return
    
    def getRowCount(self):
        """
        Return the row count of gridlayout of L{PM_Groupbox}
        
        @return: The row count of L{self.gridlayout}
        @rtype: int
        """
        return self._rowCount
    
    def incrementRowCount(self, increment = 1):
        """
        Increment the row count of the gridlayout of L{PM_groupBox}
        @param increment: The incremental value
        @type  increment: int
        """
        self._rowCount += increment
        return
        
    def addQtWidget(self, qtWidget, column = 0, spanWidth = False):
        """
        Add a Qt widget to this group box.
        
        @param qtWidget: The Qt widget to add.
        @type  qtWidget: QWidget
        
        @warning: this method has not been tested yet.
        """
        # Set the widget's row and column parameters.
        widgetRow      = self._rowCount
        widgetColumn   = column
        if spanWidth:
            widgetSpanCols = 2
        else:
            widgetSpanCols = 1
        
        self.gridLayout.addWidget( qtWidget,
                                   widgetRow, 
                                   widgetColumn,
                                   1, 
                                   widgetSpanCols )
        
        self._rowCount += 1
        return
    
    def collapse(self):
        """
        Collapse this group box i.e. hide all its contents and change the look 
        and feel of the groupbox button. 
        """
        self.vBoxLayout.setMargin(0)
        self.vBoxLayout.setSpacing(0)
        self.gridLayout.setMargin(0)
        self.gridLayout.setSpacing(0)
        # The styleSheet contains the expand/collapse.
        styleSheet = self._getTitleButtonStyleSheet(showExpanded = False)
        self.titleButton.setStyleSheet(styleSheet)
        self._containerWidget.hide()
        self.expanded = False 
        return
    
    def expand(self):
        """
        Expand this group box i.e. show all its contents and change the look 
        and feel of the groupbox button. 
        """       
        self.vBoxLayout.setMargin(PM_GROUPBOX_VBOXLAYOUT_MARGIN)
        self.vBoxLayout.setSpacing(PM_GROUPBOX_VBOXLAYOUT_SPACING)
        self.gridLayout.setMargin(PM_GROUPBOX_GRIDLAYOUT_MARGIN)
        self.gridLayout.setSpacing(PM_GROUPBOX_GRIDLAYOUT_SPACING)
            
        # The styleSheet contains the expand/collapse.
        styleSheet = self._getTitleButtonStyleSheet(showExpanded = True)
        self.titleButton.setStyleSheet(styleSheet)
        self._containerWidget.show()
        self.expanded = True
        return

    def hide(self):
        """
        Hides the group box .
        
        @see: L{show}
        """
        QWidget.hide(self)
        if self.labelWidget:
            self.labelWidget.hide() 
        
        # Change the spacer height to zero to "hide" it unless
        # self is the last GroupBox in the Property Manager.
        if self.parentWidget._lastGroupBox is self:
            return
        
        if self.verticalSpacer:
            self.verticalSpacer.changeSize(10, 0)
        return
            
    def show(self):
        """
        Unhides the group box.
        
        @see: L{hide}
        """
        QWidget.show(self)
        if self.labelWidget:
            self.labelWidget.show() 
        
        if self.parentWidget._lastGroupBox is self:
            return
        
        if self.verticalSpacer:
            self.verticalSpacer.changeSize(10, 
                                           self.verticalSpacer.defaultHeight)
        return

    # Title Button Methods #####################################
    
    def _getTitleButton(self, 
                        parentWidget = None,
                        title        = '', 
                        showExpanded = True ):
        """
        Return the group box title push button. The push button is customized 
        such that it appears as a title bar at the top of the group box. 
        If the user clicks on this 'title bar' it sends a signal to open or 
        close the group box.
        
        @param parentWidget: The parent dialog or group box containing this 
                             widget.
        @type  parentWidget: PM_Dialog or PM_GroupBox
        
        @param title: The button title.
        @type  title: str 
        
        @param showExpanded: dDetermines whether the expand or collapse image is 
                             displayed on the title button.
        @type  showExpanded: bool
                             
        @see: L{_getTitleButtonStyleSheet()}
        
        @Note: Including a title button should only be legal if the parentWidget
               is a PM_Dialog.
        """
        
        button  = QPushButton(title, parentWidget)
        button.setFlat(False)
        button.setAutoFillBackground(True)
        
        button.setStyleSheet(self._getTitleButtonStyleSheet(showExpanded))     
        
        return button
    
    def _getTitleButtonStyleSheet(self, showExpanded = True):
        """
        Returns the style sheet for a group box title button (or checkbox).
        
        @param showExpanded: Determines whether to include an expand or
                             collapse icon.
        @type  showExpanded: bool
        
        @return: The title button style sheet.
        @rtype:  str
        """
        
        # Need to move border color and text color to top 
        # (make global constants).
        if showExpanded:        
            styleSheet = \
                       "QPushButton {"\
                       "border-style: outset; "\
                       "border-width: 2px; "\
                       "border-color: #%s; "\
                       "border-radius: 2px; "\
                       "background-color: #%s; "\
                       "font: bold 12px 'Arial'; "\
                       "color: #%s; "\
                       "min-width: 10em; "\
                       "background-image: url(%s); "\
                       "background-position: right; "\
                       "background-repeat: no-repeat; "\
                       "text-align: left; "\
                       "}" % (QColor_to_Hex(pmGrpBoxButtonBorderColor),
                              QColor_to_Hex(pmGrpBoxButtonColor),
                              QColor_to_Hex(pmGrpBoxButtonTextColor),
                              pmGrpBoxExpandedIconPath
                              )
                              
        else:
            # Collapsed.
            styleSheet = \
                       "QPushButton {"\
                       "border-style: outset; "\
                       "border-width: 2px; "\
                       "border-color: #%s; "\
                       "border-radius: 2px; "\
                       "background-color: #%s; "\
                       "font: bold 12px 'Arial'; "\
                       "color: #%s; "\
                       "min-width: 10em; "\
                       "background-image: url(%s); "\
                       "background-position: right; "\
                       "background-repeat: no-repeat; "\
                       "text-align: left; "\
                       "}" % (QColor_to_Hex(pmGrpBoxButtonBorderColor),
                              QColor_to_Hex(pmGrpBoxButtonColor),
                              QColor_to_Hex(pmGrpBoxButtonTextColor),
                              pmGrpBoxCollapsedIconPath
                              )
        return styleSheet
            
    def toggleExpandCollapse(self):
        """
        Slot method for the title button to expand/collapse the group box.
        """
        if self._widgetList:
            if self.expanded:
                self.collapse()
            else: # Expand groupbox by showing all widgets in groupbox.
                self.expand()         
        else:
            print "Clicking on the group box button has no effect "\
                   "since it has no widgets."
        return
    
    # GroupBox stylesheet methods. ##############################
    
    def _getStyleSheet(self):
        """
        Return the style sheet for the groupbox. This sets the following 
        properties only:
         - border style
         - border width
         - border color
         - border radius (on corners)
         - background color
        
        @return: The group box style sheet.
        @rtype:  str
        """
        
        styleSheet = \
                   "QGroupBox {"\
                   "border-style: solid; "\
                   "border-width: 1px; "\
                   "border-color: #%s; "\
                   "border-radius: 0px; "\
                   "background-color: #%s; "\
                   "min-width: 10em; "\
                   "}" % ( QColor_to_Hex(pmGrpBoxBorderColor), 
                           QColor_to_Hex(pmGrpBoxColor)
                           )
        return styleSheet
コード例 #31
0
ファイル: plugin_updater.py プロジェクト: Hainish/calibre
class PluginUpdaterDialog(SizePersistedDialog):

    initial_extra_size = QSize(350, 100)
    forum_label_text = _('Plugin homepage')

    def __init__(self, gui, initial_filter=FILTER_UPDATE_AVAILABLE):
        SizePersistedDialog.__init__(self, gui, 'Plugin Updater plugin:plugin updater dialog')
        self.gui = gui
        self.forum_link = None
        self.zip_url = None
        self.model = None
        self.do_restart = False
        self._initialize_controls()
        self._create_context_menu()

        display_plugins = read_available_plugins()

        if display_plugins:
            self.model = DisplayPluginModel(display_plugins)
            self.proxy_model = DisplayPluginSortFilterModel(self)
            self.proxy_model.setSourceModel(self.model)
            self.plugin_view.setModel(self.proxy_model)
            self.plugin_view.resizeColumnsToContents()
            self.plugin_view.selectionModel().currentRowChanged.connect(self._plugin_current_changed)
            self.plugin_view.doubleClicked.connect(self.install_button.click)
            self.filter_combo.setCurrentIndex(initial_filter)
            self._select_and_focus_view()
        else:
            error_dialog(self.gui, _('Update Check Failed'),
                        _('Unable to reach the plugin index page.'),
                        det_msg=INDEX_URL, show=True)
            self.filter_combo.setEnabled(False)
        # Cause our dialog size to be restored from prefs or created on first usage
        self.resize_dialog()

    def _initialize_controls(self):
        self.setWindowTitle(_('User plugins'))
        self.setWindowIcon(QIcon(I('plugins/plugin_updater.png')))
        layout = QVBoxLayout(self)
        self.setLayout(layout)
        title_layout = ImageTitleLayout(self, 'plugins/plugin_updater.png',
                _('User Plugins'))
        layout.addLayout(title_layout)

        header_layout = QHBoxLayout()
        layout.addLayout(header_layout)
        self.filter_combo = PluginFilterComboBox(self)
        self.filter_combo.setMinimumContentsLength(20)
        self.filter_combo.currentIndexChanged[int].connect(self._filter_combo_changed)
        header_layout.addWidget(QLabel(_('Filter list of plugins')+':', self))
        header_layout.addWidget(self.filter_combo)
        header_layout.addStretch(10)

        # filter plugins by name
        header_layout.addWidget(QLabel(_('Filter by name')+':', self))
        self.filter_by_name_lineedit = QLineEdit(self)
        self.filter_by_name_lineedit.setText("")
        self.filter_by_name_lineedit.textChanged.connect(self._filter_name_lineedit_changed)

        header_layout.addWidget(self.filter_by_name_lineedit)

        self.plugin_view = QTableView(self)
        self.plugin_view.horizontalHeader().setStretchLastSection(True)
        self.plugin_view.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.plugin_view.setSelectionMode(QAbstractItemView.SingleSelection)
        self.plugin_view.setAlternatingRowColors(True)
        self.plugin_view.setSortingEnabled(True)
        self.plugin_view.setIconSize(QSize(28, 28))
        layout.addWidget(self.plugin_view)

        details_layout = QHBoxLayout()
        layout.addLayout(details_layout)
        forum_label = self.forum_label = QLabel('')
        forum_label.setTextInteractionFlags(Qt.LinksAccessibleByMouse | Qt.LinksAccessibleByKeyboard)
        forum_label.linkActivated.connect(self._forum_label_activated)
        details_layout.addWidget(QLabel(_('Description')+':', self), 0, Qt.AlignLeft)
        details_layout.addWidget(forum_label, 1, Qt.AlignRight)

        self.description = QLabel(self)
        self.description.setFrameStyle(QFrame.Panel | QFrame.Sunken)
        self.description.setAlignment(Qt.AlignTop | Qt.AlignLeft)
        self.description.setMinimumHeight(40)
        self.description.setWordWrap(True)
        layout.addWidget(self.description)

        self.button_box = QDialogButtonBox(QDialogButtonBox.Close)
        self.button_box.rejected.connect(self.reject)
        self.finished.connect(self._finished)
        self.install_button = self.button_box.addButton(_('&Install'), QDialogButtonBox.AcceptRole)
        self.install_button.setToolTip(_('Install the selected plugin'))
        self.install_button.clicked.connect(self._install_clicked)
        self.install_button.setEnabled(False)
        self.configure_button = self.button_box.addButton(' '+_('&Customize plugin ')+' ', QDialogButtonBox.ResetRole)
        self.configure_button.setToolTip(_('Customize the options for this plugin'))
        self.configure_button.clicked.connect(self._configure_clicked)
        self.configure_button.setEnabled(False)
        layout.addWidget(self.button_box)

    def update_forum_label(self):
        txt = ''
        if self.forum_link:
            txt = '<a href="%s">%s</a>' % (self.forum_link, self.forum_label_text)
        self.forum_label.setText(txt)

    def _create_context_menu(self):
        self.plugin_view.setContextMenuPolicy(Qt.ActionsContextMenu)
        self.install_action = QAction(QIcon(I('plugins/plugin_upgrade_ok.png')), _('&Install'), self)
        self.install_action.setToolTip(_('Install the selected plugin'))
        self.install_action.triggered.connect(self._install_clicked)
        self.install_action.setEnabled(False)
        self.plugin_view.addAction(self.install_action)
        self.history_action = QAction(QIcon(I('chapters.png')), _('Version &History'), self)
        self.history_action.setToolTip(_('Show history of changes to this plugin'))
        self.history_action.triggered.connect(self._history_clicked)
        self.history_action.setEnabled(False)
        self.plugin_view.addAction(self.history_action)
        self.forum_action = QAction(QIcon(I('plugins/mobileread.png')), _('Plugin &Forum Thread'), self)
        self.forum_action.triggered.connect(self._forum_label_activated)
        self.forum_action.setEnabled(False)
        self.plugin_view.addAction(self.forum_action)

        sep1 = QAction(self)
        sep1.setSeparator(True)
        self.plugin_view.addAction(sep1)

        self.toggle_enabled_action = QAction(_('Enable/&Disable plugin'), self)
        self.toggle_enabled_action.setToolTip(_('Enable or disable this plugin'))
        self.toggle_enabled_action.triggered.connect(self._toggle_enabled_clicked)
        self.toggle_enabled_action.setEnabled(False)
        self.plugin_view.addAction(self.toggle_enabled_action)
        self.uninstall_action = QAction(_('&Remove plugin'), self)
        self.uninstall_action.setToolTip(_('Uninstall the selected plugin'))
        self.uninstall_action.triggered.connect(self._uninstall_clicked)
        self.uninstall_action.setEnabled(False)
        self.plugin_view.addAction(self.uninstall_action)

        sep2 = QAction(self)
        sep2.setSeparator(True)
        self.plugin_view.addAction(sep2)

        self.donate_enabled_action = QAction(QIcon(I('donate.png')), _('Donate to developer'), self)
        self.donate_enabled_action.setToolTip(_('Donate to the developer of this plugin'))
        self.donate_enabled_action.triggered.connect(self._donate_clicked)
        self.donate_enabled_action.setEnabled(False)
        self.plugin_view.addAction(self.donate_enabled_action)

        sep3 = QAction(self)
        sep3.setSeparator(True)
        self.plugin_view.addAction(sep3)

        self.configure_action = QAction(QIcon(I('config.png')), _('&Customize plugin'), self)
        self.configure_action.setToolTip(_('Customize the options for this plugin'))
        self.configure_action.triggered.connect(self._configure_clicked)
        self.configure_action.setEnabled(False)
        self.plugin_view.addAction(self.configure_action)

    def _finished(self, *args):
        if self.model:
            update_plugins = filter(filter_upgradeable_plugins, self.model.display_plugins)
            self.gui.recalc_update_label(len(update_plugins))

    def _plugin_current_changed(self, current, previous):
        if current.isValid():
            actual_idx = self.proxy_model.mapToSource(current)
            display_plugin = self.model.display_plugins[actual_idx.row()]
            self.description.setText(display_plugin.description)
            self.forum_link = display_plugin.forum_link
            self.zip_url = display_plugin.zip_url
            self.forum_action.setEnabled(bool(self.forum_link))
            self.install_button.setEnabled(display_plugin.is_valid_to_install())
            self.install_action.setEnabled(self.install_button.isEnabled())
            self.uninstall_action.setEnabled(display_plugin.is_installed())
            self.history_action.setEnabled(display_plugin.has_changelog)
            self.configure_button.setEnabled(display_plugin.is_installed())
            self.configure_action.setEnabled(self.configure_button.isEnabled())
            self.toggle_enabled_action.setEnabled(display_plugin.is_installed())
            self.donate_enabled_action.setEnabled(bool(display_plugin.donation_link))
        else:
            self.description.setText('')
            self.forum_link = None
            self.zip_url = None
            self.forum_action.setEnabled(False)
            self.install_button.setEnabled(False)
            self.install_action.setEnabled(False)
            self.uninstall_action.setEnabled(False)
            self.history_action.setEnabled(False)
            self.configure_button.setEnabled(False)
            self.configure_action.setEnabled(False)
            self.toggle_enabled_action.setEnabled(False)
            self.donate_enabled_action.setEnabled(False)
        self.update_forum_label()

    def _donate_clicked(self):
        plugin = self._selected_display_plugin()
        if plugin and plugin.donation_link:
            open_url(QUrl(plugin.donation_link))

    def _select_and_focus_view(self, change_selection=True):
        if change_selection and self.plugin_view.model().rowCount() > 0:
            self.plugin_view.selectRow(0)
        else:
            idx = self.plugin_view.selectionModel().currentIndex()
            self._plugin_current_changed(idx, 0)
        self.plugin_view.setFocus()

    def _filter_combo_changed(self, idx):
        self.filter_by_name_lineedit.setText("")  # clear the name filter text when a different group was selected
        self.proxy_model.set_filter_criteria(idx)
        if idx == FILTER_NOT_INSTALLED:
            self.plugin_view.sortByColumn(5, Qt.DescendingOrder)
        else:
            self.plugin_view.sortByColumn(0, Qt.AscendingOrder)
        self._select_and_focus_view()

    def _filter_name_lineedit_changed(self, text):
        self.proxy_model.set_filter_text(text)  # set the filter text for filterAcceptsRow

    def _forum_label_activated(self):
        if self.forum_link:
            open_url(QUrl(self.forum_link))

    def _selected_display_plugin(self):
        idx = self.plugin_view.selectionModel().currentIndex()
        actual_idx = self.proxy_model.mapToSource(idx)
        return self.model.display_plugins[actual_idx.row()]

    def _uninstall_plugin(self, name_to_remove):
        if DEBUG:
            prints('Removing plugin: ', name_to_remove)
        remove_plugin(name_to_remove)
        # Make sure that any other plugins that required this plugin
        # to be uninstalled first have the requirement removed
        for display_plugin in self.model.display_plugins:
            # Make sure we update the status and display of the
            # plugin we just uninstalled
            if name_to_remove in display_plugin.uninstall_plugins:
                if DEBUG:
                    prints('Removing uninstall dependency for: ', display_plugin.name)
                display_plugin.uninstall_plugins.remove(name_to_remove)
            if display_plugin.name == name_to_remove:
                if DEBUG:
                    prints('Resetting plugin to uninstalled status: ', display_plugin.name)
                display_plugin.installed_version = None
                display_plugin.plugin = None
                display_plugin.uninstall_plugins = []
                if self.proxy_model.filter_criteria not in [FILTER_INSTALLED, FILTER_UPDATE_AVAILABLE]:
                    self.model.refresh_plugin(display_plugin)

    def _uninstall_clicked(self):
        display_plugin = self._selected_display_plugin()
        if not question_dialog(self, _('Are you sure?'), '<p>'+
                   _('Are you sure you want to uninstall the <b>%s</b> plugin?')%display_plugin.name,
                   show_copy_button=False):
            return
        self._uninstall_plugin(display_plugin.name)
        if self.proxy_model.filter_criteria in [FILTER_INSTALLED, FILTER_UPDATE_AVAILABLE]:
            self.model.reset()
            self._select_and_focus_view()
        else:
            self._select_and_focus_view(change_selection=False)

    def _install_clicked(self):
        display_plugin = self._selected_display_plugin()
        if not question_dialog(self, _('Install %s')%display_plugin.name, '<p>' +
                _('Installing plugins is a <b>security risk</b>. '
                'Plugins can contain a virus/malware. '
                    'Only install it if you got it from a trusted source.'
                    ' Are you sure you want to proceed?'),
                show_copy_button=False):
            return

        if display_plugin.uninstall_plugins:
            uninstall_names = list(display_plugin.uninstall_plugins)
            if DEBUG:
                prints('Uninstalling plugin: ', ', '.join(uninstall_names))
            for name_to_remove in uninstall_names:
                self._uninstall_plugin(name_to_remove)

        plugin_zip_url = display_plugin.zip_url
        if DEBUG:
            prints('Downloading plugin zip attachment: ', plugin_zip_url)
        self.gui.status_bar.showMessage(_('Downloading plugin zip attachment: %s') % plugin_zip_url)
        zip_path = self._download_zip(plugin_zip_url)

        if DEBUG:
            prints('Installing plugin: ', zip_path)
        self.gui.status_bar.showMessage(_('Installing plugin: %s') % zip_path)

        do_restart = False
        try:
            try:
                plugin = add_plugin(zip_path)
            except NameConflict as e:
                return error_dialog(self.gui, _('Already exists'),
                        unicode(e), show=True)
            # Check for any toolbars to add to.
            widget = ConfigWidget(self.gui)
            widget.gui = self.gui
            widget.check_for_add_to_toolbars(plugin)
            self.gui.status_bar.showMessage(_('Plugin installed: %s') % display_plugin.name)
            d = info_dialog(self.gui, _('Success'),
                    _('Plugin <b>{0}</b> successfully installed under <b>'
                        ' {1} plugins</b>. You may have to restart calibre '
                        'for the plugin to take effect.').format(plugin.name, plugin.type),
                    show_copy_button=False)
            b = d.bb.addButton(_('Restart calibre now'), d.bb.AcceptRole)
            b.setIcon(QIcon(I('lt.png')))
            d.do_restart = False
            def rf():
                d.do_restart = True
            b.clicked.connect(rf)
            d.set_details('')
            d.exec_()
            b.clicked.disconnect()
            do_restart = d.do_restart

            display_plugin.plugin = plugin
            # We cannot read the 'actual' version information as the plugin will not be loaded yet
            display_plugin.installed_version = display_plugin.available_version
        except:
            if DEBUG:
                prints('ERROR occurred while installing plugin: %s'%display_plugin.name)
                traceback.print_exc()
            error_dialog(self.gui, _('Install Plugin Failed'),
                         _('A problem occurred while installing this plugin.'
                           ' This plugin will now be uninstalled.'
                           ' Please post the error message in details below into'
                           ' the forum thread for this plugin and restart Calibre.'),
                         det_msg=traceback.format_exc(), show=True)
            if DEBUG:
                prints('Due to error now uninstalling plugin: %s'%display_plugin.name)
            remove_plugin(display_plugin.name)
            display_plugin.plugin = None

        display_plugin.uninstall_plugins = []
        if self.proxy_model.filter_criteria in [FILTER_NOT_INSTALLED, FILTER_UPDATE_AVAILABLE]:
            self.model.reset()
            self._select_and_focus_view()
        else:
            self.model.refresh_plugin(display_plugin)
            self._select_and_focus_view(change_selection=False)
        if do_restart:
            self.do_restart = True
            self.accept()

    def _history_clicked(self):
        display_plugin = self._selected_display_plugin()
        text = self._read_version_history_html(display_plugin.forum_link)
        if text:
            dlg = VersionHistoryDialog(self, display_plugin.name, text)
            dlg.exec_()
        else:
            return error_dialog(self, _('Version history missing'),
                _('Unable to find the version history for %s')%display_plugin.name,
                show=True)

    def _configure_clicked(self):
        display_plugin = self._selected_display_plugin()
        plugin = display_plugin.plugin
        if not plugin.is_customizable():
            return info_dialog(self, _('Plugin not customizable'),
                _('Plugin: %s does not need customization')%plugin.name, show=True)
        from calibre.customize import InterfaceActionBase
        if isinstance(plugin, InterfaceActionBase) and not getattr(plugin,
                'actual_iaction_plugin_loaded', False):
            return error_dialog(self, _('Must restart'),
                    _('You must restart calibre before you can'
                        ' configure the <b>%s</b> plugin')%plugin.name, show=True)
        plugin.do_user_config(self.parent())

    def _toggle_enabled_clicked(self):
        display_plugin = self._selected_display_plugin()
        plugin = display_plugin.plugin
        if not plugin.can_be_disabled:
            return error_dialog(self,_('Plugin cannot be disabled'),
                         _('The plugin: %s cannot be disabled')%plugin.name, show=True)
        if is_disabled(plugin):
            enable_plugin(plugin)
        else:
            disable_plugin(plugin)
        self.model.refresh_plugin(display_plugin)

    def _read_version_history_html(self, forum_link):
        br = browser()
        br.set_handle_gzip(True)
        try:
            raw = br.open_novisit(forum_link).read()
            if not raw:
                return None
        except:
            traceback.print_exc()
            return None
        raw = raw.decode('utf-8', errors='replace')
        root = html.fromstring(raw)
        spoiler_nodes = root.xpath('//div[@class="smallfont" and strong="Spoiler"]')
        for spoiler_node in spoiler_nodes:
            try:
                if spoiler_node.getprevious() is None:
                    # This is a spoiler node that has been indented using [INDENT]
                    # Need to go up to parent div, then previous node to get header
                    heading_node = spoiler_node.getparent().getprevious()
                else:
                    # This is a spoiler node after a BR tag from the heading
                    heading_node = spoiler_node.getprevious().getprevious()
                if heading_node is None:
                    continue
                if heading_node.text_content().lower().find('version history') != -1:
                    div_node = spoiler_node.xpath('div')[0]
                    text = html.tostring(div_node, method='html', encoding=unicode)
                    return re.sub('<div\s.*?>', '<div>', text)
            except:
                if DEBUG:
                    prints('======= MobileRead Parse Error =======')
                    traceback.print_exc()
                    prints(html.tostring(spoiler_node))
        return None

    def _download_zip(self, plugin_zip_url):
        from calibre.ptempfile import PersistentTemporaryFile
        br = browser(user_agent='%s %s' % (__appname__, __version__))
        raw = br.open_novisit(plugin_zip_url).read()
        with PersistentTemporaryFile('.zip') as pt:
            pt.write(raw)
        return pt.name
コード例 #32
0
class PluginUpdaterDialog(SizePersistedDialog):

    initial_extra_size = QSize(350, 100)

    def __init__(self, gui, initial_filter=FILTER_UPDATE_AVAILABLE):
        SizePersistedDialog.__init__(self, gui, "Plugin Updater plugin:plugin updater dialog")
        self.gui = gui
        self.forum_link = None
        self.model = None
        self.do_restart = False
        self._initialize_controls()
        self._create_context_menu()

        display_plugins = read_available_plugins()

        if display_plugins:
            self.model = DisplayPluginModel(display_plugins)
            self.proxy_model = DisplayPluginSortFilterModel(self)
            self.proxy_model.setSourceModel(self.model)
            self.plugin_view.setModel(self.proxy_model)
            self.plugin_view.resizeColumnsToContents()
            self.plugin_view.selectionModel().currentRowChanged.connect(self._plugin_current_changed)
            self.plugin_view.doubleClicked.connect(self.install_button.click)
            self.filter_combo.setCurrentIndex(initial_filter)
            self._select_and_focus_view()
        else:
            error_dialog(
                self.gui,
                _("Update Check Failed"),
                _("Unable to reach the MobileRead plugins forum index page."),
                det_msg=MR_INDEX_URL,
                show=True,
            )
            self.filter_combo.setEnabled(False)
        # Cause our dialog size to be restored from prefs or created on first usage
        self.resize_dialog()

    def _initialize_controls(self):
        self.setWindowTitle(_("User plugins"))
        self.setWindowIcon(QIcon(I("plugins/plugin_updater.png")))
        layout = QVBoxLayout(self)
        self.setLayout(layout)
        title_layout = ImageTitleLayout(self, "plugins/plugin_updater.png", _("User Plugins"))
        layout.addLayout(title_layout)

        header_layout = QHBoxLayout()
        layout.addLayout(header_layout)
        self.filter_combo = PluginFilterComboBox(self)
        self.filter_combo.setMinimumContentsLength(20)
        self.filter_combo.currentIndexChanged[int].connect(self._filter_combo_changed)
        header_layout.addWidget(QLabel(_("Filter list of plugins") + ":", self))
        header_layout.addWidget(self.filter_combo)
        header_layout.addStretch(10)

        self.plugin_view = QTableView(self)
        self.plugin_view.horizontalHeader().setStretchLastSection(True)
        self.plugin_view.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.plugin_view.setSelectionMode(QAbstractItemView.SingleSelection)
        self.plugin_view.setAlternatingRowColors(True)
        self.plugin_view.setSortingEnabled(True)
        self.plugin_view.setIconSize(QSize(28, 28))
        layout.addWidget(self.plugin_view)

        details_layout = QHBoxLayout()
        layout.addLayout(details_layout)
        forum_label = QLabel('<a href="http://www.foo.com/">Plugin Forum Thread</a>', self)
        forum_label.setTextInteractionFlags(Qt.LinksAccessibleByMouse | Qt.LinksAccessibleByKeyboard)
        forum_label.linkActivated.connect(self._forum_label_activated)
        details_layout.addWidget(QLabel(_("Description") + ":", self), 0, Qt.AlignLeft)
        details_layout.addWidget(forum_label, 1, Qt.AlignRight)

        self.description = QLabel(self)
        self.description.setFrameStyle(QFrame.Panel | QFrame.Sunken)
        self.description.setAlignment(Qt.AlignTop | Qt.AlignLeft)
        self.description.setMinimumHeight(40)
        self.description.setWordWrap(True)
        layout.addWidget(self.description)

        self.button_box = QDialogButtonBox(QDialogButtonBox.Close)
        self.button_box.rejected.connect(self.reject)
        self.finished.connect(self._finished)
        self.install_button = self.button_box.addButton(_("&Install"), QDialogButtonBox.AcceptRole)
        self.install_button.setToolTip(_("Install the selected plugin"))
        self.install_button.clicked.connect(self._install_clicked)
        self.install_button.setEnabled(False)
        self.configure_button = self.button_box.addButton(
            " " + _("&Customize plugin ") + " ", QDialogButtonBox.ResetRole
        )
        self.configure_button.setToolTip(_("Customize the options for this plugin"))
        self.configure_button.clicked.connect(self._configure_clicked)
        self.configure_button.setEnabled(False)
        layout.addWidget(self.button_box)

    def _create_context_menu(self):
        self.plugin_view.setContextMenuPolicy(Qt.ActionsContextMenu)
        self.install_action = QAction(QIcon(I("plugins/plugin_upgrade_ok.png")), _("&Install"), self)
        self.install_action.setToolTip(_("Install the selected plugin"))
        self.install_action.triggered.connect(self._install_clicked)
        self.install_action.setEnabled(False)
        self.plugin_view.addAction(self.install_action)
        self.history_action = QAction(QIcon(I("chapters.png")), _("Version &History"), self)
        self.history_action.setToolTip(_("Show history of changes to this plugin"))
        self.history_action.triggered.connect(self._history_clicked)
        self.history_action.setEnabled(False)
        self.plugin_view.addAction(self.history_action)
        self.forum_action = QAction(QIcon(I("plugins/mobileread.png")), _("Plugin &Forum Thread"), self)
        self.forum_action.triggered.connect(self._forum_label_activated)
        self.forum_action.setEnabled(False)
        self.plugin_view.addAction(self.forum_action)

        sep1 = QAction(self)
        sep1.setSeparator(True)
        self.plugin_view.addAction(sep1)

        self.toggle_enabled_action = QAction(_("Enable/&Disable plugin"), self)
        self.toggle_enabled_action.setToolTip(_("Enable or disable this plugin"))
        self.toggle_enabled_action.triggered.connect(self._toggle_enabled_clicked)
        self.toggle_enabled_action.setEnabled(False)
        self.plugin_view.addAction(self.toggle_enabled_action)
        self.uninstall_action = QAction(_("&Remove plugin"), self)
        self.uninstall_action.setToolTip(_("Uninstall the selected plugin"))
        self.uninstall_action.triggered.connect(self._uninstall_clicked)
        self.uninstall_action.setEnabled(False)
        self.plugin_view.addAction(self.uninstall_action)

        sep2 = QAction(self)
        sep2.setSeparator(True)
        self.plugin_view.addAction(sep2)

        self.donate_enabled_action = QAction(QIcon(I("donate.png")), _("Donate to developer"), self)
        self.donate_enabled_action.setToolTip(_("Donate to the developer of this plugin"))
        self.donate_enabled_action.triggered.connect(self._donate_clicked)
        self.donate_enabled_action.setEnabled(False)
        self.plugin_view.addAction(self.donate_enabled_action)

        sep3 = QAction(self)
        sep3.setSeparator(True)
        self.plugin_view.addAction(sep3)

        self.configure_action = QAction(QIcon(I("config.png")), _("&Customize plugin"), self)
        self.configure_action.setToolTip(_("Customize the options for this plugin"))
        self.configure_action.triggered.connect(self._configure_clicked)
        self.configure_action.setEnabled(False)
        self.plugin_view.addAction(self.configure_action)

    def _finished(self, *args):
        if self.model:
            update_plugins = filter(filter_upgradeable_plugins, self.model.display_plugins)
            self.gui.recalc_update_label(len(update_plugins))

    def _plugin_current_changed(self, current, previous):
        if current.isValid():
            actual_idx = self.proxy_model.mapToSource(current)
            display_plugin = self.model.display_plugins[actual_idx.row()]
            self.description.setText(display_plugin.description)
            self.forum_link = display_plugin.forum_link
            self.forum_action.setEnabled(bool(self.forum_link))
            self.install_button.setEnabled(display_plugin.is_valid_to_install())
            self.install_action.setEnabled(self.install_button.isEnabled())
            self.uninstall_action.setEnabled(display_plugin.is_installed())
            self.history_action.setEnabled(display_plugin.has_changelog)
            self.configure_button.setEnabled(display_plugin.is_installed())
            self.configure_action.setEnabled(self.configure_button.isEnabled())
            self.toggle_enabled_action.setEnabled(display_plugin.is_installed())
            self.donate_enabled_action.setEnabled(bool(display_plugin.donation_link))
        else:
            self.description.setText("")
            self.forum_link = None
            self.forum_action.setEnabled(False)
            self.install_button.setEnabled(False)
            self.install_action.setEnabled(False)
            self.uninstall_action.setEnabled(False)
            self.history_action.setEnabled(False)
            self.configure_button.setEnabled(False)
            self.configure_action.setEnabled(False)
            self.toggle_enabled_action.setEnabled(False)
            self.donate_enabled_action.setEnabled(False)

    def _donate_clicked(self):
        plugin = self._selected_display_plugin()
        if plugin and plugin.donation_link:
            open_url(QUrl(plugin.donation_link))

    def _select_and_focus_view(self, change_selection=True):
        if change_selection and self.plugin_view.model().rowCount() > 0:
            self.plugin_view.selectRow(0)
        else:
            idx = self.plugin_view.selectionModel().currentIndex()
            self._plugin_current_changed(idx, 0)
        self.plugin_view.setFocus()

    def _filter_combo_changed(self, idx):
        self.proxy_model.set_filter_criteria(idx)
        if idx == FILTER_NOT_INSTALLED:
            self.plugin_view.sortByColumn(5, Qt.DescendingOrder)
        else:
            self.plugin_view.sortByColumn(0, Qt.AscendingOrder)
        self._select_and_focus_view()

    def _forum_label_activated(self):
        if self.forum_link:
            open_url(QUrl(self.forum_link))

    def _selected_display_plugin(self):
        idx = self.plugin_view.selectionModel().currentIndex()
        actual_idx = self.proxy_model.mapToSource(idx)
        return self.model.display_plugins[actual_idx.row()]

    def _uninstall_plugin(self, name_to_remove):
        if DEBUG:
            prints("Removing plugin: ", name_to_remove)
        remove_plugin(name_to_remove)
        # Make sure that any other plugins that required this plugin
        # to be uninstalled first have the requirement removed
        for display_plugin in self.model.display_plugins:
            # Make sure we update the status and display of the
            # plugin we just uninstalled
            if name_to_remove in display_plugin.uninstall_plugins:
                if DEBUG:
                    prints("Removing uninstall dependency for: ", display_plugin.name)
                display_plugin.uninstall_plugins.remove(name_to_remove)
            if display_plugin.name == name_to_remove:
                if DEBUG:
                    prints("Resetting plugin to uninstalled status: ", display_plugin.name)
                display_plugin.installed_version = None
                display_plugin.plugin = None
                display_plugin.uninstall_plugins = []
                if self.proxy_model.filter_criteria not in [FILTER_INSTALLED, FILTER_UPDATE_AVAILABLE]:
                    self.model.refresh_plugin(display_plugin)

    def _uninstall_clicked(self):
        display_plugin = self._selected_display_plugin()
        if not question_dialog(
            self,
            _("Are you sure?"),
            "<p>" + _("Are you sure you want to uninstall the <b>%s</b> plugin?") % display_plugin.name,
            show_copy_button=False,
        ):
            return
        self._uninstall_plugin(display_plugin.name)
        if self.proxy_model.filter_criteria in [FILTER_INSTALLED, FILTER_UPDATE_AVAILABLE]:
            self.model.reset()
            self._select_and_focus_view()
        else:
            self._select_and_focus_view(change_selection=False)

    def _install_clicked(self):
        display_plugin = self._selected_display_plugin()
        if not question_dialog(
            self,
            _("Install %s") % display_plugin.name,
            "<p>"
            + _(
                "Installing plugins is a <b>security risk</b>. "
                "Plugins can contain a virus/malware. "
                "Only install it if you got it from a trusted source."
                " Are you sure you want to proceed?"
            ),
            show_copy_button=False,
        ):
            return

        if display_plugin.uninstall_plugins:
            uninstall_names = list(display_plugin.uninstall_plugins)
            if DEBUG:
                prints("Uninstalling plugin: ", ", ".join(uninstall_names))
            for name_to_remove in uninstall_names:
                self._uninstall_plugin(name_to_remove)

        if DEBUG:
            prints("Locating zip file for %s: %s" % (display_plugin.name, display_plugin.forum_link))
        self.gui.status_bar.showMessage(
            _("Locating zip file for %(name)s: %(link)s")
            % dict(name=display_plugin.name, link=display_plugin.forum_link)
        )
        plugin_zip_url = self._read_zip_attachment_url(display_plugin.forum_link)
        if not plugin_zip_url:
            return error_dialog(
                self.gui,
                _("Install Plugin Failed"),
                _("Unable to locate a plugin zip file for <b>%s</b>") % display_plugin.name,
                det_msg=display_plugin.forum_link,
                show=True,
            )

        if DEBUG:
            prints("Downloading plugin zip attachment: ", plugin_zip_url)
        self.gui.status_bar.showMessage(_("Downloading plugin zip attachment: %s") % plugin_zip_url)
        zip_path = self._download_zip(plugin_zip_url)

        if DEBUG:
            prints("Installing plugin: ", zip_path)
        self.gui.status_bar.showMessage(_("Installing plugin: %s") % zip_path)

        do_restart = False
        try:
            try:
                plugin = add_plugin(zip_path)
            except NameConflict as e:
                return error_dialog(self.gui, _("Already exists"), unicode(e), show=True)
            # Check for any toolbars to add to.
            widget = ConfigWidget(self.gui)
            widget.gui = self.gui
            widget.check_for_add_to_toolbars(plugin)
            self.gui.status_bar.showMessage(_("Plugin installed: %s") % display_plugin.name)
            d = info_dialog(
                self.gui,
                _("Success"),
                _(
                    "Plugin <b>{0}</b> successfully installed under <b>"
                    " {1} plugins</b>. You may have to restart calibre "
                    "for the plugin to take effect."
                ).format(plugin.name, plugin.type),
                show_copy_button=False,
            )
            b = d.bb.addButton(_("Restart calibre now"), d.bb.AcceptRole)
            b.setIcon(QIcon(I("lt.png")))
            d.do_restart = False

            def rf():
                d.do_restart = True

            b.clicked.connect(rf)
            d.set_details("")
            d.exec_()
            b.clicked.disconnect()
            do_restart = d.do_restart

            display_plugin.plugin = plugin
            # We cannot read the 'actual' version information as the plugin will not be loaded yet
            display_plugin.installed_version = display_plugin.available_version
        except:
            if DEBUG:
                prints("ERROR occurred while installing plugin: %s" % display_plugin.name)
                traceback.print_exc()
            error_dialog(
                self.gui,
                _("Install Plugin Failed"),
                _(
                    "A problem occurred while installing this plugin."
                    " This plugin will now be uninstalled."
                    " Please post the error message in details below into"
                    " the forum thread for this plugin and restart Calibre."
                ),
                det_msg=traceback.format_exc(),
                show=True,
            )
            if DEBUG:
                prints("Due to error now uninstalling plugin: %s" % display_plugin.name)
                remove_plugin(display_plugin.name)
                display_plugin.plugin = None

        display_plugin.uninstall_plugins = []
        if self.proxy_model.filter_criteria in [FILTER_NOT_INSTALLED, FILTER_UPDATE_AVAILABLE]:
            self.model.reset()
            self._select_and_focus_view()
        else:
            self.model.refresh_plugin(display_plugin)
            self._select_and_focus_view(change_selection=False)
        if do_restart:
            self.do_restart = True
            self.accept()

    def _history_clicked(self):
        display_plugin = self._selected_display_plugin()
        text = self._read_version_history_html(display_plugin.forum_link)
        if text:
            dlg = VersionHistoryDialog(self, display_plugin.name, text)
            dlg.exec_()
        else:
            return error_dialog(
                self,
                _("Version history missing"),
                _("Unable to find the version history for %s") % display_plugin.name,
                show=True,
            )

    def _configure_clicked(self):
        display_plugin = self._selected_display_plugin()
        plugin = display_plugin.plugin
        if not plugin.is_customizable():
            return info_dialog(
                self, _("Plugin not customizable"), _("Plugin: %s does not need customization") % plugin.name, show=True
            )
        from calibre.customize import InterfaceActionBase

        if isinstance(plugin, InterfaceActionBase) and not getattr(plugin, "actual_iaction_plugin_loaded", False):
            return error_dialog(
                self,
                _("Must restart"),
                _("You must restart calibre before you can" " configure the <b>%s</b> plugin") % plugin.name,
                show=True,
            )
        plugin.do_user_config(self.parent())

    def _toggle_enabled_clicked(self):
        display_plugin = self._selected_display_plugin()
        plugin = display_plugin.plugin
        if not plugin.can_be_disabled:
            return error_dialog(
                self, _("Plugin cannot be disabled"), _("The plugin: %s cannot be disabled") % plugin.name, show=True
            )
        if is_disabled(plugin):
            enable_plugin(plugin)
        else:
            disable_plugin(plugin)
        self.model.refresh_plugin(display_plugin)

    def _read_version_history_html(self, forum_link):
        br = browser()
        br.set_handle_gzip(True)
        try:
            raw = br.open_novisit(forum_link).read()
            if not raw:
                return None
        except:
            traceback.print_exc()
            return None
        raw = raw.decode("utf-8", errors="replace")
        root = html.fromstring(raw)
        spoiler_nodes = root.xpath('//div[@class="smallfont" and strong="Spoiler"]')
        for spoiler_node in spoiler_nodes:
            try:
                if spoiler_node.getprevious() is None:
                    # This is a spoiler node that has been indented using [INDENT]
                    # Need to go up to parent div, then previous node to get header
                    heading_node = spoiler_node.getparent().getprevious()
                else:
                    # This is a spoiler node after a BR tag from the heading
                    heading_node = spoiler_node.getprevious().getprevious()
                if heading_node is None:
                    continue
                if heading_node.text_content().lower().find("version history") != -1:
                    div_node = spoiler_node.xpath("div")[0]
                    text = html.tostring(div_node, method="html", encoding=unicode)
                    return re.sub("<div\s.*?>", "<div>", text)
            except:
                if DEBUG:
                    prints("======= MobileRead Parse Error =======")
                    traceback.print_exc()
                    prints(html.tostring(spoiler_node))
        return None

    def _read_zip_attachment_url(self, forum_link):
        br = browser()
        br.set_handle_gzip(True)
        try:
            raw = br.open_novisit(forum_link).read()
            if not raw:
                return None
        except:
            traceback.print_exc()
            return None
        raw = raw.decode("utf-8", errors="replace")
        root = html.fromstring(raw)
        attachment_nodes = root.xpath("//fieldset/table/tr/td/a")
        for attachment_node in attachment_nodes:
            try:
                filename = attachment_node.text_content().lower()
                if filename.find(".zip") != -1:
                    full_url = MR_URL + attachment_node.attrib["href"]
                    return full_url
            except:
                if DEBUG:
                    prints("======= MobileRead Parse Error =======")
                    traceback.print_exc()
                    prints(html.tostring(attachment_node))
        return None

    def _download_zip(self, plugin_zip_url):
        from calibre.ptempfile import PersistentTemporaryFile

        br = browser()
        br.set_handle_gzip(True)
        raw = br.open_novisit(plugin_zip_url).read()
        pt = PersistentTemporaryFile(".zip")
        pt.write(raw)
        pt.close()
        return pt.name
コード例 #33
0
ファイル: PM_Dialog.py プロジェクト: elfion/nanoengineer
class PM_Dialog( QDialog, SponsorableMixin ):
    """
    The PM_Dialog class is the base class for Property Manager dialogs.
    
    [To make a PM class from this superclass, subclass it to customize
    the widget set and add behavior.
    You must also provide certain methods that used to be provided by
    GeneratorBaseClass, including ok_btn_clicked and several others,
    including at least some defined by SponsorableMixin (open_sponsor_homepage,
    setSponsor).
    This set of requirements may be cleaned up.]
    """
    
    headerTitleText  = ""  # The header title text.
    
    _widgetList = [] # A list of all group boxes in this PM dialog, 
                     # including the message group box
                     # (but not header, sponsor button, etc.)
                     
    _groupBoxCount = 0 # Number of PM_GroupBoxes in this PM dialog
    
    _lastGroupBox = None # The last PM_GroupBox in this PM dialog
                         # (i.e. the most recent PM_GroupBox added)
    
    def __init__(self, 
                 name,
                 iconPath = "",
                 title    = ""
                 ):
        """
        Property Manager constructor.
        
        @param name: the name to assign the property manager dialog object.
        @type  name: str
        
        @param iconPath: the relative path for the icon (PNG image) that 
                         appears in the header.
        @type  iconPath: str
        
        @param title: the title that appears in the header.
        @type  title: str
        """
        
        QDialog.__init__(self)
        
        self.setObjectName(name)
        self._widgetList = [] 
        
        # Main pallete for PropMgr.
        
        self.setPalette(QPalette(pmColor))
        
        # Main vertical layout for PropMgr.
        self.vBoxLayout = QVBoxLayout(self)
        self.vBoxLayout.setMargin(PM_MAINVBOXLAYOUT_MARGIN)
        self.vBoxLayout.setSpacing(PM_MAINVBOXLAYOUT_SPACING)

        # Add PropMgr's header, sponsor button, top row buttons and (hidden) 
        # message group box.
        self._createHeader(iconPath, title)
        self._createSponsorButton()
        self._createTopRowBtns() # Create top buttons row
        
        self.MessageGroupBox = PM_MessageGroupBox(self)
        
        # Keep the line below around; it might be useful.
        # I may want to use it now that I understand it.
        # Mark 2007-05-17.
        #QMetaObject.connectSlotsByName(self)
        
        self._addGroupBoxes()
        
                
        try:
            self._addWhatsThisText()
        except:
            print_compact_traceback("Error loading whatsthis text for this "
                                    "property manager: ")
        
        try:
            self._addToolTipText()
        except:
            print_compact_traceback("Error loading tool tip text for this "
                                    "property manager: ")            
            
        #The following attr is used for comparison in method
        #'_update_UI_wanted_as_something_changed'
        self._previous_all_change_indicators = None
        

    def update_UI(self):
        """
        Update whatever is shown in this PM based on current state
        of the rest of the system, especially the state of self.command
        and of the model it shows.

        This is part of the PM API required by baseCommand,
        since it's called by baseCommand.command_update_UI.
        
        @note: Overridden in Command_PropertyManager, but should not be
               overridden in its subclasses. See that method's docstring
               for details.
        """
        #bruce 081125 defined this here, to fix bugs in example commands
        return
    
    def keyPressEvent(self, event):
        """
        Handles keyPress event. 
        
        @note: Subclasses should carefully override this. 
        Note that the default implementation doesn't permit ESC key 
        as a way to close the PM_dialog. (This is typically desirable
        for Property Managers.) If any subclass needs to implement the key press, 
        they should first call this method (i.e. superclass.keyPressEvent) and then 
        implement specific code that closes the dialog when ESC key is pressed.
        """
        key = event.key()
        # Don't use ESC key to close the PM dialog. Fixes bug 2596
        if key == Qt.Key_Escape:
            pass
        else:
            QDialog.keyPressEvent(self, event) 
        return
                                    
    
    def _addGroupBoxes(self):
        """
        Add various group boxes to this PM. Subclasses should override this
        method.
        """
        pass

    def _addWhatsThisText(self):
        """
        Add what's this text. 
        Subclasses should override this method. 
        """
        pass
    
    def _addToolTipText(self):
        """
        Add Tool tip text. 
        Subclasses should override this method. 
        """
        pass
    
    
    def show(self):
        """
        Shows the Property Manager.
        """
        self.setSponsor()
        
        # Show or hide the sponsor logo based on whether the user gave 
        # permission to download sponsor logos.
        if env.prefs[sponsor_download_permission_prefs_key]:
            self.sponsorButtonContainer.show()
        else:
            self.sponsorButtonContainer.hide()
        
        if not self.pw or self:            
            self.pw = self.win.activePartWindow()
            
        self.pw.updatePropertyManagerTab(self)
        self.pw.pwProjectTabWidget.setCurrentIndex(
            self.pw.pwProjectTabWidget.indexOf(self))
        
        # Show the default message whenever we open the Property Manager.
        self.MessageGroupBox.MessageTextEdit.restoreDefault()
        
    def open(self, pm):
        """
        Closes the current property manager (if any) and opens the 
        property manager I{pm}.
        
        @param pm: The property manager to open.
        @type  pm: L{PM_Dialog} or QDialog (of legacy PMs)
        
        @attention: This method is a temporary workaround for "Insert > Plane".
                    The current command should always be responsible for 
                    (re)opening its own PM via self.show().
                    
        @see: L{show()}
        """
        if 1:
            commandSequencer = self.win.commandSequencer #bruce 071008
            commandName = commandSequencer.currentCommand.commandName
                # that's an internal name, but this is just for a debug print
            print "PM_Dialog.open(): Reopening the PM for command:", commandName
        
        # The following line of code is buggy when you, for instance, exit a PM
        # and reopen the previous one. It sends the disconnect signal twice to 
        # the PM that is just closed.So disabling this line -- Ninad 2007-12-04
        
        ##self.close() # Just in case there is another PM open.

        self.pw = self.win.activePartWindow()         
        self.pw.updatePropertyManagerTab(pm)
        try:
            pm.setSponsor()
        except:
            print """PM_Dialog.open(): pm has no attribute 'setSponsor()'  
                     ignoring."""
        self.pw.pwProjectTabWidget.setCurrentIndex(
            self.pw.pwProjectTabWidget.indexOf(pm))
        
    def close(self):
        """
        Closes the Property Manager.
        """
        if not self.pw:
            self.pw = self.win.activePartWindow() 
        self.pw.pwProjectTabWidget.setCurrentIndex(0)
        
        ## try: [bruce 071018 moved this lower, since errmsg only covers attr]
        pmWidget = self.pw.propertyManagerScrollArea.widget()
        if debug_flags.atom_debug: #bruce 071018
            "atom_debug fyi: %r is closing %r (can they differ?)" % \
                        (self, pmWidget)
        try:
            pmWidget.update_props_if_needed_before_closing
        except AttributeError:
            if 1 or debug_flags.atom_debug:
                msg1 = "Last PropMgr %r doesn't have method" % pmWidget
                msg2 = " update_props_if_needed_before_closing. That's"
                msg3 = " OK (for now, only implemented for Plane PM). "
                msg4 = "Ignoring Exception: "
                print_compact_traceback(msg1 + msg2 + msg3 + msg4)
                #bruce 071018: I'll define that method in PM_Dialog
                # so this message should become rare or nonexistent,
                # so I'll make it happen whether or not atom_debug.
        else:
            pmWidget.update_props_if_needed_before_closing()
                    
        self.pw.pwProjectTabWidget.removeTab(
            self.pw.pwProjectTabWidget.indexOf(
                self.pw.propertyManagerScrollArea))
        
        if self.pw.propertyManagerTab:
            self.pw.propertyManagerTab = None

    def update_props_if_needed_before_closing(self):
        # bruce 071018 default implem
        """
        Subclasses can override this to update some cosmetic properties
        of their associated model objects before closing self
        (the Property Manager).
        """
        pass
    
    def updateMessage(self, msg = ''):
        """
        Updates the message box with an informative message
        @param msg: Message to be displayed in the Message groupbox of 
                        the property manager
        @type  msg: string
        """
        self.MessageGroupBox.insertHtmlMessage(msg, 
                                               setAsDefault = False,
                                               minLines     = 5) 
        
    def _createHeader(self, iconPath, title):
        """
        Creates the Property Manager header, which contains an icon
        (a QLabel with a pixmap) and white text (a QLabel with text).
        
        @param iconPath: The relative path for the icon (PNG image) that 
                         appears in the header.
        @type  iconPath: str
        
        @param title: The title that appears in the header.
        @type  title: str
        """
        
        # Heading frame (dark gray), which contains 
        # a pixmap and (white) heading text.
        self.headerFrame = QFrame(self)
        self.headerFrame.setFrameShape(QFrame.NoFrame)
        self.headerFrame.setFrameShadow(QFrame.Plain)
        
        self.headerFrame.setPalette(QPalette(pmHeaderFrameColor))
        self.headerFrame.setAutoFillBackground(True)

        # HBox layout for heading frame, containing the pixmap
        # and label (title).
        HeaderFrameHLayout = QHBoxLayout(self.headerFrame)
        # 2 pixels around edges --
        HeaderFrameHLayout.setMargin(PM_HEADER_FRAME_MARGIN) 
        # 5 pixel between pixmap and label. --
        HeaderFrameHLayout.setSpacing(PM_HEADER_FRAME_SPACING) 

        # PropMgr icon. Set image by calling setHeaderIcon().
        self.headerIcon = QLabel(self.headerFrame)
        self.headerIcon.setSizePolicy(
            QSizePolicy(QSizePolicy.Policy(QSizePolicy.Fixed),
                              QSizePolicy.Policy(QSizePolicy.Fixed)))
            
        self.headerIcon.setScaledContents(True)
        
        HeaderFrameHLayout.addWidget(self.headerIcon)
        
        # PropMgr header title text (a QLabel).
        self.headerTitle = QLabel(self.headerFrame)
        headerTitlePalette = self._getHeaderTitlePalette()
        self.headerTitle.setPalette(headerTitlePalette)
        self.headerTitle.setAlignment(PM_LABEL_LEFT_ALIGNMENT)

        # Assign header title font.
        self.headerTitle.setFont(self._getHeaderFont())
        HeaderFrameHLayout.addWidget(self.headerTitle)
        
        self.vBoxLayout.addWidget(self.headerFrame)
        
        # Set header icon and title text.
        self.setHeaderIcon(iconPath)
        self.setHeaderTitle(title)
        
    def _getHeaderFont(self):
        """
        Returns the font used for the header.
        
        @return: the header font
        @rtype:  QFont
        """
        font = QFont()
        font.setFamily(PM_HEADER_FONT)
        font.setPointSize(PM_HEADER_FONT_POINT_SIZE)
        font.setBold(PM_HEADER_FONT_BOLD)
        return font
        
    def setHeaderTitle(self, title):
        """
        Set the Property Manager header title to string <title>.
        
        @param title: the title to insert in the header.
        @type  title: str
        """
        self.headerTitleText = title
        self.headerTitle.setText(title)
    
    def setHeaderIcon(self, iconPath):
        """
        Set the Property Manager header icon.
        
        @param iconPath: the relative path to the PNG file containing the 
                         icon image.
        @type  iconPath: str
        """
        
        if not iconPath:
            return
        
        self.headerIcon.setPixmap(getpixmap(iconPath))
        
    def _createSponsorButton(self):
        """
        Creates the Property Manager sponsor button, which contains
        a QPushButton inside of a QGridLayout inside of a QFrame.
        The sponsor logo image is not loaded here.
        """
        
        # Sponsor button (inside a frame)
        self.sponsorButtonContainer = QWidget(self)

        SponsorFrameGrid = QGridLayout(self.sponsorButtonContainer)
        SponsorFrameGrid.setMargin(PM_SPONSOR_FRAME_MARGIN)
        SponsorFrameGrid.setSpacing(PM_SPONSOR_FRAME_SPACING) # Has no effect.

        self.sponsor_btn = QToolButton(self.sponsorButtonContainer)
        self.sponsor_btn.setAutoRaise(True)
        self.connect(self.sponsor_btn,
                     SIGNAL("clicked()"),
                     self.open_sponsor_homepage)
        
        SponsorFrameGrid.addWidget(self.sponsor_btn, 0, 0, 1, 1)
        
        self.vBoxLayout.addWidget(self.sponsorButtonContainer)

        button_whatsthis_widget = self.sponsor_btn
        #bruce 070615 bugfix -- put tooltip & whatsthis on self.sponsor_btn, 
        # not self.
        # [self.sponsorButtonContainer might be another possible place to put them.]
        
        button_whatsthis_widget.setWhatsThis("""<b>Sponsor Button</b>
            <p>When clicked, this sponsor logo will display a short 
            description about a NanoEngineer-1 sponsor. This can 
            be an official sponsor or credit given to a contributor 
            that has helped code part or all of this command. 
            A link is provided in the description to learn more 
            about this sponsor.</p>""")
        
        button_whatsthis_widget.setToolTip("NanoEngineer-1 Sponsor Button")
        
        return

    def _createTopRowBtns(self):
        """
        Creates the Done, Cancel, Preview, Restore Defaults and What's This 
        buttons row at the top of the Property Manager.
        """        
        topBtnSize = QSize(22, 22) # button images should be 16 x 16, though.
        
        # Main "button group" widget (but it is not a QButtonGroup).
        self.pmTopRowBtns = QHBoxLayout()
        # This QHBoxLayout is (probably) not necessary. Try using just the frame
        # for the foundation. I think it should work. Mark 2007-05-30
        
        # Horizontal spacer
        horizontalSpacer = QSpacerItem(1, 1, 
                                QSizePolicy.Expanding, 
                                QSizePolicy.Minimum)
        
        # Widget containing all the buttons.
        self.topRowBtnsContainer = QWidget()
        
        # Create Hbox layout for main frame.
        topRowBtnsHLayout = QHBoxLayout(self.topRowBtnsContainer)
        topRowBtnsHLayout.setMargin(PM_TOPROWBUTTONS_MARGIN)
        topRowBtnsHLayout.setSpacing(PM_TOPROWBUTTONS_SPACING)
        
        # Set to True to center align the buttons in the PM
        if False: # Left aligns the buttons.
            topRowBtnsHLayout.addItem(horizontalSpacer)
        
        # Done (OK) button.
        self.done_btn = QToolButton(self.topRowBtnsContainer)
        self.done_btn.setIcon(
            geticon("ui/actions/Properties Manager/Done_16x16.png"))
        self.done_btn.setIconSize(topBtnSize)  
        self.done_btn.setAutoRaise(True) 
        self.connect(self.done_btn,
                     SIGNAL("clicked()"),
                     self.doneButtonClicked)
        self.done_btn.setToolTip("Done")
        
        topRowBtnsHLayout.addWidget(self.done_btn)
        
        # Cancel (Abort) button.
        self.cancel_btn = QToolButton(self.topRowBtnsContainer)
        self.cancel_btn.setIcon(
            geticon("ui/actions/Properties Manager/Abort_16x16.png"))
        self.cancel_btn.setIconSize(topBtnSize) 
        self.cancel_btn.setAutoRaise(True) 
        self.connect(self.cancel_btn,
                     SIGNAL("clicked()"),
                     self.cancelButtonClicked)
        self.cancel_btn.setToolTip("Cancel")
        
        topRowBtnsHLayout.addWidget(self.cancel_btn)
        
        #@ abort_btn deprecated. We still need it because modes use it. 
        self.abort_btn = self.cancel_btn
        
        # Restore Defaults button.
        self.restore_defaults_btn = QToolButton(self.topRowBtnsContainer)
        self.restore_defaults_btn.setIcon(
            geticon("ui/actions/Properties Manager/Restore_16x16.png"))
        self.restore_defaults_btn.setIconSize(topBtnSize) 
        self.restore_defaults_btn.setAutoRaise(True) 
        self.connect(self.restore_defaults_btn,
                     SIGNAL("clicked()"),
                     self.restoreDefaultsButtonClicked)
        self.restore_defaults_btn.setToolTip("Restore Defaults")
        topRowBtnsHLayout.addWidget(self.restore_defaults_btn)
        
        # Preview (glasses) button.
        self.preview_btn = QToolButton(self.topRowBtnsContainer)
        self.preview_btn.setIcon(
            geticon("ui/actions/Properties Manager/Preview_16x16.png"))
        self.preview_btn.setIconSize(topBtnSize) 
        self.preview_btn.setAutoRaise(True) 
        self.connect(self.preview_btn,
                     SIGNAL("clicked()"),
                     self.previewButtonClicked)
        self.preview_btn.setToolTip("Preview")
        
        topRowBtnsHLayout.addWidget(self.preview_btn)        
        
        # What's This (?) button.
        self.whatsthis_btn = QToolButton(self.topRowBtnsContainer)
        self.whatsthis_btn.setIcon(
            geticon("ui/actions/Properties Manager/WhatsThis_16x16.png"))
        self.whatsthis_btn.setIconSize(topBtnSize) 
        self.whatsthis_btn.setAutoRaise(True) 
        self.connect(self.whatsthis_btn,
                     SIGNAL("clicked()"),
                     self.whatsThisButtonClicked)
        self.whatsthis_btn.setToolTip("Enter \"What's This\" help mode")
        
        topRowBtnsHLayout.addWidget(self.whatsthis_btn)
        
        topRowBtnsHLayout.addItem(horizontalSpacer)
        
        # Create Button Row
        self.pmTopRowBtns.addWidget(self.topRowBtnsContainer)
        
        self.vBoxLayout.addLayout(self.pmTopRowBtns)
        
        # Add What's This for buttons.
        
        self.done_btn.setWhatsThis("""<b>Done</b>
            <p>
            <img source=\"ui/actions/Properties Manager/Done_16x16.png\"><br>
            Completes and/or exits the current command.</p>""")
        
        self.cancel_btn.setWhatsThis("""<b>Cancel</b>
            <p>
            <img source=\"ui/actions/Properties Manager/Abort_16x16.png\"><br>
            Cancels the current command.</p>""")
        
        self.restore_defaults_btn.setWhatsThis("""<b>Restore Defaults</b>
            <p><img source=\"ui/actions/Properties Manager/Restore_16x16.png\"><br>
            Restores the defaut values of the Property Manager.</p>""")
        
        self.preview_btn.setWhatsThis("""<b>Preview</b>
            <p>
            <img source=\"ui/actions/Properties Manager/Preview_16x16.png\"><br>
            Preview the structure based on current Property Manager settings.
            </p>""")

        self.whatsthis_btn.setWhatsThis("""<b>What's This</b> 
            <p>
            <img source=\"ui/actions/Properties Manager/WhatsThis_16x16.png\"><br>
            This invokes \"What's This?\" help mode which is part of 
            NanoEngineer-1's online help system, and provides users with 
            information about the functionality and usage of a particular 
            command button or widget.
            </p>""")
        
        return

    def hideTopRowButtons(self, pmButtonFlags = None):
        """
        Hides one or more top row buttons using <pmButtonFlags>.
        Button flags not set will cause the button to be shown
        if currently hidden.
        
        @param pmButtonFlags: This enumerator describes the which buttons to 
                              hide, where:
        
            - PM_DONE_BUTTON            =  1
            - PM_CANCEL_BUTTON          =  2
            - PM_RESTORE_DEFAULTS_BUTTON =  4
            - PM_PREVIEW_BUTTON         =  8
            - PM_WHATS_THIS_BUTTON       = 16
            - PM_ALL_BUTTONS            = 31
            
        @type  pmButtonFlags: int
        """
        
        if pmButtonFlags & PM_DONE_BUTTON: 
            self.done_btn.hide()
        else: 
            self.done_btn.show()
            
        if pmButtonFlags & PM_CANCEL_BUTTON: 
            self.cancel_btn.hide()
        else: 
            self.cancel_btn.show()
            
        if pmButtonFlags & PM_RESTORE_DEFAULTS_BUTTON: 
            self.restore_defaults_btn.hide()
        else: 
            self.restore_defaults_btn.show()
            
        if pmButtonFlags & PM_PREVIEW_BUTTON: 
            self.preview_btn.hide()
        else: 
            self.preview_btn.show()
            
        if pmButtonFlags & PM_WHATS_THIS_BUTTON: 
            self.whatsthis_btn.hide()
        else: 
            self.whatsthis_btn.show()
        
    def showTopRowButtons(self, pmButtonFlags = PM_ALL_BUTTONS):
        """
        Shows one or more top row buttons using <pmButtonFlags>.
        Button flags not set will cause the button to be hidden
        if currently displayed.
        
        @param pmButtonFlags: this enumerator describes which buttons to 
        display, where:
        
            - PM_DONE_BUTTON            =  1
            - PM_CANCEL_BUTTON          =  2
            - PM_RESTORE_DEFAULTS_BUTTON =  4
            - PM_PREVIEW_BUTTON         =  8
            - PM_WHATS_THIS_BUTTON       = 16
            - PM_ALL_BUTTONS            = 31
            
        @type  pmButtonFlags: int
        """
        
        self.hideTopRowButtons(pmButtonFlags ^ PM_ALL_BUTTONS)
        
    def _getHeaderTitlePalette(self):
        """
        Return a palette for header title (text) label. 
        """
        palette = QPalette()
        palette.setColor(QPalette.WindowText, pmHeaderTitleColor)
        return palette
        
    def doneButtonClicked(self): # note: never overridden, as of 080815
        """
        Slot for the Done button.
        """
        self.ok_btn_clicked()
    
    def cancelButtonClicked(self): # note: never overridden, as of 080815
        """
        Slot for the Cancel button.
        """
        self.cancel_btn_clicked()
    
    def restoreDefaultsButtonClicked(self):
        """
        Slot for "Restore Defaults" button in the Property Manager.
        It is called each time the button is clicked.
        """
        for widget in self._widgetList:
            if isinstance(widget, PM_GroupBox):
                widget.restoreDefault()
                         
    def previewButtonClicked(self):
        """
        Slot for the Preview button.
        """
        self.preview_btn_clicked()
        
    def whatsThisButtonClicked(self):
        """
        Slot for the What's This button.
        """
        QWhatsThis.enterWhatsThisMode()

    # default implementations for subclasses
    # [bruce 080815 pulled these in from subclasses]

    def ok_btn_clicked(self):
        """
        Implements Done button. Called by its slot method in PM_Dialog.
        
        [subclasses can override as needed]
        """      
        self.win.toolsDone()

    def cancel_btn_clicked(self):
        """
        Implements Cancel button. Called by its slot method in PM_Dialog.

        [subclasses can override as needed]
        """  
        # Note: many subclasses override this to call self.w.toolsDone
        # (rather than toolsCancel). This should be cleaned up
        # so those overrides are not needed. (Maybe they are already
        # not needed.) [bruce 080815 comment]
        
        self.win.toolsCancel()

    pass
コード例 #34
0
ファイル: jobs.py プロジェクト: sss/calibre
class JobsButton(QFrame):  # {{{
    def __init__(self, horizontal=False, size=48, parent=None):
        QFrame.__init__(self, parent)
        if horizontal:
            size = 24
        self.pi = ProgressIndicator(self, size)
        self._jobs = QLabel('<b>' + _('Jobs:') + ' 0')
        self._jobs.mouseReleaseEvent = self.mouseReleaseEvent
        self.shortcut = _('Shift+Alt+J')

        if horizontal:
            self.setLayout(QHBoxLayout())
            self.layout().setDirection(self.layout().RightToLeft)
        else:
            self.setLayout(QVBoxLayout())
            self._jobs.setAlignment(Qt.AlignHCenter | Qt.AlignBottom)

        self.layout().addWidget(self.pi)
        self.layout().addWidget(self._jobs)
        if not horizontal:
            self.layout().setAlignment(self._jobs, Qt.AlignHCenter)
        self._jobs.setMargin(0)
        self.layout().setMargin(0)
        self._jobs.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
        self.setCursor(Qt.PointingHandCursor)
        b = _('Click to see list of jobs')
        self.setToolTip(b + u' (%s)' % self.shortcut)
        self.action_toggle = QAction(b, parent)
        parent.addAction(self.action_toggle)
        self.action_toggle.setShortcut(self.shortcut)
        self.action_toggle.triggered.connect(self.toggle)

    def initialize(self, jobs_dialog, job_manager):
        self.jobs_dialog = jobs_dialog
        job_manager.job_added.connect(self.job_added)
        job_manager.job_done.connect(self.job_done)
        self.jobs_dialog.addAction(self.action_toggle)

    def mouseReleaseEvent(self, event):
        self.toggle()

    def toggle(self, *args):
        if self.jobs_dialog.isVisible():
            self.jobs_dialog.hide()
        else:
            self.jobs_dialog.show()

    @property
    def is_running(self):
        return self.pi.isAnimated()

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

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

    def jobs(self):
        src = unicode(self._jobs.text())
        return int(re.search(r'\d+', src).group())

    def job_added(self, nnum):
        jobs = self._jobs
        src = unicode(jobs.text())
        num = self.jobs()
        text = src.replace(str(num), str(nnum))
        jobs.setText(text)
        self.start()

    def job_done(self, nnum):
        jobs = self._jobs
        src = unicode(jobs.text())
        num = self.jobs()
        text = src.replace(str(num), str(nnum))
        jobs.setText(text)
        if nnum == 0:
            self.no_more_jobs()

    def no_more_jobs(self):
        if self.is_running:
            self.stop()
            QCoreApplication.instance().alert(self, 5000)
コード例 #35
0
class PM_Dialog(QDialog, SponsorableMixin):
    """
    The PM_Dialog class is the base class for Property Manager dialogs.
    
    [To make a PM class from this mixin-superclass, subclass it to customize
    the widget set and add behavior.
    You must also provide certain methods provided by GeneratorBaseClass
    (either by inheriting it -- not sure if superclass order matters for that --
    or by defining them yourself), including ok_btn_clicked and several others,
    including at least some defined by SponsorableMixin (open_sponsor_homepage,
    setSponsor).
    This set of requirements may be cleaned up.]
    [Note: Technically, this is not a "base class" but a "mixin class".]    
    """

    headerTitleText = ""  # The header title text.

    _widgetList = []  # A list of all group boxes in this PM dialog,
    # including the message group box.
    # (but not header, sponsor button, etc.)
    _groupBoxCount = 0  # Number of PM_GroupBoxes in this PM dialog.
    _lastGroupBox = None  # The last PM_GroupBox in this PM dialog.

    # (i.e. the most recent PM_GroupBox added).

    def __init__(self, name, iconPath="", title=""):
        """
        Property Manager constructor.
        
        @param name: the name to assign the property manager dialog object.
        @type  name: str
        
        @param iconPath: the relative path for the icon (PNG image) that 
                         appears in the header.
        @type  iconPath: str
        
        @param title: the title that appears in the header.
        @type  title: str
        """

        QDialog.__init__(self)

        self.setObjectName(name)
        self._widgetList = []

        # Main pallete for PropMgr.

        self.setPalette(QPalette(pmColor))

        # Main vertical layout for PropMgr.
        self.vBoxLayout = QVBoxLayout(self)
        self.vBoxLayout.setMargin(PM_MAINVBOXLAYOUT_MARGIN)
        self.vBoxLayout.setSpacing(PM_MAINVBOXLAYOUT_SPACING)

        # Add PropMgr's header, sponsor button, top row buttons and (hidden)
        # message group box.
        self._createHeader(iconPath, title)
        self._createSponsorButton()
        self._createTopRowBtns()  # Create top buttons row

        self.MessageGroupBox = PM_MessageGroupBox(self)

        # Keep the line below around; it might be useful.
        # I may want to use it now that I understand it.
        # Mark 2007-05-17.
        #QMetaObject.connectSlotsByName(self)

        self._addGroupBoxes()

        try:
            self._addWhatsThisText()
        except:
            print_compact_traceback("Error loading whatsthis text for this " \
                                    "property manager.")

        try:
            self._addToolTipText()
        except:
            print_compact_traceback("Error loading tool tip text for this " \
                                    "property manager.")

    def keyPressEvent(self, event):
        """
        Handles keyPress event. 
        
        NOTE: 
        Subclasses should carefully override this. 
        Note that the default implementation  doesn't permit ESC key 
        as a way to close the PM_dialog. (this is typically dsesirable
        for Property Managers) If any subclass need to implement the key press, 
        they should first call this method(i.e. superclass.keyPressEvent) and then 
        implement specific code that closed the dialog when ESC key is pressed.
        """
        key = event.key()
        # Don't use ESC key to close the PM dialog. Fixes bug 2596
        if key == Qt.Key_Escape:
            pass
        else:
            QDialog.keyPressEvent(self, event)
        return

    def _addGroupBoxes(self):
        """
        Add various group boxes to this PM. Subclasses should override this 
        method. 
         
        """
        pass

    def _addWhatsThisText(self):
        """
        Add what's this text. 
        Subclasses should override this  method. 
        """
        pass

    def _addToolTipText(self):
        """
        Add Tool tip text. 
        Subclasses should override this  method. 
        """
        pass

    def show(self):
        """
        Shows the Property Manager.
        """
        self.setSponsor()

        if not self.pw or self:
            self.pw = self.win.activePartWindow()

        self.pw.updatePropertyManagerTab(self)
        self.pw.pwProjectTabWidget.setCurrentIndex(
            self.pw.pwProjectTabWidget.indexOf(self))

        # Show the default message whenever we open the Property Manager.
        self.MessageGroupBox.MessageTextEdit.restoreDefault()

    def open(self, pm):
        """
        Closes the current property manager (if any) and opens the 
        property manager I{pm}.
        
        @param pm: The property manager to open.
        @type  pm: L{PM_Dialog} or QDialog (of legacy PMs)
        
        @attention: This method is a temporary workaround for "Insert > Plane".
                    The current command should always be responsible for 
                    (re)opening its own PM via self.show().
                    
        @see: L{show()}
        """
        if 1:
            commandSequencer = self.win.commandSequencer  #bruce 071008
            commandName = commandSequencer.currentCommand.commandName
            # that's an internal name, but this is just for a debug print
            print "PM_Dialog.open(): Reopening the PM for command:", commandName

        # The following line of code is buggy when you, for instance, exit a PM
        # and reopen the previous one. It sends the disconnect signal twice to
        # the PM that is just closed.So disabling this line -- Ninad 2007-12-04

        ##self.close() # Just in case there is another PM open.

        self.pw = self.win.activePartWindow()
        self.pw.updatePropertyManagerTab(pm)
        try:
            pm.setSponsor()
        except:
            print """PM_Dialog.open(): pm has no attribute 'setSponsor()'  
                     ignoring."""
        self.pw.pwProjectTabWidget.setCurrentIndex(
            self.pw.pwProjectTabWidget.indexOf(pm))

    def close(self):
        """
        Closes the Property Manager.
        """
        if not self.pw:
            self.pw = self.win.activePartWindow()
        self.pw.pwProjectTabWidget.setCurrentIndex(0)

        ## try: [bruce 071018 moved this lower, since errmsg only covers attr]
        pmWidget = self.pw.propertyManagerScrollArea.widget()
        if debug_flags.atom_debug:  #bruce 071018
            "atom_debug fyi: %r is closing %r (can they differ?)" % \
                        (self, pmWidget)
        try:
            pmWidget.update_props_if_needed_before_closing
        except AttributeError:
            if 1 or debug_flags.atom_debug:
                msg1 = "Last PropMgr %r doesn't have method" % pmWidget
                msg2 = " update_props_if_needed_before_closing. That's"
                msg3 = " OK (for now, only implemented for Plane PM). "
                msg4 = "Ignoring Exception: "
                print_compact_traceback(msg1 + msg2 + msg3 + msg4)
                #bruce 071018: I'll define that method in PM_Dialog
                # so this message should become rare or nonexistent,
                # so I'll make it happen whether or not atom_debug.
        else:
            pmWidget.update_props_if_needed_before_closing()

        self.pw.pwProjectTabWidget.removeTab(
            self.pw.pwProjectTabWidget.indexOf(
                self.pw.propertyManagerScrollArea))

        if self.pw.propertyManagerTab:
            self.pw.propertyManagerTab = None

    def update_props_if_needed_before_closing(self):
        # bruce 071018 default implem
        """
        Subclasses can override this to update some cosmetic properties
        of their associated model objects before closing self
        (the Property Manager).
        """
        pass

    def updateMessage(self, msg=''):
        """
        Updates the message box with an informative message
        @param msg: Message to be displayed in the Message groupbox of 
                        the property manager
        @type  msg: string
        """
        self.MessageGroupBox.insertHtmlMessage(msg,
                                               setAsDefault=False,
                                               minLines=5)

    def _createHeader(self, iconPath, title):
        """
        Creates the Property Manager header, which contains an icon
        (a QLabel with a pixmap) and white text (a QLabel with text).
        
        @param iconPath: The relative path for the icon (PNG image) that 
                         appears in the header.
        @type  iconPath: str
        
        @param title: The title that appears in the header.
        @type  title: str
        """

        # Heading frame (dark gray), which contains
        # a pixmap and (white) heading text.
        self.headerFrame = QFrame(self)
        self.headerFrame.setFrameShape(QFrame.NoFrame)
        self.headerFrame.setFrameShadow(QFrame.Plain)

        self.headerFrame.setPalette(QPalette(pmHeaderFrameColor))
        self.headerFrame.setAutoFillBackground(True)

        # HBox layout for heading frame, containing the pixmap
        # and label (title).
        HeaderFrameHLayout = QHBoxLayout(self.headerFrame)
        # 2 pixels around edges --
        HeaderFrameHLayout.setMargin(PM_HEADER_FRAME_MARGIN)
        # 5 pixel between pixmap and label. --
        HeaderFrameHLayout.setSpacing(PM_HEADER_FRAME_SPACING)

        # PropMgr icon. Set image by calling setHeaderIcon().
        self.headerIcon = QLabel(self.headerFrame)
        self.headerIcon.setSizePolicy(
            QSizePolicy(QSizePolicy.Policy(QSizePolicy.Fixed),
                        QSizePolicy.Policy(QSizePolicy.Fixed)))

        self.headerIcon.setScaledContents(True)

        HeaderFrameHLayout.addWidget(self.headerIcon)

        # PropMgr header title text (a QLabel).
        self.headerTitle = QLabel(self.headerFrame)
        headerTitlePalette = self._getHeaderTitlePalette()
        self.headerTitle.setPalette(headerTitlePalette)
        self.headerTitle.setAlignment(PM_LABEL_LEFT_ALIGNMENT)

        # Assign header title font.
        self.headerTitle.setFont(self._getHeaderFont())
        HeaderFrameHLayout.addWidget(self.headerTitle)

        self.vBoxLayout.addWidget(self.headerFrame)

        # Set header icon and title text.
        self.setHeaderIcon(iconPath)
        self.setHeaderTitle(title)

    def _getHeaderFont(self):
        """
        Returns the font used for the header.
        
        @return: the header font
        @rtype:  QFont
        """
        font = QFont()
        font.setFamily(PM_HEADER_FONT)
        font.setPointSize(PM_HEADER_FONT_POINT_SIZE)
        font.setBold(PM_HEADER_FONT_BOLD)
        return font

    def setHeaderTitle(self, title):
        """
        Set the Property Manager header title to string <title>.
        
        @param title: the title to insert in the header.
        @type  title: str
        """
        self.headerTitleText = title
        self.headerTitle.setText(title)

    def setHeaderIcon(self, iconPath):
        """
        Set the Property Manager header icon.
        
        @param iconPath: the relative path to the PNG file containing the 
                         icon image.
        @type  iconPath: str
        """

        if not iconPath:
            return

        self.headerIcon.setPixmap(getpixmap(iconPath))

    def _createSponsorButton(self):
        """
        Creates the Property Manager sponsor button, which contains
        a QPushButton inside of a QGridLayout inside of a QFrame.
        The sponsor logo image is not loaded here.
        """

        # Sponsor button (inside a frame)
        self.sponsor_frame = QFrame(self)
        self.sponsor_frame.setFrameShape(QFrame.NoFrame)
        self.sponsor_frame.setFrameShadow(QFrame.Plain)

        SponsorFrameGrid = QGridLayout(self.sponsor_frame)
        SponsorFrameGrid.setMargin(PM_SPONSOR_FRAME_MARGIN)
        SponsorFrameGrid.setSpacing(PM_SPONSOR_FRAME_SPACING)  # Has no effect.

        self.sponsor_btn = QPushButton(self.sponsor_frame)
        self.sponsor_btn.setAutoDefault(False)
        self.sponsor_btn.setFlat(True)
        self.connect(self.sponsor_btn, SIGNAL("clicked()"),
                     self.open_sponsor_homepage)

        SponsorFrameGrid.addWidget(self.sponsor_btn, 0, 0, 1, 1)

        self.vBoxLayout.addWidget(self.sponsor_frame)

        button_whatsthis_widget = self.sponsor_btn
        #bruce 070615 bugfix -- put tooltip & whatsthis on self.sponsor_btn,
        # not self.
        # [self.sponsor_frame might be another possible place to put them.]

        button_whatsthis_widget.setWhatsThis("""<b>Sponsor Button</b>
            <p>When clicked, this sponsor logo will display a short 
            description about a NanoEngineer-1 sponsor. This can 
            be an official sponsor or credit given to a contributor 
            that has helped code part or all of this command. 
            A link is provided in the description to learn more 
            about this sponsor.</p>""")

        button_whatsthis_widget.setToolTip("NanoEngineer-1 Sponsor Button")

        return

    def _createTopRowBtns(self):
        """
        Creates the Done, Cancel, Preview, Restore Defaults and What's This 
        buttons row at the top of the Property Manager.
        """

        # Main "button group" widget (but it is not a QButtonGroup).
        self.pmTopRowBtns = QHBoxLayout()
        # This QHBoxLayout is (probably) not necessary. Try using just the frame
        # for the foundation. I think it should work. Mark 2007-05-30

        # Horizontal spacer
        horizontalSpacer = QSpacerItem(1, 1, QSizePolicy.Expanding,
                                       QSizePolicy.Minimum)

        # Frame containing all the buttons.
        self.topRowBtnsFrame = QFrame()

        self.topRowBtnsFrame.setFrameShape(QFrame.NoFrame)
        self.topRowBtnsFrame.setFrameShadow(QFrame.Plain)

        # Create Hbox layout for main frame.
        topRowBtnsHLayout = QHBoxLayout(self.topRowBtnsFrame)
        topRowBtnsHLayout.setMargin(PM_TOPROWBUTTONS_MARGIN)
        topRowBtnsHLayout.setSpacing(PM_TOPROWBUTTONS_SPACING)

        topRowBtnsHLayout.addItem(horizontalSpacer)

        # Set button type.
        if 1:  # Mark 2007-05-30
            # Needs to be QToolButton for MacOS. Fine for Windows, too.
            buttonType = QToolButton
            # May want to use QToolButton.setAutoRaise(1) below. Mark 2007-05-29
        else:
            buttonType = QPushButton  # Do not use.

        # Done (OK) button.
        self.done_btn = buttonType(self.topRowBtnsFrame)
        self.done_btn.setIcon(
            geticon("ui/actions/Properties Manager/Done.png"))
        self.done_btn.setIconSize(QSize(22, 22))
        self.connect(self.done_btn, SIGNAL("clicked()"),
                     self.doneButtonClicked)
        self.done_btn.setToolTip("Done")

        topRowBtnsHLayout.addWidget(self.done_btn)

        # Cancel (Abort) button.
        self.cancel_btn = buttonType(self.topRowBtnsFrame)
        self.cancel_btn.setIcon(
            geticon("ui/actions/Properties Manager/Abort.png"))
        self.cancel_btn.setIconSize(QSize(22, 22))
        self.connect(self.cancel_btn, SIGNAL("clicked()"),
                     self.cancelButtonClicked)
        self.cancel_btn.setToolTip("Cancel")

        topRowBtnsHLayout.addWidget(self.cancel_btn)

        #@ abort_btn deprecated. We still need it because modes use it.
        self.abort_btn = self.cancel_btn

        # Restore Defaults button.
        self.restore_defaults_btn = buttonType(self.topRowBtnsFrame)
        self.restore_defaults_btn.setIcon(
            geticon("ui/actions/Properties Manager/Restore.png"))
        self.restore_defaults_btn.setIconSize(QSize(22, 22))
        self.connect(self.restore_defaults_btn, SIGNAL("clicked()"),
                     self.restoreDefaultsButtonClicked)
        self.restore_defaults_btn.setToolTip("Restore Defaults")
        topRowBtnsHLayout.addWidget(self.restore_defaults_btn)

        # Preview (glasses) button.
        self.preview_btn = buttonType(self.topRowBtnsFrame)
        self.preview_btn.setIcon(
            geticon("ui/actions/Properties Manager/Preview.png"))
        self.preview_btn.setIconSize(QSize(22, 22))
        self.connect(self.preview_btn, SIGNAL("clicked()"),
                     self.previewButtonClicked)
        self.preview_btn.setToolTip("Preview")

        topRowBtnsHLayout.addWidget(self.preview_btn)

        # What's This (?) button.
        self.whatsthis_btn = buttonType(self.topRowBtnsFrame)
        self.whatsthis_btn.setIcon(
            geticon("ui/actions/Properties Manager/WhatsThis.png"))
        self.whatsthis_btn.setIconSize(QSize(22, 22))
        self.connect(self.whatsthis_btn, SIGNAL("clicked()"),
                     self.whatsThisButtonClicked)
        self.whatsthis_btn.setToolTip("Enter \"What's This\" help mode")

        topRowBtnsHLayout.addWidget(self.whatsthis_btn)

        topRowBtnsHLayout.addItem(horizontalSpacer)

        # Create Button Row
        self.pmTopRowBtns.addWidget(self.topRowBtnsFrame)

        self.vBoxLayout.addLayout(self.pmTopRowBtns)

        # Add What's This for buttons.

        self.done_btn.setWhatsThis("""<b>Done</b>
            <p>
            <img source=\"ui/actions/Properties Manager/Done.png\"><br>
            Completes and/or exits the current command.</p>""")

        self.cancel_btn.setWhatsThis("""<b>Cancel</b>
            <p>
            <img source=\"ui/actions/Properties Manager/Abort.png\"><br>
            Cancels the current command.</p>""")

        self.restore_defaults_btn.setWhatsThis("""<b>Restore Defaults</b>
            <p><img source=\"ui/actions/Properties Manager/Restore.png\"><br>
            Restores the defaut values of the Property Manager.</p>""")

        self.preview_btn.setWhatsThis("""<b>Preview</b>
            <p>
            <img source=\"ui/actions/Properties Manager/Preview.png\"><br>
            Preview the structure based on current Property Manager settings.
            </p>""")

        self.whatsthis_btn.setWhatsThis("""<b>What's This</b> 
            <p>
            <img source=\"ui/actions/Properties Manager/WhatsThis.png\"><br>
            This invokes \"What's This?\" help mode which is part of 
            NanoEngineer-1's online help system, and provides users with 
            information about the functionality and usage of a particular 
            command button or widget.
            </p>""")

        return

    def hideTopRowButtons(self, pmButtonFlags=None):
        """
        Hides one or more top row buttons using <pmButtonFlags>.
        Button flags not set will cause the button to be shown
        if currently hidden.
        
        @param pmButtonFlags: This enumerator describes the which buttons to 
                              hide, where:
        
            - PM_DONE_BUTTON            =  1
            - PM_CANCEL_BUTTON          =  2
            - PM_RESTORE_DEFAULTS_BUTTON =  4
            - PM_PREVIEW_BUTTON         =  8
            - PM_WHATS_THIS_BUTTON       = 16
            - PM_ALL_BUTTONS            = 31
            
        @type  pmButtonFlags: int
        """

        if pmButtonFlags & PM_DONE_BUTTON:
            self.done_btn.hide()
        else:
            self.done_btn.show()

        if pmButtonFlags & PM_CANCEL_BUTTON:
            self.cancel_btn.hide()
        else:
            self.cancel_btn.show()

        if pmButtonFlags & PM_RESTORE_DEFAULTS_BUTTON:
            self.restore_defaults_btn.hide()
        else:
            self.restore_defaults_btn.show()

        if pmButtonFlags & PM_PREVIEW_BUTTON:
            self.preview_btn.hide()
        else:
            self.preview_btn.show()

        if pmButtonFlags & PM_WHATS_THIS_BUTTON:
            self.whatsthis_btn.hide()
        else:
            self.whatsthis_btn.show()

    def showTopRowButtons(self, pmButtonFlags=PM_ALL_BUTTONS):
        """
        Shows one or more top row buttons using <pmButtonFlags>.
        Button flags not set will cause the button to be hidden
        if currently displayed.
        
        @param pmButtonFlags: this enumerator describes which buttons to 
        display, where:
        
            - PM_DONE_BUTTON            =  1
            - PM_CANCEL_BUTTON          =  2
            - PM_RESTORE_DEFAULTS_BUTTON =  4
            - PM_PREVIEW_BUTTON         =  8
            - PM_WHATS_THIS_BUTTON       = 16
            - PM_ALL_BUTTONS            = 31
            
        @type  pmButtonFlags: int
        """

        self.hideTopRowButtons(pmButtonFlags ^ PM_ALL_BUTTONS)

    def _getHeaderTitlePalette(self):
        """
        Return a palette for header title (text) label. 
        """
        palette = QPalette()
        palette.setColor(QPalette.WindowText, pmHeaderTitleColor)
        return palette

    def doneButtonClicked(self):
        """
        Slot for the What's This button.
        """
        self.ok_btn_clicked()

    def cancelButtonClicked(self):
        """
        Slot for the What's This button.
        """
        self.cancel_btn_clicked()

    def restoreDefaultsButtonClicked(self):
        """
        Slot for "Restore Defaults" button in the Property Manager.
        It is called each time the button is clicked.
        """
        for widget in self._widgetList:
            if isinstance(widget, PM_GroupBox):
                widget.restoreDefault()

    def previewButtonClicked(self):
        """
        Slot for the What's This button.
        """
        self.preview_btn_clicked()

    def whatsThisButtonClicked(self):
        """
        Slot for the What's This button.
        """
        QWhatsThis.enterWhatsThisMode()
コード例 #36
0
    def __init__(self, plugin_path, alfdir):
        QWidget.__init__(self)

        self.plugin_path = plugin_path
        self.alfdir = alfdir

        # get the prefs
        self.dedrmprefs = prefs.DeDRM_Prefs()

        # make a local copy
        self.tempdedrmprefs = {}
        self.tempdedrmprefs['bandnkeys'] = self.dedrmprefs['bandnkeys'].copy()
        self.tempdedrmprefs['adeptkeys'] = self.dedrmprefs['adeptkeys'].copy()
        self.tempdedrmprefs['ereaderkeys'] = self.dedrmprefs[
            'ereaderkeys'].copy()
        self.tempdedrmprefs['kindlekeys'] = self.dedrmprefs['kindlekeys'].copy(
        )
        self.tempdedrmprefs['pids'] = list(self.dedrmprefs['pids'])
        self.tempdedrmprefs['serials'] = list(self.dedrmprefs['serials'])
        self.tempdedrmprefs['adobewineprefix'] = self.dedrmprefs[
            'adobewineprefix']
        self.tempdedrmprefs['kindlewineprefix'] = self.dedrmprefs[
            'kindlewineprefix']

        # 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/">Plugin 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(_('Configuration:'), self)
        layout.addWidget(keys_group_box)
        keys_group_box_layout = QHBoxLayout()
        keys_group_box.setLayout(keys_group_box_layout)

        button_layout = QVBoxLayout()
        keys_group_box_layout.addLayout(button_layout)
        self.bandn_button = QtGui.QPushButton(self)
        self.bandn_button.setToolTip(
            _(u"Click to manage keys for Barnes and Noble ebooks"))
        self.bandn_button.setText(u"Barnes and Noble ebooks")
        self.bandn_button.clicked.connect(self.bandn_keys)
        self.kindle_serial_button = QtGui.QPushButton(self)
        self.kindle_serial_button.setToolTip(
            _(u"Click to manage eInk Kindle serial numbers for Kindle ebooks"))
        self.kindle_serial_button.setText(u"eInk Kindle ebooks")
        self.kindle_serial_button.clicked.connect(self.kindle_serials)
        self.kindle_key_button = QtGui.QPushButton(self)
        self.kindle_key_button.setToolTip(
            _(u"Click to manage keys for Kindle for Mac/PC ebooks"))
        self.kindle_key_button.setText(u"Kindle for Mac/PC ebooks")
        self.kindle_key_button.clicked.connect(self.kindle_keys)
        self.adept_button = QtGui.QPushButton(self)
        self.adept_button.setToolTip(
            _(u"Click to manage keys for Adobe Digital Editions ebooks"))
        self.adept_button.setText(u"Adobe Digital Editions ebooks")
        self.adept_button.clicked.connect(self.adept_keys)
        self.mobi_button = QtGui.QPushButton(self)
        self.mobi_button.setToolTip(
            _(u"Click to manage PIDs for Mobipocket ebooks"))
        self.mobi_button.setText(u"Mobipocket ebooks")
        self.mobi_button.clicked.connect(self.mobi_keys)
        self.ereader_button = QtGui.QPushButton(self)
        self.ereader_button.setToolTip(
            _(u"Click to manage keys for eReader ebooks"))
        self.ereader_button.setText(u"eReader ebooks")
        self.ereader_button.clicked.connect(self.ereader_keys)
        button_layout.addWidget(self.kindle_serial_button)
        button_layout.addWidget(self.bandn_button)
        button_layout.addWidget(self.mobi_button)
        button_layout.addWidget(self.ereader_button)
        button_layout.addWidget(self.adept_button)
        button_layout.addWidget(self.kindle_key_button)

        self.resize(self.sizeHint())
コード例 #37
0
ファイル: edit_authors_dialog.py プロジェクト: Eksmo/calibre
    def __init__(self, parent, db, id_to_select, select_sort, select_link):
        QDialog.__init__(self, parent)
        Ui_EditAuthorsDialog.__init__(self)
        self.setupUi(self)
        # Remove help icon on title bar
        icon = self.windowIcon()
        self.setWindowFlags(self.windowFlags()&(~Qt.WindowContextHelpButtonHint))
        self.setWindowIcon(icon)

        try:
            self.table_column_widths = \
                        gprefs.get('manage_authors_table_widths', None)
            geom = gprefs.get('manage_authors_dialog_geometry', bytearray(''))
            self.restoreGeometry(QByteArray(geom))
        except:
            pass

        self.buttonBox.accepted.connect(self.accepted)

        # Set up the column headings
        self.table.setSelectionMode(QAbstractItemView.SingleSelection)
        self.table.setColumnCount(3)
        self.down_arrow_icon = QIcon(I('arrow-down.png'))
        self.up_arrow_icon = QIcon(I('arrow-up.png'))
        self.blank_icon = QIcon(I('blank.png'))
        self.auth_col = QTableWidgetItem(_('Author'))
        self.table.setHorizontalHeaderItem(0, self.auth_col)
        self.auth_col.setIcon(self.blank_icon)
        self.aus_col = QTableWidgetItem(_('Author sort'))
        self.table.setHorizontalHeaderItem(1, self.aus_col)
        self.aus_col.setIcon(self.up_arrow_icon)
        self.aul_col = QTableWidgetItem(_('Link'))
        self.table.setHorizontalHeaderItem(2, self.aul_col)
        self.aus_col.setIcon(self.blank_icon)

        # Add the data
        self.authors = {}
        auts = db.get_authors_with_ids()
        self.table.setRowCount(len(auts))
        select_item = None
        for row, (id, author, sort, link) in enumerate(auts):
            author = author.replace('|', ',')
            self.authors[id] = (author, sort, link)
            aut = tableItem(author)
            aut.setData(Qt.UserRole, id)
            sort = tableItem(sort)
            link = tableItem(link)
            self.table.setItem(row, 0, aut)
            self.table.setItem(row, 1, sort)
            self.table.setItem(row, 2, link)
            if id == id_to_select:
                if select_sort:
                    select_item = sort
                elif select_link:
                    select_item = link
                else:
                    select_item = aut
        self.table.resizeColumnsToContents()
        if self.table.columnWidth(2) < 200:
            self.table.setColumnWidth(2, 200)

        # set up the cellChanged signal only after the table is filled
        self.table.cellChanged.connect(self.cell_changed)

        # set up sort buttons
        self.sort_by_author.setCheckable(True)
        self.sort_by_author.setChecked(False)
        self.sort_by_author.clicked.connect(self.do_sort_by_author)
        self.author_order = 1

        self.table.sortByColumn(1, Qt.AscendingOrder)
        self.sort_by_author_sort.clicked.connect(self.do_sort_by_author_sort)
        self.sort_by_author_sort.setCheckable(True)
        self.sort_by_author_sort.setChecked(True)
        self.author_sort_order = 1

        self.recalc_author_sort.clicked.connect(self.do_recalc_author_sort)
        self.auth_sort_to_author.clicked.connect(self.do_auth_sort_to_author)

        # Position on the desired item
        if select_item is not None:
            self.table.setCurrentItem(select_item)
            self.table.editItem(select_item)
            self.start_find_pos = select_item.row() * 2 + select_item.column()
        else:
            self.table.setCurrentCell(0, 0)
            self.start_find_pos = -1

        # set up the search box
        self.find_box.initialize('manage_authors_search')
        self.find_box.lineEdit().returnPressed.connect(self.do_find)
        self.find_box.editTextChanged.connect(self.find_text_changed)
        self.find_button.clicked.connect(self.do_find)

        l = QLabel(self.table)
        self.not_found_label = l
        l.setFrameStyle(QFrame.StyledPanel)
        l.setAutoFillBackground(True)
        l.setText(_('No matches found'))
        l.setAlignment(Qt.AlignVCenter)
        l.resize(l.sizeHint())
        l.move(10,20)
        l.setVisible(False)
        self.not_found_label.move(40, 40)
        self.not_found_label_timer = QTimer()
        self.not_found_label_timer.setSingleShot(True)
        self.not_found_label_timer.timeout.connect(
                self.not_found_label_timer_event, type=Qt.QueuedConnection)

        self.table.setContextMenuPolicy(Qt.CustomContextMenu)
        self.table.customContextMenuRequested .connect(self.show_context_menu)
コード例 #38
0
class ConfigWidget(QWidget, Logger):
    '''
    Config dialog for Marvin Manager
    '''

    WIZARD_PROFILES = {
        'Annotations': {
            'label': 'mm_annotations',
            'datatype': 'comments',
            'display': {},
            'is_multiple': False
        },
        'Collections': {
            'label': 'mm_collections',
            'datatype': 'text',
            'display': {u'is_names': False},
            'is_multiple': True
        },
        'Last read': {
            'label': 'mm_date_read',
            'datatype': 'datetime',
            'display': {},
            'is_multiple': False
        },
        'Locked': {
            'label': 'mm_locked',
            'datatype': 'bool',
            'display': {},
            'is_multiple': False
        },
        'Progress': {
            'label': 'mm_progress',
            'datatype': 'float',
            'display': {u'number_format': u'{0:.0f}%'},
            'is_multiple': False
        },
        'Read': {
            'label': 'mm_read',
            'datatype': 'bool',
            'display': {},
            'is_multiple': False
        },
        'Reading list': {
            'label': 'mm_reading_list',
            'datatype': 'bool',
            'display': {},
            'is_multiple': False
        },
        'Word count': {
            'label': 'mm_word_count',
            'datatype': 'int',
            'display': {u'number_format': u'{0:n}'},
            'is_multiple': False
        }
    }

    def __init__(self, plugin_action):
        QWidget.__init__(self)
        self.parent = plugin_action

        self.gui = get_gui()
        self.icon = plugin_action.icon
        self.opts = plugin_action.opts
        self.prefs = plugin_prefs
        self.resources_path = plugin_action.resources_path
        self.verbose = plugin_action.verbose

        self.restart_required = False

        self._log_location()

        self.l = QGridLayout()
        self.setLayout(self.l)
        self.column1_layout = QVBoxLayout()
        self.l.addLayout(self.column1_layout, 0, 0)
        self.column2_layout = QVBoxLayout()
        self.l.addLayout(self.column2_layout, 0, 1)

        # ----------------------------- Column 1 -----------------------------
        # ~~~~~~~~ Create the Custom fields options group box ~~~~~~~~
        self.cfg_custom_fields_gb = QGroupBox(self)
        self.cfg_custom_fields_gb.setTitle('Custom column assignments')
        self.column1_layout.addWidget(self.cfg_custom_fields_gb)

        self.cfg_custom_fields_qgl = QGridLayout(self.cfg_custom_fields_gb)
        current_row = 0

        # ++++++++ Labels + HLine ++++++++
        self.marvin_source_label = QLabel("Marvin source")
        self.cfg_custom_fields_qgl.addWidget(self.marvin_source_label, current_row, 0)
        self.calibre_destination_label = QLabel("calibre destination")
        self.cfg_custom_fields_qgl.addWidget(self.calibre_destination_label, current_row, 1)
        current_row += 1
        self.sd_hl = QFrame(self.cfg_custom_fields_gb)
        self.sd_hl.setFrameShape(QFrame.HLine)
        self.sd_hl.setFrameShadow(QFrame.Raised)
        self.cfg_custom_fields_qgl.addWidget(self.sd_hl, current_row, 0, 1, 3)
        current_row += 1

        # ++++++++ Annotations ++++++++
        self.cfg_annotations_label = QLabel('Annotations')
        self.cfg_annotations_label.setAlignment(Qt.AlignLeft)
        self.cfg_custom_fields_qgl.addWidget(self.cfg_annotations_label, current_row, 0)

        self.annotations_field_comboBox = QComboBox(self.cfg_custom_fields_gb)
        self.annotations_field_comboBox.setObjectName('annotations_field_comboBox')
        self.annotations_field_comboBox.setToolTip('Select a custom column to store Marvin annotations')
        self.cfg_custom_fields_qgl.addWidget(self.annotations_field_comboBox, current_row, 1)

        self.cfg_highlights_wizard = QToolButton()
        self.cfg_highlights_wizard.setIcon(QIcon(I('wizard.png')))
        self.cfg_highlights_wizard.setToolTip("Create a custom column to store Marvin annotations")
        self.cfg_highlights_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Annotations'))
        self.cfg_custom_fields_qgl.addWidget(self.cfg_highlights_wizard, current_row, 2)
        current_row += 1

        # ++++++++ Collections ++++++++
        self.cfg_collections_label = QLabel('Collections')
        self.cfg_collections_label.setAlignment(Qt.AlignLeft)
        self.cfg_custom_fields_qgl.addWidget(self.cfg_collections_label, current_row, 0)

        self.collection_field_comboBox = QComboBox(self.cfg_custom_fields_gb)
        self.collection_field_comboBox.setObjectName('collection_field_comboBox')
        self.collection_field_comboBox.setToolTip('Select a custom column to store Marvin collection assignments')
        self.cfg_custom_fields_qgl.addWidget(self.collection_field_comboBox, current_row, 1)

        self.cfg_collections_wizard = QToolButton()
        self.cfg_collections_wizard.setIcon(QIcon(I('wizard.png')))
        self.cfg_collections_wizard.setToolTip("Create a custom column for Marvin collection assignments")
        self.cfg_collections_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Collections'))
        self.cfg_custom_fields_qgl.addWidget(self.cfg_collections_wizard, current_row, 2)
        current_row += 1

        # ++++++++ Last read ++++++++
        self.cfg_date_read_label = QLabel("Last read")
        self.cfg_date_read_label.setAlignment(Qt.AlignLeft)
        self.cfg_custom_fields_qgl.addWidget(self.cfg_date_read_label, current_row, 0)

        self.date_read_field_comboBox = QComboBox(self.cfg_custom_fields_gb)
        self.date_read_field_comboBox.setObjectName('date_read_field_comboBox')
        self.date_read_field_comboBox.setToolTip('Select a custom column to store Last read date')
        self.cfg_custom_fields_qgl.addWidget(self.date_read_field_comboBox, current_row, 1)

        self.cfg_collections_wizard = QToolButton()
        self.cfg_collections_wizard.setIcon(QIcon(I('wizard.png')))
        self.cfg_collections_wizard.setToolTip("Create a custom column to store Last read date")
        self.cfg_collections_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Last read'))
        self.cfg_custom_fields_qgl.addWidget(self.cfg_collections_wizard, current_row, 2)
        current_row += 1

        # ++++++++ Locked ++++++++
        self.cfg_locked_label = QLabel("Locked")
        self.cfg_locked_label.setAlignment(Qt.AlignLeft)
        self.cfg_custom_fields_qgl.addWidget(self.cfg_locked_label, current_row, 0)

        self.locked_field_comboBox = QComboBox(self.cfg_custom_fields_gb)
        self.locked_field_comboBox.setObjectName('locked_field_comboBox')
        self.locked_field_comboBox.setToolTip('Select a custom column to store Locked status')
        self.cfg_custom_fields_qgl.addWidget(self.locked_field_comboBox, current_row, 1)

        self.cfg_locked_wizard = QToolButton()
        self.cfg_locked_wizard.setIcon(QIcon(I('wizard.png')))
        self.cfg_locked_wizard.setToolTip("Create a custom column to store Locked status")
        self.cfg_locked_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Locked'))
        self.cfg_custom_fields_qgl.addWidget(self.cfg_locked_wizard, current_row, 2)
        current_row += 1

        # ++++++++ Progress ++++++++
        self.cfg_progress_label = QLabel('Progress')
        self.cfg_progress_label.setAlignment(Qt.AlignLeft)
        self.cfg_custom_fields_qgl.addWidget(self.cfg_progress_label, current_row, 0)

        self.progress_field_comboBox = QComboBox(self.cfg_custom_fields_gb)
        self.progress_field_comboBox.setObjectName('progress_field_comboBox')
        self.progress_field_comboBox.setToolTip('Select a custom column to store Marvin reading progress')
        self.cfg_custom_fields_qgl.addWidget(self.progress_field_comboBox, current_row, 1)

        self.cfg_progress_wizard = QToolButton()
        self.cfg_progress_wizard.setIcon(QIcon(I('wizard.png')))
        self.cfg_progress_wizard.setToolTip("Create a custom column to store Marvin reading progress")
        self.cfg_progress_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Progress'))
        self.cfg_custom_fields_qgl.addWidget(self.cfg_progress_wizard, current_row, 2)
        current_row += 1

        # ++++++++ Read flag ++++++++
        self.cfg_read_label = QLabel('Read')
        self.cfg_read_label.setAlignment(Qt.AlignLeft)
        self.cfg_custom_fields_qgl.addWidget(self.cfg_read_label, current_row, 0)

        self.read_field_comboBox = QComboBox(self.cfg_custom_fields_gb)
        self.read_field_comboBox.setObjectName('read_field_comboBox')
        self.read_field_comboBox.setToolTip('Select a custom column to store Marvin Read status')
        self.cfg_custom_fields_qgl.addWidget(self.read_field_comboBox, current_row, 1)

        self.cfg_read_wizard = QToolButton()
        self.cfg_read_wizard.setIcon(QIcon(I('wizard.png')))
        self.cfg_read_wizard.setToolTip("Create a custom column to store Marvin Read status")
        self.cfg_read_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Read'))
        self.cfg_custom_fields_qgl.addWidget(self.cfg_read_wizard, current_row, 2)
        current_row += 1

        # ++++++++ Reading list flag ++++++++
        self.cfg_reading_list_label = QLabel('Reading list')
        self.cfg_reading_list_label.setAlignment(Qt.AlignLeft)
        self.cfg_custom_fields_qgl.addWidget(self.cfg_reading_list_label, current_row, 0)

        self.reading_list_field_comboBox = QComboBox(self.cfg_custom_fields_gb)
        self.reading_list_field_comboBox.setObjectName('reading_list_field_comboBox')
        self.reading_list_field_comboBox.setToolTip('Select a custom column to store Marvin Reading list status')
        self.cfg_custom_fields_qgl.addWidget(self.reading_list_field_comboBox, current_row, 1)

        self.cfg_reading_list_wizard = QToolButton()
        self.cfg_reading_list_wizard.setIcon(QIcon(I('wizard.png')))
        self.cfg_reading_list_wizard.setToolTip("Create a custom column to store Marvin Reading list status")
        self.cfg_reading_list_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Reading list'))
        self.cfg_custom_fields_qgl.addWidget(self.cfg_reading_list_wizard, current_row, 2)
        current_row += 1

        # ++++++++ Word count ++++++++
        self.cfg_word_count_label = QLabel('Word count')
        self.cfg_word_count_label.setAlignment(Qt.AlignLeft)
        self.cfg_custom_fields_qgl.addWidget(self.cfg_word_count_label, current_row, 0)

        self.word_count_field_comboBox = QComboBox(self.cfg_custom_fields_gb)
        self.word_count_field_comboBox.setObjectName('word_count_field_comboBox')
        self.word_count_field_comboBox.setToolTip('Select a custom column to store Marvin word counts')
        self.cfg_custom_fields_qgl.addWidget(self.word_count_field_comboBox, current_row, 1)

        self.cfg_word_count_wizard = QToolButton()
        self.cfg_word_count_wizard.setIcon(QIcon(I('wizard.png')))
        self.cfg_word_count_wizard.setToolTip("Create a custom column to store Marvin word counts")
        self.cfg_word_count_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Word count'))
        self.cfg_custom_fields_qgl.addWidget(self.cfg_word_count_wizard, current_row, 2)
        current_row += 1

        self.spacerItem1 = QSpacerItem(20, 20, QSizePolicy.Minimum, QSizePolicy.Expanding)
        self.column1_layout.addItem(self.spacerItem1)

        # ----------------------------- Column 2 -----------------------------
        # ~~~~~~~~ Create the CSS group box ~~~~~~~~
        self.cfg_css_options_gb = QGroupBox(self)
        self.cfg_css_options_gb.setTitle('CSS')
        self.column2_layout.addWidget(self.cfg_css_options_gb)
        self.cfg_css_options_qgl = QGridLayout(self.cfg_css_options_gb)

        current_row = 0

        # ++++++++ Annotations appearance ++++++++
        self.annotations_icon = QIcon(os.path.join(self.resources_path, 'icons', 'annotations_hiliter.png'))
        self.cfg_annotations_appearance_toolbutton = QToolButton()
        self.cfg_annotations_appearance_toolbutton.setIcon(self.annotations_icon)
        self.cfg_annotations_appearance_toolbutton.clicked.connect(self.configure_appearance)
        self.cfg_css_options_qgl.addWidget(self.cfg_annotations_appearance_toolbutton, current_row, 0)
        self.cfg_annotations_label = ClickableQLabel("Book notes, Bookmark notes and Annotations")
        self.connect(self.cfg_annotations_label, SIGNAL('clicked()'), self.configure_appearance)
        self.cfg_css_options_qgl.addWidget(self.cfg_annotations_label, current_row, 1)
        current_row += 1

        # ++++++++ Injected CSS ++++++++
        self.css_editor_icon = QIcon(I('format-text-heading.png'))
        self.cfg_css_editor_toolbutton = QToolButton()
        self.cfg_css_editor_toolbutton.setIcon(self.css_editor_icon)
        self.cfg_css_editor_toolbutton.clicked.connect(self.edit_css)
        self.cfg_css_options_qgl.addWidget(self.cfg_css_editor_toolbutton, current_row, 0)
        self.cfg_css_editor_label = ClickableQLabel("Articles, Vocabulary")
        self.connect(self.cfg_css_editor_label, SIGNAL('clicked()'), self.edit_css)
        self.cfg_css_options_qgl.addWidget(self.cfg_css_editor_label, current_row, 1)


        """
        # ~~~~~~~~ Create the Dropbox syncing group box ~~~~~~~~
        self.cfg_dropbox_syncing_gb = QGroupBox(self)
        self.cfg_dropbox_syncing_gb.setTitle('Dropbox')
        self.column2_layout.addWidget(self.cfg_dropbox_syncing_gb)
        self.cfg_dropbox_syncing_qgl = QGridLayout(self.cfg_dropbox_syncing_gb)
        current_row = 0

        # ++++++++ Syncing enabled checkbox ++++++++
        self.dropbox_syncing_checkbox = QCheckBox('Enable Dropbox updates')
        self.dropbox_syncing_checkbox.setObjectName('dropbox_syncing')
        self.dropbox_syncing_checkbox.setToolTip('Refresh custom column content from Marvin metadata')
        self.cfg_dropbox_syncing_qgl.addWidget(self.dropbox_syncing_checkbox,
            current_row, 0, 1, 3)
        current_row += 1

        # ++++++++ Dropbox folder picker ++++++++
        self.dropbox_folder_icon = QIcon(os.path.join(self.resources_path, 'icons', 'dropbox.png'))
        self.cfg_dropbox_folder_toolbutton = QToolButton()
        self.cfg_dropbox_folder_toolbutton.setIcon(self.dropbox_folder_icon)
        self.cfg_dropbox_folder_toolbutton.setToolTip("Specify Dropbox folder location on your computer")
        self.cfg_dropbox_folder_toolbutton.clicked.connect(self.select_dropbox_folder)
        self.cfg_dropbox_syncing_qgl.addWidget(self.cfg_dropbox_folder_toolbutton,
            current_row, 1)

        # ++++++++ Dropbox location lineedit ++++++++
        self.dropbox_location_lineedit = QLineEdit()
        self.dropbox_location_lineedit.setPlaceholderText("Dropbox folder location")
        self.cfg_dropbox_syncing_qgl.addWidget(self.dropbox_location_lineedit,
            current_row, 2)
        """

        # ~~~~~~~~ Create the General options group box ~~~~~~~~
        self.cfg_runtime_options_gb = QGroupBox(self)
        self.cfg_runtime_options_gb.setTitle('General options')
        self.column2_layout.addWidget(self.cfg_runtime_options_gb)
        self.cfg_runtime_options_qvl = QVBoxLayout(self.cfg_runtime_options_gb)

        # ++++++++ Temporary markers: Duplicates ++++++++
        self.duplicate_markers_checkbox = QCheckBox('Apply temporary markers to duplicate books')
        self.duplicate_markers_checkbox.setObjectName('apply_markers_to_duplicates')
        self.duplicate_markers_checkbox.setToolTip('Books with identical content will be flagged in the Library window')
        self.cfg_runtime_options_qvl.addWidget(self.duplicate_markers_checkbox)

        # ++++++++ Temporary markers: Updated ++++++++
        self.updated_markers_checkbox = QCheckBox('Apply temporary markers to books with updated content')
        self.updated_markers_checkbox.setObjectName('apply_markers_to_updated')
        self.updated_markers_checkbox.setToolTip('Books with updated content will be flagged in the Library window')
        self.cfg_runtime_options_qvl.addWidget(self.updated_markers_checkbox)

        # ++++++++ Auto refresh checkbox ++++++++
        self.auto_refresh_checkbox = QCheckBox('Automatically refresh custom column content')
        self.auto_refresh_checkbox.setObjectName('auto_refresh_at_startup')
        self.auto_refresh_checkbox.setToolTip('Update calibre custom column when Marvin XD is opened')
        self.cfg_runtime_options_qvl.addWidget(self.auto_refresh_checkbox)

        # ++++++++ Progress as percentage checkbox ++++++++
        self.reading_progress_checkbox = QCheckBox('Show reading progress as percentage')
        self.reading_progress_checkbox.setObjectName('show_progress_as_percentage')
        self.reading_progress_checkbox.setToolTip('Display percentage in Progress column')
        self.cfg_runtime_options_qvl.addWidget(self.reading_progress_checkbox)

        # ~~~~~~~~ Create the Debug options group box ~~~~~~~~
        self.cfg_debug_options_gb = QGroupBox(self)
        self.cfg_debug_options_gb.setTitle('Debug options')
        self.column2_layout.addWidget(self.cfg_debug_options_gb)
        self.cfg_debug_options_qvl = QVBoxLayout(self.cfg_debug_options_gb)

        # ++++++++ Debug logging checkboxes ++++++++
        self.debug_plugin_checkbox = QCheckBox('Enable debug logging for Marvin XD')
        self.debug_plugin_checkbox.setObjectName('debug_plugin_checkbox')
        self.debug_plugin_checkbox.setToolTip('Print plugin diagnostic messages to console')
        self.cfg_debug_options_qvl.addWidget(self.debug_plugin_checkbox)

        self.debug_libimobiledevice_checkbox = QCheckBox('Enable debug logging for libiMobileDevice')
        self.debug_libimobiledevice_checkbox.setObjectName('debug_libimobiledevice_checkbox')
        self.debug_libimobiledevice_checkbox.setToolTip('Print libiMobileDevice diagnostic messages to console')
        self.cfg_debug_options_qvl.addWidget(self.debug_libimobiledevice_checkbox)

        self.spacerItem2 = QSpacerItem(20, 20, QSizePolicy.Minimum, QSizePolicy.Expanding)
        self.column2_layout.addItem(self.spacerItem2)

        # ~~~~~~~~ End of construction zone ~~~~~~~~
        self.resize(self.sizeHint())

        # ~~~~~~~~ Populate/restore config options ~~~~~~~~
        #  Annotations comboBox
        self.populate_annotations()
        self.populate_collections()
        self.populate_date_read()
        self.populate_locked()
        self.populate_progress()
        self.populate_read()
        self.populate_reading_list()
        self.populate_word_count()

        """
        # Restore Dropbox settings, hook changes
        dropbox_syncing = self.prefs.get('dropbox_syncing', False)
        self.dropbox_syncing_checkbox.setChecked(dropbox_syncing)
        self.set_dropbox_syncing(dropbox_syncing)
        self.dropbox_syncing_checkbox.clicked.connect(partial(self.set_dropbox_syncing))
        self.dropbox_location_lineedit.setText(self.prefs.get('dropbox_folder', ''))
        """

        # Restore general settings
        self.duplicate_markers_checkbox.setChecked(self.prefs.get('apply_markers_to_duplicates', True))
        self.updated_markers_checkbox.setChecked(self.prefs.get('apply_markers_to_updated', True))
        self.auto_refresh_checkbox.setChecked(self.prefs.get('auto_refresh_at_startup', False))
        self.reading_progress_checkbox.setChecked(self.prefs.get('show_progress_as_percentage', False))

        # Restore debug settings, hook changes
        self.debug_plugin_checkbox.setChecked(self.prefs.get('debug_plugin', False))
        self.debug_plugin_checkbox.stateChanged.connect(self.set_restart_required)
        self.debug_libimobiledevice_checkbox.setChecked(self.prefs.get('debug_libimobiledevice', False))
        self.debug_libimobiledevice_checkbox.stateChanged.connect(self.set_restart_required)

        # Hook changes to Annotations comboBox
#         self.annotations_field_comboBox.currentIndexChanged.connect(
#             partial(self.save_combobox_setting, 'annotations_field_comboBox'))
        self.connect(self.annotations_field_comboBox,
                     SIGNAL('currentIndexChanged(const QString &)'),
                     self.annotations_destination_changed)

        # Launch the annotated_books_scanner
        field = get_cc_mapping('annotations', 'field', None)
        self.annotated_books_scanner = InventoryAnnotatedBooks(self.gui, field)
        self.connect(self.annotated_books_scanner, self.annotated_books_scanner.signal,
            self.inventory_complete)
        QTimer.singleShot(1, self.start_inventory)

    def annotations_destination_changed(self, qs_new_destination_name):
        '''
        If the destination field changes, move all existing annotations from old to new
        '''
        self._log_location(str(qs_new_destination_name))
        #self._log("self.eligible_annotations_fields: %s" % self.eligible_annotations_fields)

        old_destination_field = get_cc_mapping('annotations', 'field', None)
        old_destination_name = get_cc_mapping('annotations', 'combobox', None)

        self._log("old_destination_field: %s" % old_destination_field)
        self._log("old_destination_name: %s" % old_destination_name)

        new_destination_name = unicode(qs_new_destination_name)
        self._log("new_destination_name: %s" % repr(new_destination_name))

        if old_destination_name == new_destination_name:
            self._log_location("old_destination_name = new_destination_name, no changes")
            return

        if new_destination_name == '':
            self._log_location("annotations storage disabled")
            set_cc_mapping('annotations', field=None, combobox=new_destination_name)
            return

        new_destination_field = self.eligible_annotations_fields[new_destination_name]

        if existing_annotations(self.parent, old_destination_field):
            command = self.launch_new_destination_dialog(old_destination_name, new_destination_name)

            if command == 'move':
                set_cc_mapping('annotations', field=new_destination_field, combobox=new_destination_name)

                if self.annotated_books_scanner.isRunning():
                    self.annotated_books_scanner.wait()
                move_annotations(self, self.annotated_books_scanner.annotation_map,
                    old_destination_field, new_destination_field)

            elif command == 'change':
                # Keep the updated destination field, but don't move annotations
                pass

            elif command == 'cancel':
                # Restore previous destination
                self.annotations_field_comboBox.blockSignals(True)
                old_index = self.annotations_field_comboBox.findText(old_destination_name)
                self.annotations_field_comboBox.setCurrentIndex(old_index)
                self.annotations_field_comboBox.blockSignals(False)

        else:
            # No existing annotations, just update prefs
            self._log("no existing annotations, updating destination to '{0}'".format(new_destination_name))
            set_cc_mapping('annotations', field=new_destination_field, combobox=new_destination_name)

    def configure_appearance(self):
        '''
        '''
        self._log_location()
        appearance_settings = {
                                'appearance_css': default_elements,
                                'appearance_hr_checkbox': False,
                                'appearance_timestamp_format': default_timestamp
                              }

        # Save, hash the original settings
        original_settings = {}
        osh = hashlib.md5()
        for setting in appearance_settings:
            original_settings[setting] = plugin_prefs.get(setting, appearance_settings[setting])
            osh.update(repr(plugin_prefs.get(setting, appearance_settings[setting])))

        # Display the Annotations appearance dialog
        aa = AnnotationsAppearance(self, self.annotations_icon, plugin_prefs)
        cancelled = False
        if aa.exec_():
            # appearance_hr_checkbox and appearance_timestamp_format changed live to prefs during previews
            plugin_prefs.set('appearance_css', aa.elements_table.get_data())
            # Generate a new hash
            nsh = hashlib.md5()
            for setting in appearance_settings:
                nsh.update(repr(plugin_prefs.get(setting, appearance_settings[setting])))
        else:
            for setting in appearance_settings:
                plugin_prefs.set(setting, original_settings[setting])
            nsh = osh

        # If there were changes, and there are existing annotations,
        # and there is an active Annotations field, offer to re-render
        field = get_cc_mapping('annotations', 'field', None)
        if osh.digest() != nsh.digest() and existing_annotations(self.parent, field):
            title = 'Update annotations?'
            msg = '<p>Update existing annotations to new appearance settings?</p>'
            d = MessageBox(MessageBox.QUESTION,
                           title, msg,
                           show_copy_button=False)
            self._log_location("QUESTION: %s" % msg)
            if d.exec_():
                self._log_location("Updating existing annotations to modified appearance")

                # Wait for indexing to complete
                while not self.annotated_books_scanner.isFinished():
                    Application.processEvents()

                move_annotations(self, self.annotated_books_scanner.annotation_map,
                    field, field, window_title="Updating appearance")

    def edit_css(self):
        '''
        '''
        self._log_location()
        from calibre_plugins.marvin_manager.book_status import dialog_resources_path
        klass = os.path.join(dialog_resources_path, 'css_editor.py')
        if os.path.exists(klass):
            sys.path.insert(0, dialog_resources_path)
            this_dc = importlib.import_module('css_editor')
            sys.path.remove(dialog_resources_path)
            dlg = this_dc.CSSEditorDialog(self, 'css_editor')
            dlg.initialize(self)
            dlg.exec_()

    def get_eligible_custom_fields(self, eligible_types=[], is_multiple=None):
        '''
        Discover qualifying custom fields for eligible_types[]
        '''
        #self._log_location(eligible_types)

        eligible_custom_fields = {}
        for cf in self.gui.current_db.custom_field_keys():
            cft = self.gui.current_db.metadata_for_field(cf)['datatype']
            cfn = self.gui.current_db.metadata_for_field(cf)['name']
            cfim = self.gui.current_db.metadata_for_field(cf)['is_multiple']
            #self._log("cf: %s  cft: %s  cfn: %s cfim: %s" % (cf, cft, cfn, cfim))
            if cft in eligible_types:
                if is_multiple is not None:
                    if bool(cfim) == is_multiple:
                        eligible_custom_fields[cfn] = cf
                else:
                    eligible_custom_fields[cfn] = cf
        return eligible_custom_fields

    def inventory_complete(self, msg):
        self._log_location(msg)

    def launch_cc_wizard(self, column_type):
        '''
        '''
        def _update_combo_box(comboBox, destination, previous):
            '''
            '''
            cb = getattr(self, comboBox)
            cb.blockSignals(True)
            all_items = [str(cb.itemText(i))
                         for i in range(cb.count())]
            if previous and previous in all_items:
                all_items.remove(previous)
            all_items.append(destination)

            cb.clear()
            cb.addItems(sorted(all_items, key=lambda s: s.lower()))

            # Select the new destination in the comboBox
            idx = cb.findText(destination)
            if idx > -1:
                cb.setCurrentIndex(idx)

            cb.blockSignals(False)

        from calibre_plugins.marvin_manager.book_status import dialog_resources_path

        klass = os.path.join(dialog_resources_path, 'cc_wizard.py')
        if os.path.exists(klass):
            #self._log("importing CC Wizard dialog from '%s'" % klass)
            sys.path.insert(0, dialog_resources_path)
            this_dc = importlib.import_module('cc_wizard')
            sys.path.remove(dialog_resources_path)
            dlg = this_dc.CustomColumnWizard(self,
                                             column_type,
                                             self.WIZARD_PROFILES[column_type],
                                             verbose=True)
            dlg.exec_()

            if dlg.modified_column:
                self._log("modified_column: %s" % dlg.modified_column)

                self.restart_required = True

                destination = dlg.modified_column['destination']
                label = dlg.modified_column['label']
                previous = dlg.modified_column['previous']
                source = dlg.modified_column['source']

                if source == "Annotations":
                    _update_combo_box("annotations_field_comboBox", destination, previous)

                    # Add/update the new destination so save_settings() can find it
                    self.eligible_annotations_fields[destination] = label

                    # Save manually in case user cancels
                    set_cc_mapping('annotations', combobox=destination, field=label)

                elif source == 'Collections':
                    _update_combo_box("collection_field_comboBox", destination, previous)

                    # Add/update the new destination so save_settings() can find it
                    self.eligible_collection_fields[destination] = label

                    # Save manually in case user cancels
                    set_cc_mapping('collections', combobox=destination, field=label)

                elif source == 'Last read':
                    _update_combo_box("date_read_field_comboBox", destination, previous)

                    # Add/update the new destination so save_settings() can find it
                    self.eligible_date_read_fields[destination] = label

                    # Save manually in case user cancels
                    set_cc_mapping('date_read', combobox=destination, field=label)

                elif source == 'Locked':
                    _update_combo_box("locked_field_comboBox", destination, previous)

                    # Add/update the new destination so save_settings() can find it
                    self.eligible_locked_fields[destination] = label

                    # Save manually in case user cancels
                    set_cc_mapping('locked', combobox=destination, field=label)

                elif source == "Progress":
                    _update_combo_box("progress_field_comboBox", destination, previous)

                    # Add/update the new destination so save_settings() can find it
                    self.eligible_progress_fields[destination] = label

                    # Save manually in case user cancels
                    set_cc_mapping('progress', combobox=destination, field=label)

                elif source == "Read":
                    _update_combo_box("read_field_comboBox", destination, previous)

                    # Add/update the new destination so save_settings() can find it
                    self.eligible_read_fields[destination] = label

                    # Save manually in case user cancels
                    set_cc_mapping('read', combobox=destination, field=label)

                elif source == "Reading list":
                    _update_combo_box("reading_list_field_comboBox", destination, previous)

                    # Add/update the new destination so save_settings() can find it
                    self.eligible_reading_list_fields[destination] = label

                    # Save manually in case user cancels
                    set_cc_mapping('reading_list', combobox=destination, field=label)

                elif source == "Word count":
                    _update_combo_box("word_count_field_comboBox", destination, previous)

                    # Add/update the new destination so save_settings() can find it
                    self.eligible_word_count_fields[destination] = label

                    # Save manually in case user cancels
                    set_cc_mapping('word_count', combobox=destination, field=label)
        else:
            self._log("ERROR: Can't import from '%s'" % klass)

    def launch_new_destination_dialog(self, old, new):
        '''
        Return 'move', 'change' or 'cancel'
        '''
        from calibre_plugins.marvin_manager.book_status import dialog_resources_path
        self._log_location()
        klass = os.path.join(dialog_resources_path, 'new_destination.py')
        if os.path.exists(klass):
            self._log("importing new destination dialog from '%s'" % klass)
            sys.path.insert(0, dialog_resources_path)
            this_dc = importlib.import_module('new_destination')
            sys.path.remove(dialog_resources_path)
            dlg = this_dc.NewDestinationDialog(self, old, new)
            dlg.exec_()
            return dlg.command

    def populate_annotations(self):
        datatype = self.WIZARD_PROFILES['Annotations']['datatype']
        self.eligible_annotations_fields = self.get_eligible_custom_fields([datatype])
        self.annotations_field_comboBox.addItems([''])
        ecf = sorted(self.eligible_annotations_fields.keys(), key=lambda s: s.lower())
        self.annotations_field_comboBox.addItems(ecf)

        # Retrieve stored value
        existing = get_cc_mapping('annotations', 'combobox')
        if existing:
            ci = self.annotations_field_comboBox.findText(existing)
            self.annotations_field_comboBox.setCurrentIndex(ci)

    def populate_collections(self):
        datatype = self.WIZARD_PROFILES['Collections']['datatype']
        self.eligible_collection_fields = self.get_eligible_custom_fields([datatype],
                                                                          is_multiple=True)
        self.collection_field_comboBox.addItems([''])
        ecf = sorted(self.eligible_collection_fields.keys(), key=lambda s: s.lower())
        self.collection_field_comboBox.addItems(ecf)

        # Retrieve stored value
        existing = get_cc_mapping('collections', 'combobox')
        if existing:
            ci = self.collection_field_comboBox.findText(existing)
            self.collection_field_comboBox.setCurrentIndex(ci)

    def populate_date_read(self):
        #self.eligible_date_read_fields = self.get_eligible_custom_fields(['datetime'])
        datatype = self.WIZARD_PROFILES['Last read']['datatype']
        self.eligible_date_read_fields = self.get_eligible_custom_fields([datatype])
        self.date_read_field_comboBox.addItems([''])
        ecf = sorted(self.eligible_date_read_fields.keys(), key=lambda s: s.lower())
        self.date_read_field_comboBox.addItems(ecf)

        # Retrieve stored value
        existing = get_cc_mapping('date_read', 'combobox')
        if existing:
            ci = self.date_read_field_comboBox.findText(existing)
            self.date_read_field_comboBox.setCurrentIndex(ci)

    def populate_locked(self):
        datatype = self.WIZARD_PROFILES['Locked']['datatype']
        self.eligible_locked_fields = self.get_eligible_custom_fields([datatype])
        self.locked_field_comboBox.addItems([''])
        ecf = sorted(self.eligible_locked_fields.keys(), key=lambda s: s.lower())
        self.locked_field_comboBox.addItems(ecf)

        # Retrieve stored value
        existing = get_cc_mapping('locked', 'combobox')
        if existing:
            ci = self.locked_field_comboBox.findText(existing)
            self.locked_field_comboBox.setCurrentIndex(ci)

    def populate_progress(self):
        #self.eligible_progress_fields = self.get_eligible_custom_fields(['float'])
        datatype = self.WIZARD_PROFILES['Progress']['datatype']
        self.eligible_progress_fields = self.get_eligible_custom_fields([datatype])
        self.progress_field_comboBox.addItems([''])
        ecf = sorted(self.eligible_progress_fields.keys(), key=lambda s: s.lower())
        self.progress_field_comboBox.addItems(ecf)

        # Retrieve stored value
        existing = get_cc_mapping('progress', 'combobox')
        if existing:
            ci = self.progress_field_comboBox.findText(existing)
            self.progress_field_comboBox.setCurrentIndex(ci)

    def populate_read(self):
        datatype = self.WIZARD_PROFILES['Read']['datatype']
        self.eligible_read_fields = self.get_eligible_custom_fields([datatype])
        self.read_field_comboBox.addItems([''])
        ecf = sorted(self.eligible_read_fields.keys(), key=lambda s: s.lower())
        self.read_field_comboBox.addItems(ecf)

        # Retrieve stored value
        existing = get_cc_mapping('read', 'combobox')
        if existing:
            ci = self.read_field_comboBox.findText(existing)
            self.read_field_comboBox.setCurrentIndex(ci)

    def populate_reading_list(self):
        datatype = self.WIZARD_PROFILES['Reading list']['datatype']
        self.eligible_reading_list_fields = self.get_eligible_custom_fields([datatype])
        self.reading_list_field_comboBox.addItems([''])
        ecf = sorted(self.eligible_reading_list_fields.keys(), key=lambda s: s.lower())
        self.reading_list_field_comboBox.addItems(ecf)

        # Retrieve stored value
        existing = get_cc_mapping('reading_list', 'combobox')
        if existing:
            ci = self.reading_list_field_comboBox.findText(existing)
            self.reading_list_field_comboBox.setCurrentIndex(ci)

    def populate_word_count(self):
        #self.eligible_word_count_fields = self.get_eligible_custom_fields(['int'])
        datatype = self.WIZARD_PROFILES['Word count']['datatype']
        self.eligible_word_count_fields = self.get_eligible_custom_fields([datatype])
        self.word_count_field_comboBox.addItems([''])
        ecf = sorted(self.eligible_word_count_fields.keys(), key=lambda s: s.lower())
        self.word_count_field_comboBox.addItems(ecf)

        # Retrieve stored value
        existing = get_cc_mapping('word_count', 'combobox')
        if existing:
            ci = self.word_count_field_comboBox.findText(existing)
            self.word_count_field_comboBox.setCurrentIndex(ci)

    """
    def select_dropbox_folder(self):
        '''
        '''
        self._log_location()
        dropbox_location = QFileDialog.getExistingDirectory(
            self,
            "Dropbox folder",
            os.path.expanduser("~"),
            QFileDialog.ShowDirsOnly | QFileDialog.DontResolveSymlinks)
        self.dropbox_location_lineedit.setText(unicode(dropbox_location))

    def set_dropbox_syncing(self, state):
        '''
        Called when checkbox changes state, or when restoring state
        Set enabled state of Dropbox folder picker to match
        '''
        self.cfg_dropbox_folder_toolbutton.setEnabled(state)
        self.dropbox_location_lineedit.setEnabled(state)
    """

    def set_restart_required(self, state):
        '''
        Set restart_required flag to show show dialog when closing dialog
        '''
        self.restart_required = True

    """
    def save_combobox_setting(self, cb, index):
        '''
        Apply changes immediately
        '''
        cf = str(getattr(self, cb).currentText())
        self._log_location("%s => %s" % (cb, repr(cf)))

        if cb == 'annotations_field_comboBox':
            field = None
            if cf:
                field = self.eligible_annotations_fields[cf]
            set_cc_mapping('annotations', combobox=cf, field=field)
    """

    def save_settings(self):
        self._log_location()

        # Annotations field
        cf = unicode(self.annotations_field_comboBox.currentText())
        field = None
        if cf:
            field = self.eligible_annotations_fields[cf]
        set_cc_mapping('annotations', combobox=cf, field=field)

        # Collections field
        cf = unicode(self.collection_field_comboBox.currentText())
        field = None
        if cf:
            field = self.eligible_collection_fields[cf]
        set_cc_mapping('collections', combobox=cf, field=field)

        # Date read field
        cf = unicode(self.date_read_field_comboBox.currentText())
        field = None
        if cf:
            field = self.eligible_date_read_fields[cf]
        set_cc_mapping('date_read', combobox=cf, field=field)

        # Locked field
        cf = unicode(self.locked_field_comboBox.currentText())
        field = None
        if cf:
            field = self.eligible_locked_fields[cf]
        set_cc_mapping('locked', combobox=cf, field=field)

        # Progress field
        cf = unicode(self.progress_field_comboBox.currentText())
        field = None
        if cf:
            field = self.eligible_progress_fields[cf]
        set_cc_mapping('progress', combobox=cf, field=field)

        # Read field
        cf = unicode(self.read_field_comboBox.currentText())
        field = None
        if cf:
            field = self.eligible_read_fields[cf]
        set_cc_mapping('read', combobox=cf, field=field)

        # Reading list field
        cf = unicode(self.reading_list_field_comboBox.currentText())
        field = None
        if cf:
            field = self.eligible_reading_list_fields[cf]
        set_cc_mapping('reading_list', combobox=cf, field=field)

        # Word count field
        cf = unicode(self.word_count_field_comboBox.currentText())
        field = None
        if cf:
            field = self.eligible_word_count_fields[cf]
        set_cc_mapping('word_count', combobox=cf, field=field)

        '''
        # Save Dropbox settings
        self.prefs.set('dropbox_syncing', self.dropbox_syncing_checkbox.isChecked())
        self.prefs.set('dropbox_folder', unicode(self.dropbox_location_lineedit.text()))
        '''

        # Save general settings
        self.prefs.set('apply_markers_to_duplicates', self.duplicate_markers_checkbox.isChecked())
        self.prefs.set('apply_markers_to_updated', self.updated_markers_checkbox.isChecked())
        self.prefs.set('auto_refresh_at_startup', self.auto_refresh_checkbox.isChecked())
        self.prefs.set('show_progress_as_percentage', self.reading_progress_checkbox.isChecked())

        # Save debug settings
        self.prefs.set('debug_plugin', self.debug_plugin_checkbox.isChecked())
        self.prefs.set('debug_libimobiledevice', self.debug_libimobiledevice_checkbox.isChecked())

        # If restart needed, inform user
        if self.restart_required:
            do_restart = show_restart_warning('Restart calibre for the changes to be applied.',
                                              parent=self.gui)
            if do_restart:
                self.gui.quit(restart=True)

    def start_inventory(self):
        self._log_location()
        self.annotated_books_scanner.start()
コード例 #39
0
class ProgressBar(QDialog, Logger):
    def __init__(
        self,
        parent=None,
        max_items=100,
        window_title="Progress Bar",
        label="Label goes here",
        frameless=True,
        on_top=False,
    ):
        if on_top:
            _flags = Qt.WindowStaysOnTopHint
            if frameless:
                _flags |= Qt.FramelessWindowHint
            QDialog.__init__(self, parent=parent, flags=_flags)
        else:
            _flags = Qt.Dialog
            if frameless:
                _flags |= Qt.FramelessWindowHint
            QDialog.__init__(self, parent=parent, flags=_flags)
        self.application = Application
        self.setWindowTitle(window_title)
        self.l = QVBoxLayout(self)
        self.setLayout(self.l)

        self.label = QLabel(label)
        self.label.setAlignment(Qt.AlignHCenter)
        self.l.addWidget(self.label)

        self.progressBar = QProgressBar(self)
        self.progressBar.setRange(0, max_items)
        self.progressBar.setMinimum(0)
        self.progressBar.setMaximum(0)
        self.progressBar.setValue(0)
        self.l.addWidget(self.progressBar)

        self.close_requested = False

    def closeEvent(self, event):
        self._log_location()
        self.close_requested = True

    def increment(self):
        self.progressBar.setValue(self.progressBar.value() + 1)
        self.refresh()

    def refresh(self):
        self.application.processEvents()

    def set_label(self, value):
        self.label.setText(value)
        self.label.repaint()
        self.refresh()

    def set_maximum(self, value):
        self.progressBar.setMaximum(value)
        self.refresh()

    def set_value(self, value):
        self.progressBar.setValue(value)
        self.progressBar.repaint()
        self.refresh()
コード例 #40
0
    def __init__(self,
                 parent=None,
                 desc=None,
                 name=None,
                 modal=0,
                 fl=0,
                 env=None,
                 type="QDialog"):
        if env is None:
            import foundation.env as env  # this is a little weird... probably it'll be ok, and logically it seems correct.

        self.desc = desc

        self.typ = type
        if type == "QDialog":
            QDialog.__init__(self, parent, name, modal, fl)
        elif type == "QTextEdit":
            QTextEdit.__init__(self, parent, name)
        elif type == "QFrame":
            QFrame.__init__(self, parent, name)
        else:
            print "don't know about type == %r" % (type, )

        self.image1 = QPixmap()
        self.image1.loadFromData(image1_data,
                                 "PNG")  # should be: title_icon ####
        self.image3 = QPixmap()
        self.image3.loadFromData(image3_data, "PNG")
        self.image4 = QPixmap()
        self.image4.loadFromData(image4_data, "PNG")
        self.image5 = QPixmap()
        self.image5.loadFromData(image5_data, "PNG")
        self.image6 = QPixmap()
        self.image6.loadFromData(image6_data, "PNG")
        self.image7 = QPixmap()
        self.image7.loadFromData(image7_data, "PNG")
        self.image0 = QPixmap(image0_data)  # should be: border_icon ####
        self.image2 = QPixmap(image2_data)  # should be: sponsor_pixmap ####

        try:
            ####@@@@
            title_icon_name = self.desc.options.get('title_icon')
            border_icon_name = self.desc.options.get('border_icon')
            if title_icon_name:
                self.image1 = imagename_to_pixmap(
                    title_icon_name)  ###@@@ pass icon_path
                ###@@@ import imagename_to_pixmap or use env function
                # or let that func itself be an arg, or have an env arg for it
                ###e rename it icon_name_to_pixmap, or find_icon? (the latter only if it's ok if it returns an iconset)
                ###e use iconset instead?
            if border_icon_name:
                self.image0 = imagename_to_pixmap(border_icon_name)
        except:
            print_compact_traceback(
                "bug in icon-setting code, using fallback icons: ")
            pass

        if not name:
            self.setName("parameter_dialog_or_frame")  ###

        ###k guess this will need: if type == 'QDialog'
        self.setIcon(self.image0)  # should be: border_icon ####

        nanotube_dialogLayout = QVBoxLayout(self, 0, 0,
                                            "nanotube_dialogLayout")

        self.heading_frame = QFrame(self, "heading_frame")
        self.heading_frame.setPaletteBackgroundColor(QColor(122, 122, 122))
        self.heading_frame.setFrameShape(QFrame.NoFrame)
        self.heading_frame.setFrameShadow(QFrame.Plain)
        heading_frameLayout = QHBoxLayout(self.heading_frame, 0, 3,
                                          "heading_frameLayout")

        self.heading_pixmap = QLabel(self.heading_frame, "heading_pixmap")
        self.heading_pixmap.setSizePolicy(
            QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed, 0, 0,
                        self.heading_pixmap.sizePolicy().hasHeightForWidth()))
        self.heading_pixmap.setPixmap(
            self.image1)  # should be: title_icon ####
        self.heading_pixmap.setScaledContents(1)
        heading_frameLayout.addWidget(self.heading_pixmap)

        self.heading_label = QLabel(self.heading_frame, "heading_label")
        self.heading_label.setPaletteForegroundColor(QColor(255, 255, 255))
        heading_label_font = QFont(self.heading_label.font())
        heading_label_font.setPointSize(12)
        heading_label_font.setBold(1)
        self.heading_label.setFont(heading_label_font)
        heading_frameLayout.addWidget(self.heading_label)
        nanotube_dialogLayout.addWidget(self.heading_frame)

        self.body_frame = QFrame(self, "body_frame")
        self.body_frame.setFrameShape(QFrame.StyledPanel)
        self.body_frame.setFrameShadow(QFrame.Raised)
        body_frameLayout = QVBoxLayout(self.body_frame, 3, 3,
                                       "body_frameLayout")

        self.sponsor_frame = QFrame(self.body_frame, "sponsor_frame")
        self.sponsor_frame.setPaletteBackgroundColor(QColor(255, 255, 255))
        self.sponsor_frame.setFrameShape(QFrame.StyledPanel)
        self.sponsor_frame.setFrameShadow(QFrame.Raised)
        sponsor_frameLayout = QHBoxLayout(self.sponsor_frame, 0, 0,
                                          "sponsor_frameLayout")

        self.sponsor_btn = QPushButton(self.sponsor_frame, "sponsor_btn")
        self.sponsor_btn.setAutoDefault(0)  #bruce 060703 bugfix
        self.sponsor_btn.setSizePolicy(
            QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred, 0, 0,
                        self.sponsor_btn.sizePolicy().hasHeightForWidth()))
        self.sponsor_btn.setPaletteBackgroundColor(QColor(255, 255, 255))
        self.sponsor_btn.setPixmap(
            self.image2
        )  # should be: sponsor_pixmap #### [also we'll need to support >1 sponsor]
        self.sponsor_btn.setFlat(1)
        sponsor_frameLayout.addWidget(self.sponsor_btn)
        body_frameLayout.addWidget(self.sponsor_frame)

        layout59 = QHBoxLayout(None, 0, 6, "layout59")
        left_spacer = QSpacerItem(20, 20, QSizePolicy.Expanding,
                                  QSizePolicy.Minimum)
        layout59.addItem(left_spacer)

        self.done_btn = QToolButton(self.body_frame, "done_btn")
        self.done_btn.setIcon(QIcon(self.image3))
        layout59.addWidget(self.done_btn)

        self.abort_btn = QToolButton(self.body_frame, "abort_btn")
        self.abort_btn.setIcon(QIcon(self.image4))
        layout59.addWidget(self.abort_btn)

        self.preview_btn = QToolButton(self.body_frame, "preview_btn")
        self.preview_btn.setIcon(QIcon(self.image5))
        layout59.addWidget(self.preview_btn)

        self.whatsthis_btn = QToolButton(self.body_frame, "whatsthis_btn")
        self.whatsthis_btn.setIcon(QIcon(self.image6))
        layout59.addWidget(self.whatsthis_btn)
        right_spacer = QSpacerItem(20, 20, QSizePolicy.Expanding,
                                   QSizePolicy.Minimum)
        layout59.addItem(right_spacer)
        body_frameLayout.addLayout(layout59)

        self.groups = []
        self.param_getters = {
        }  # map from param name to get-function (which gets current value out of its widget or controller)

        for group_desc in self.desc.kids('group'):

            # == start parameters_grpbox ### this will differ for Windows style

            header_refs = [
            ]  # keep python refcounted refs to all objects we make (at least the ones pyuic stored in self attrs)

            self.parameters_grpbox = QGroupBox(self.body_frame,
                                               "parameters_grpbox")
            self.parameters_grpbox.setFrameShape(QGroupBox.StyledPanel)
            self.parameters_grpbox.setFrameShadow(QGroupBox.Sunken)
            self.parameters_grpbox.setMargin(0)
            self.parameters_grpbox.setColumnLayout(0, Qt.Vertical)
            self.parameters_grpbox.layout().setSpacing(1)
            self.parameters_grpbox.layout().setMargin(4)
            parameters_grpboxLayout = QVBoxLayout(
                self.parameters_grpbox.layout())
            parameters_grpboxLayout.setAlignment(Qt.AlignTop)

            layout20 = QHBoxLayout(None, 0, 6, "layout20")

            self.nt_parameters_grpbtn = QPushButton(self.parameters_grpbox,
                                                    "nt_parameters_grpbtn")
            self.nt_parameters_grpbtn.setSizePolicy(
                QSizePolicy(
                    QSizePolicy.Minimum, QSizePolicy.Fixed, 0, 0,
                    self.nt_parameters_grpbtn.sizePolicy().hasHeightForWidth())
            )
            self.nt_parameters_grpbtn.setMaximumSize(QSize(16, 16))
            self.nt_parameters_grpbtn.setAutoDefault(0)
            self.nt_parameters_grpbtn.setIcon(QIcon(
                self.image7))  ### not always right, but doesn't matter
            self.nt_parameters_grpbtn.setFlat(1)
            layout20.addWidget(self.nt_parameters_grpbtn)

            self.parameters_grpbox_label = QLabel(self.parameters_grpbox,
                                                  "parameters_grpbox_label")
            self.parameters_grpbox_label.setSizePolicy(
                QSizePolicy(
                    QSizePolicy.Preferred, QSizePolicy.Minimum, 0, 0,
                    self.parameters_grpbox_label.sizePolicy().
                    hasHeightForWidth()))
            self.parameters_grpbox_label.setAlignment(QLabel.AlignVCenter)
            layout20.addWidget(self.parameters_grpbox_label)
            gbx_spacer1 = QSpacerItem(67, 16, QSizePolicy.Expanding,
                                      QSizePolicy.Minimum)
            layout20.addItem(gbx_spacer1)
            parameters_grpboxLayout.addLayout(layout20)

            nt_parameters_body_layout = QGridLayout(
                None, 1, 1, 0, 6, "nt_parameters_body_layout"
            )  ### what is 6 -- is it related to number of items???
            # is it 6 in all the ones we got, but that could be a designer error so i better look it up sometime.

            # == start its kids

            # will use from above: self.parameters_grpbox, nt_parameters_body_layout

            nextrow = 0  # which row of the QGridLayout to start filling next (loop variable)
            hidethese = [
            ]  # set of objects to hide or show, when this group is closed or opened

            for param in group_desc.kids('parameter'):
                # param (a group subobj desc) is always a parameter, but we already plan to extend this beyond that,
                # so we redundantly test for this here.
                getter = None
                paramname = None
                # set these for use by uniform code at the end (e.g. for tooltips)
                editfield = None
                label = None
                if param.isa('parameter'):
                    label = QLabel(self.parameters_grpbox, "members_label")
                    label.setAlignment(QLabel.AlignVCenter | QLabel.AlignRight)
                    nt_parameters_body_layout.addWidget(label, nextrow, 0)
                    hidethese.append(label)
                    thisrow = nextrow
                    nextrow += 1
                    #e following should be known in a place that knows the input language, not here
                    paramname = param.options.get('name') or (
                        param.args and param.args[0]) or "?"
                    paramlabel = param.options.get(
                        'label'
                    ) or paramname  ##e wrong, label "" or none ought to be possible
                    # QtGui.QApplication.translate(self.__class__.__name__, "xyz")
                    label.setText(
                        QtGui.QApplication.translate(self.__class__.__name__,
                                                     paramlabel))

                if param.isa('parameter',
                             widget='combobox',
                             type=('str', None)):
                    self.members_combox = QComboBox(
                        0, self.parameters_grpbox,
                        "members_combox")  ###k  what's 0?
                    editfield = self.members_combox
                    #### it probably needs a handler class, and then that could do this setup
                    self.members_combox.clear()
                    default = param.options.get(
                        'default', None)  # None is not equal to any string
                    thewidgetkid = param.kids(
                        'widget'
                    )[-1]  # kluge; need to think what the desc method for this should be
                    for item in thewidgetkid.kids('item'):
                        itemval = item.args[0]
                        itemtext = itemval
                        self.members_combox.insertItem(
                            QtGui.QApplication.translate(
                                self.__class__.__name__,
                                itemtext))  #k __tr ok??
                        if itemval == default:  #k or itemtext?
                            pass  ##k i find no setItem in our py code, so not sure yet what to do for this.
                    nt_parameters_body_layout.addWidget(
                        self.members_combox, thisrow, 1)
                    hidethese.append(self.members_combox)
                    getter = (lambda combobox=self.members_combox: str(
                        combobox.currentText()))
                    ##e due to __tr or non-str values, it might be better to use currentIndex and look it up in a table
                    # (though whether __tr is good here might depend on what it's used for)

                elif param.isa('parameter',
                               widget=('lineedit', None),
                               type=('str', None)):
                    # this covers explicit str|lineedit, and 3 default cases str, lineedit, neither.
                    # (i.e. if you say parameter and nothing else, it's str lineedit by default.)
                    self.length_linedit = QLineEdit(self.parameters_grpbox,
                                                    "length_linedit")
                    editfield = self.length_linedit
                    nt_parameters_body_layout.addWidget(
                        self.length_linedit, thisrow, 1)
                    hidethese.append(self.length_linedit)
                    default = str(param.options.get('default', ""))
                    self.length_linedit.setText(
                        QtGui.QApplication.translate(self.__class__.__name__,
                                                     default))  # __tr ok?
                    getter = (lambda lineedit=self.length_linedit: str(
                        lineedit.text()))

                elif param.isa('parameter',
                               widget=('lineedit', None),
                               type='float'):
                    self.length_linedit = QLineEdit(self.parameters_grpbox,
                                                    "length_linedit")
                    editfield = self.length_linedit
                    nt_parameters_body_layout.addWidget(
                        self.length_linedit, thisrow, 1)
                    hidethese.append(self.length_linedit)
                    controller = FloatLineeditController_Qt(
                        self, param, self.length_linedit)
                    header_refs.append(controller)
                    getter = controller.get_value

                elif param.isa('parameter', widget = ('spinbox', None), type = 'int') or \
                     param.isa('parameter', widget = ('spinbox'), type = None):
                    self.chirality_N_spinbox = QSpinBox(
                        self.parameters_grpbox, "chirality_N_spinbox"
                    )  # was chirality_m_spinbox, now chirality_N_spinbox
                    editfield = self.chirality_N_spinbox
                    ### seems like Qt defaults for min and max are 0,100 -- way too small a range!
                    if param.options.has_key('min') or 1:
                        self.chirality_N_spinbox.setMinimum(
                            param.options.get('min', -999999999))  # was 0
                    if param.options.has_key('max') or 1:
                        self.chirality_N_spinbox.setMaximum(
                            param.options.get(
                                'max',
                                +999999999))  # wasn't in egcode, but needed
                    self.chirality_N_spinbox.setValue(
                        param.options.get('default', 0))  # was 5
                    ##e note: i suspect this default 0 should come from something that knows this desc grammar.
                    suffix = param.options.get('suffix', '')
                    if suffix:
                        self.chirality_N_spinbox.setSuffix(
                            QtGui.QApplication.translate(
                                self.__class__.__name__, suffix))
                    else:
                        self.chirality_N_spinbox.setSuffix(
                            QString.null)  # probably not needed
                    nt_parameters_body_layout.addWidget(
                        self.chirality_N_spinbox, thisrow, 1)
                    hidethese.append(self.chirality_N_spinbox)
                    getter = self.chirality_N_spinbox.value  # note: it also has .text, which includes suffix

                else:
                    print "didn't match:", param  ###e improve this

                # things done the same way for all kinds of param-editing widgets
                if 1:  #bruce 060703 moved this down here, as bugfix
                    # set tooltip (same one for editfield and label)
                    tooltip = param.options.get('tooltip', '')
                    ###e do it for more kinds of params; share the code somehow; do it in controller, or setup-aid?
                    ###k QToolTip appropriateness; tooltip option might be entirely untested
                    if tooltip and label:
                        QToolTip.add(
                            label,
                            QtGui.QApplication.translate(
                                self.__class__.__name__, tooltip))
                    if tooltip and editfield:
                        QToolTip.add(
                            editfield,
                            QtGui.QApplication.translate(
                                self.__class__.__name__, tooltip)
                        )  ##k ok?? review once not all params have same-row labels.

                if getter and paramname and paramname != '?':
                    self.param_getters[paramname] = getter
                ### also bind these params to actions...
                continue  # next param

            header_refs.extend([
                self.parameters_grpbox, self.nt_parameters_grpbtn,
                self.parameters_grpbox_label
            ])

            # now create the logic/control object for the group
            group = CollapsibleGroupController_Qt(self, group_desc,
                                                  header_refs, hidethese,
                                                  self.nt_parameters_grpbtn)
            ### maybe ask env for the class to use for this?
            self.groups.append(
                group
            )  ### needed?? only for scanning the params, AFAIK -- oh, and to maintain a python refcount.

            # from languageChange:
            if 1:  # i don't know if these are needed:
                self.parameters_grpbox.setTitle(QString.null)
                self.nt_parameters_grpbtn.setText(QString.null)
            self.parameters_grpbox_label.setText(
                QtGui.QApplication.translate(
                    self.__class__.__name__,
                    group_desc.args[0]))  # was "Nanotube Parameters"
            ##e note that it's questionable in the syntax design for this property of a group (overall group label)
            # to be in that position (desc arg 0).

            # == end its kids

            parameters_grpboxLayout.addLayout(nt_parameters_body_layout)
            body_frameLayout.addWidget(self.parameters_grpbox)

            # == end parameters groupbox

            continue  # next group

        nanotube_dialogLayout.addWidget(self.body_frame)
        spacer14 = QSpacerItem(20, 20, QSizePolicy.Minimum,
                               QSizePolicy.Expanding)
        nanotube_dialogLayout.addItem(spacer14)

        layout42 = QHBoxLayout(None, 4, 6, "layout42")
        btm_spacer = QSpacerItem(59, 20, QSizePolicy.Expanding,
                                 QSizePolicy.Minimum)
        layout42.addItem(btm_spacer)

        self.cancel_btn = QPushButton(self, "cancel_btn")
        self.cancel_btn.setAutoDefault(0)  #bruce 060703 bugfix
        layout42.addWidget(self.cancel_btn)

        self.ok_btn = QPushButton(self, "ok_btn")
        self.ok_btn.setAutoDefault(0)  #bruce 060703 bugfix
        layout42.addWidget(self.ok_btn)
        nanotube_dialogLayout.addLayout(layout42)

        self.languageChange()

        self.resize(
            QSize(246, 618).expandedTo(self.minimumSizeHint())
        )  ### this size will need to be adjusted (guess -- it's only place overall size is set)
        qt4todo('self.clearWState(Qt.WState_Polished)')

        ## self.connect(self.nt_parameters_grpbtn,SIGNAL("clicked()"),self.toggle_nt_parameters_grpbtn) ####

        # new:
        for button, methodname in (
            (self.sponsor_btn,
             'do_sponsor_btn'),  #e generalize to more than one sponsor button
            (self.done_btn, 'do_done_btn'),
            (self.abort_btn, 'do_abort_btn'),
            (self.preview_btn, 'do_preview_btn'),
            (self.whatsthis_btn, 'do_whatsthis_btn'),
            (self.cancel_btn, 'do_cancel_btn'),
            (self.ok_btn, 'do_ok_btn')):
            if hasattr(self, methodname):
                self.connect(button, SIGNAL("clicked()"),
                             getattr(self, methodname))
        return
コード例 #41
0
ファイル: dialogs.py プロジェクト: 12101/dedrm-ebook-tools
    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())
コード例 #42
0
ファイル: dialogs.py プロジェクト: startion2007/DeDRM.Net
    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())
コード例 #43
0
ファイル: dialogs.py プロジェクト: 12101/dedrm-ebook-tools
    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())
コード例 #44
0
ファイル: dialogs.py プロジェクト: startion2007/DeDRM.Net
    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())
コード例 #45
0
ファイル: YaliDialog.py プロジェクト: Pardus-Linux/yali
class InformationWindow(QWidget):

    def __init__(self):
        QWidget.__init__(self, ctx.mainScreen)
        self.setObjectName("InformationWindow")
        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.setFixedHeight(50)
        self.setMaximumWidth(800)
        self.setStyleSheet("""
            QFrame#frame { border: 1px solid rgba(255,255,255,30);
                           /*border-radius: 4px;*/
                           background-color: rgba(0,0,0,100);}

            QLabel { border:none;
                     color:#FFFFFF;}

            QProgressBar { border: 1px solid white;}

            QProgressBar::chunk { background-color: #F1610D;
                                  width: 0.5px;}
        """)

        self.gridlayout = QGridLayout(self)
        self.frame = QFrame(self)
        self.frame.setObjectName("frame")
        self.horizontalLayout = QHBoxLayout(self.frame)
        self.horizontalLayout.setContentsMargins(10, 0, 10, 0)

        # Spinner
        self.spinner = QLabel(self.frame)
        self.spinner.setMinimumSize(QSize(16, 16))
        self.spinner.setMaximumSize(QSize(16, 16))
        self.spinner.setIndent(6)
        self.movie = QMovie(':/images/working.mng')
        self.spinner.setMovie(self.movie)
        self.movie.start()
        self.horizontalLayout.addWidget(self.spinner)

        # Message
        self.label = QLabel(self.frame)
        self.label.setAlignment(Qt.AlignCenter)
        self.label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.icon = QLabel(self.frame)
        self.icon.setFixedWidth(16)
        self.icon.setFixedHeight(16)
        self.horizontalLayout.setSpacing(10)
        self.horizontalLayout.addWidget(self.icon)
        self.horizontalLayout.addWidget(self.label)

        self.gridlayout.addWidget(self.frame,0,0,1,1)

    def update(self, message, type=None, spinner=False):
        fontMetric = self.label.fontMetrics()
        textWidth = fontMetric.width(message)

        if type:
            self.icon.show()
            if type == "error":
                self.icon.setPixmap(QPixmap(":/gui/pics/dialog-error.png"))
                self.setStyleSheet(" QFrame#frame {background-color: rgba(255,0,0,100);} ")

            elif type == "warning":
                self.icon.setPixmap(QPixmap(":/gui/pics/dialog-warning.png"))
                self.setStyleSheet(" QFrame#frame {background-color: rgba(0,0,0,100);} ")

            self.setFixedWidth(textWidth + self.icon.width() + 50)
            self.label.setText(message)

        else:
            self.icon.hide()
            self.setStyleSheet(" QFrame#frame {background-color: rgba(0,0,0,100);} ")
            self.setFixedWidth(textWidth + self.icon.width() + 100)
            self.label.setText(message)

        self.spinner.setVisible(spinner)
        self.move(ctx.mainScreen.width()/2 - self.width()/2,
                  ctx.mainScreen.height() - self.height()/2 - 50)

        self.show()

    def refresh(self):
        ctx.mainScreen.processEvents()

    def show(self):
        QWidget.show(self)
        self.refresh()

    def hide(self):
        QWidget.hide(self)
        self.refresh()
コード例 #46
0
ファイル: GamessJob.py プロジェクト: ematvey/NanoEngineer-1
class JobProgressDialog(QDialog): # review: should any of this be refiled into SimJob? [bruce 071216 Q]
    """
    """
    def __init__(self, process, calculation):
        """
        """
        QDialog.__init__(self, None, None, True) 
        
        self.process = process
        
        self.setCaption("Please Wait")
        
        pbVBLayout = QVBoxLayout(self,11,6,"ProgressBarDialogLayout")

        msgLabel = QLabel(self,"msgLabel")
        msgLabel.setAlignment(QLabel.AlignCenter)
        
        if calculation == 'Energy':
            msgLabel.setText("Calculating Energy ...")
        else:
            msgLabel.setText("Optimizing ...")
        
        pbVBLayout.addWidget(msgLabel)
                      
        self.msgLabel2 = QLabel(self,"msgLabel2")
        self.msgLabel2.setAlignment(QLabel.AlignCenter)
        self.msgLabel2.setText('')
        
        pbVBLayout.addWidget(self.msgLabel2)
        
        cancelButton = QPushButton(self,"canel")
        cancelButton.setText("Cancel")
        
        pbVBLayout.addWidget(cancelButton)
        
        self.resize(QSize(248,146).expandedTo(self.minimumSizeHint()))
        self.connect(cancelButton, SIGNAL("clicked()"), self.reject)
        return
    
    def reject(self):
        """
        """
        if self.process.isRunning():
            self.process.tryTerminate()
            QTimer.singleShot( 5000, self.process, SLOT('kill()') )
            #self.process.kill()
            print "I asked to kill the process."
        return
        
    def getMsgLabel(self):
        return self.msgLabel2
    
    def launchProgressDialog(self):
        """
        """
        stime = time.time()
        self.show()
        while 1:
            env.call_qApp_processEvents()
            if self.Rejected:
                break
            duration = time.time() - stime
            elapmsg = "Elapsed Time: " + hhmmss_str(int(duration))
            self.msgLabel2.setText(elapmsg) 
            time.sleep(0.01)
        return
    
    pass # end of class JobProgressDialog
コード例 #47
0
class JobProgressDialog(
        QDialog
):  # review: should any of this be refiled into SimJob? [bruce 071216 Q]
    """
    """
    def __init__(self, process, calculation):
        """
        """
        QDialog.__init__(self, None, None, True)

        self.process = process

        self.setCaption("Please Wait")

        pbVBLayout = QVBoxLayout(self, 11, 6, "ProgressBarDialogLayout")

        msgLabel = QLabel(self, "msgLabel")
        msgLabel.setAlignment(QLabel.AlignCenter)

        if calculation == 'Energy':
            msgLabel.setText("Calculating Energy ...")
        else:
            msgLabel.setText("Optimizing ...")

        pbVBLayout.addWidget(msgLabel)

        self.msgLabel2 = QLabel(self, "msgLabel2")
        self.msgLabel2.setAlignment(QLabel.AlignCenter)
        self.msgLabel2.setText('')

        pbVBLayout.addWidget(self.msgLabel2)

        cancelButton = QPushButton(self, "canel")
        cancelButton.setText("Cancel")

        pbVBLayout.addWidget(cancelButton)

        self.resize(QSize(248, 146).expandedTo(self.minimumSizeHint()))
        self.connect(cancelButton, SIGNAL("clicked()"), self.reject)
        return

    def reject(self):
        """
        """
        if self.process.isRunning():
            self.process.tryTerminate()
            QTimer.singleShot(5000, self.process, SLOT('kill()'))
            #self.process.kill()
            print "I asked to kill the process."
        return

    def getMsgLabel(self):
        return self.msgLabel2

    def launchProgressDialog(self):
        """
        """
        stime = time.time()
        self.show()
        while 1:
            env.call_qApp_processEvents()
            if self.Rejected:
                break
            duration = time.time() - stime
            elapmsg = "Elapsed Time: " + hhmmss_str(int(duration))
            self.msgLabel2.setText(elapmsg)
            time.sleep(0.01)
        return

    pass  # end of class JobProgressDialog
コード例 #48
0
class AboutDialog(QDialog):
    def __init__(self, parent=None, name=None, modal=0, fl=None):
        if fl is None:
            fl = Qt.Dialog | Qt.WindowTitleHint
        QDialog.__init__(self, parent, Qt.Dialog | Qt.WindowTitleHint)
        self.setModal(modal)

        image0 = pixmaps.tigger_logo.pm()

        # self.setSizeGripEnabled(0)
        LayoutWidget = QWidget(self)
        LayoutWidget.setSizePolicy(QSizePolicy.MinimumExpanding,
                                   QSizePolicy.MinimumExpanding)

        lo_top = QVBoxLayout(LayoutWidget)

        lo_title = QHBoxLayout(None)

        self.title_icon = QLabel(LayoutWidget)
        self.title_icon.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        self.title_icon.setPixmap(image0)
        self.title_icon.setAlignment(Qt.AlignCenter)
        lo_title.addWidget(self.title_icon)

        self.title_label = QLabel(LayoutWidget)
        self.title_label.setWordWrap(True)
        lo_title.addWidget(self.title_label)
        lo_top.addLayout(lo_title)

        lo_logos = QHBoxLayout(None)
        lo_top.addLayout(lo_logos)
        # for logo in ("astron",):
        #   icon = QLabel(LayoutWidget)
        #   icon.setSizePolicy(QSizePolicy.Fixed,QSizePolicy.Fixed)
        #   icon.setPixmap(getattr(pixmaps,logo+"_logo").pm())
        #   icon.setAlignment(Qt.AlignCenter)
        #   lo_logos.addWidget(icon)

        lo_mainbtn = QHBoxLayout(None)
        lo_mainbtn.addItem(
            QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum))
        lo_top.addLayout(lo_mainbtn)

        self.btn_ok = QPushButton(LayoutWidget)
        self.btn_ok.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        self.btn_ok.setMinimumSize(QSize(60, 0))
        self.btn_ok.setAutoDefault(1)
        self.btn_ok.setDefault(1)
        lo_mainbtn.addWidget(self.btn_ok)
        lo_mainbtn.addItem(
            QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum))

        self.languageChange()

        LayoutWidget.adjustSize()

        # LayoutWidget.resize(QSize(489,330).expandedTo(LayoutWidget.minimumSizeHint()))
        # self.resize(QSize(489,330).expandedTo(self.minimumSizeHint()))
        # self.clearWState(Qt.WState_Polished)

        self.connect(self.btn_ok, SIGNAL("clicked()"), self.accept)

    def languageChange(self):
        self.setWindowTitle(self.__tr("About Tigger"))
        self.title_label.setText(self.__tr( \
            """<h3>Tigger %s</h3>
            <p>(C) 2010-2017 Oleg Smirnov & Rhodes University & SKA SA<br>
            <br>Please direct feedback and bug reports at https://github.com/ska-sa/tigger</p>
            """ % (release_string) \
            ))

        self.btn_ok.setText(self.__tr("&OK"))

    def __tr(self, s, c=None):
        return qApp.translate("About", s, c)
コード例 #49
0
class InformationWindow(QWidget):
    def __init__(self):
        QWidget.__init__(self, ctx.mainScreen)
        self.setObjectName("InformationWindow")
        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.setFixedHeight(50)
        self.setMaximumWidth(800)
        self.setStyleSheet("""
            QFrame#frame { border: 1px solid rgba(255,255,255,30);
                           /*border-radius: 4px;*/
                           background-color: rgba(0,0,0,100);}

            QLabel { border:none;
                     color:#FFFFFF;}

            QProgressBar { border: 1px solid white;}

            QProgressBar::chunk { background-color: #F1610D;
                                  width: 0.5px;}
        """)

        self.gridlayout = QGridLayout(self)
        self.frame = QFrame(self)
        self.frame.setObjectName("frame")
        self.horizontalLayout = QHBoxLayout(self.frame)
        self.horizontalLayout.setContentsMargins(10, 0, 10, 0)

        # Spinner
        self.spinner = QLabel(self.frame)
        self.spinner.setMinimumSize(QSize(16, 16))
        self.spinner.setMaximumSize(QSize(16, 16))
        self.spinner.setIndent(6)
        self.movie = QMovie(':/images/working.mng')
        self.spinner.setMovie(self.movie)
        self.movie.start()
        self.horizontalLayout.addWidget(self.spinner)

        # Message
        self.label = QLabel(self.frame)
        self.label.setAlignment(Qt.AlignCenter)
        self.label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.icon = QLabel(self.frame)
        self.icon.setFixedWidth(16)
        self.icon.setFixedHeight(16)
        self.horizontalLayout.setSpacing(10)
        self.horizontalLayout.addWidget(self.icon)
        self.horizontalLayout.addWidget(self.label)

        self.gridlayout.addWidget(self.frame, 0, 0, 1, 1)

    def update(self, message, type=None, spinner=False):
        fontMetric = self.label.fontMetrics()
        textWidth = fontMetric.width(message)

        if type:
            self.icon.show()
            if type == "error":
                self.icon.setPixmap(QPixmap(":/gui/pics/dialog-error.png"))
                self.setStyleSheet(
                    " QFrame#frame {background-color: rgba(255,0,0,100);} ")

            elif type == "warning":
                self.icon.setPixmap(QPixmap(":/gui/pics/dialog-warning.png"))
                self.setStyleSheet(
                    " QFrame#frame {background-color: rgba(0,0,0,100);} ")

            self.setFixedWidth(textWidth + self.icon.width() + 50)
            self.label.setText(message)

        else:
            self.icon.hide()
            self.setStyleSheet(
                " QFrame#frame {background-color: rgba(0,0,0,100);} ")
            self.setFixedWidth(textWidth + self.icon.width() + 100)
            self.label.setText(message)

        self.spinner.setVisible(spinner)
        self.move(ctx.mainScreen.width() / 2 - self.width() / 2,
                  ctx.mainScreen.height() - self.height() / 2 - 50)

        self.show()

    def refresh(self):
        ctx.mainScreen.processEvents()

    def show(self):
        QWidget.show(self)
        self.refresh()

    def hide(self):
        QWidget.hide(self)
        self.refresh()