Ejemplo n.º 1
0
	def __init__(self, parent=None):
		super(AddAreaDlg, self).__init__(parent)
		self.setWindowTitle("New Relief Device Area")
		
		name_label = QLabel("&Name:")
		self.name_lineedit = QLineEdit()
		self.name_lineedit.setMaxLength(200)
		name_label.setBuddy(self.name_lineedit)
		location_label = QLabel("&Location:")
		self.location_combobox = QComboBox()
		self.location_combobox.setEditable(True)
		location_label.setBuddy(self.location_combobox)
		self.browse_button = QPushButton("&Browse...")
		button_box = QDialogButtonBox(QDialogButtonBox.Ok|QDialogButtonBox.Cancel)
		
		layout = QGridLayout()
		layout.addWidget(name_label, 0, 0)
		layout.addWidget(self.name_lineedit, 0, 1)
		layout.addWidget(location_label, 1, 0)
		layout.addWidget(self.location_combobox, 1, 1)
		layout.addWidget(self.browse_button, 1, 2)
		#layout.addWidget(QFrame.HLine, 2, 0)
		layout.addWidget(button_box, 2, 1)
		self.setLayout(layout)
		
		self.browse_button.clicked.connect(self.browseFiles)
		button_box.accepted.connect(self.accept)
		button_box.rejected.connect(self.reject)
Ejemplo n.º 2
0
	def __init__(self, root_node, parent=None):
		super(AddScenarioDlg, self).__init__(parent)
		self.setWindowTitle("Add Scenario")
		
		type_label = QLabel("&Scenario Type:")
		self.type_combobox = QComboBox()
		type_label.setBuddy(self.type_combobox)
		self.type_combobox.addItems(["External Fire", "Liquid Overfill", "Regulator Failure"])
		device_label = QLabel("&Associated Relief Device:")
		self.device_combobox = QComboBox()
		device_label.setBuddy(self.device_combobox)
		for area in root_node.children:
			for device in area.children:
				self.device_combobox.addItem(device.name, device)
		button_box = QDialogButtonBox(QDialogButtonBox.Ok|QDialogButtonBox.Cancel)
			
		layout = QGridLayout()
		layout.addWidget(type_label, 0, 0)
		layout.addWidget(self.type_combobox, 0, 1)
		layout.addWidget(device_label, 1, 0)
		layout.addWidget(self.device_combobox, 1, 1)
		layout.addWidget(button_box, 2, 1)
		self.setLayout(layout)
		
		button_box.accepted.connect(self.accept)
		button_box.rejected.connect(self.reject)
Ejemplo n.º 3
0
 def __init__(self, name, tendril, parent=None):
     super(TendrilWidget, self).__init__(parent)
     hlayout = QHBoxLayout(self)
     label = QLabel("&" + name)
     hlayout.addWidget(label)
     self.thunker = TendrilThunker(tendril)
     if tendril.val == True or tendril.val == False:
         spacer = QSpacerItem(0,
                              0,
                              hPolicy=QSizePolicy.Expanding,
                              vPolicy=QSizePolicy.Minimum)
         hlayout.addItem(spacer)
         checkbox = QCheckBox(self)
         checkbox.setCheckState(
             Qt.Checked if tendril.val else Qt.Unchecked)
         checkbox.stateChanged.connect(self.thunker.update)
         label.setBuddy(checkbox)
         hlayout.addWidget(checkbox)
     else:
         edit = QLineEdit(str(tendril.val), self)
         edit.textChanged.connect(self.thunker.update)
         label.setBuddy(edit)
         hlayout.addWidget(edit)
     self.setLayout(hlayout)
     self.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
Ejemplo n.º 4
0
 def create_main_area(self, layout):
     # Master password
     master_password_label = QLabel("&Master-Passwort:")
     self.master_password_edit = QLineEdit()
     self.master_password_edit.setEchoMode(QLineEdit.EchoMode.Password)
     self.master_password_edit.textChanged.connect(self.masterpassword_changed)
     self.master_password_edit.returnPressed.connect(self.move_focus)
     self.master_password_edit.editingFinished.connect(self.masterpassword_entered)
     self.master_password_edit.setMaximumHeight(28)
     master_password_label.setBuddy(self.master_password_edit)
     layout.addWidget(master_password_label)
     layout.addWidget(self.master_password_edit)
     # Domain
     domain_label = QLabel("&Domain:")
     self.domain_edit = QComboBox()
     self.domain_edit.setEditable(True)
     self.domain_edit.textChanged.connect(self.domain_changed)
     self.domain_edit.currentIndexChanged.connect(self.domain_changed)
     self.domain_edit.lineEdit().editingFinished.connect(self.domain_entered)
     self.domain_edit.lineEdit().returnPressed.connect(self.move_focus)
     self.domain_edit.setMaximumHeight(28)
     domain_label.setBuddy(self.domain_edit)
     layout.addWidget(domain_label)
     layout.addWidget(self.domain_edit)
     # Username
     self.username_label = QLabel("&Username:"******"&Passwortstärke:")
     self.strength_label.setVisible(False)
     self.strength_selector = PasswordStrengthSelector()
     self.strength_selector.set_min_length(4)
     self.strength_selector.set_max_length(36)
     self.strength_selector.setMinimumHeight(60)
     self.strength_selector.set_length(12)
     self.strength_selector.set_complexity(6)
     self.strength_selector.strength_changed.connect(self.strength_changed)
     self.strength_selector.setVisible(False)
     self.strength_label.setBuddy(self.strength_selector)
     layout.addWidget(self.strength_label)
     layout.addWidget(self.strength_selector)
     # Password
     self.password_label = QLabel("&Passwort:")
     self.password_label.setVisible(False)
     self.password = QLabel()
     self.password.setTextFormat(Qt.PlainText)
     self.password.setAlignment(Qt.AlignCenter)
     self.password.setFont(QFont("Helvetica", 18, QFont.Bold))
     self.password.setVisible(False)
     self.password_label.setBuddy(self.password)
     layout.addWidget(self.password_label)
     layout.addWidget(self.password)
Ejemplo n.º 5
0
class CustomPage(QWizardPage):
    '''
    Custom Computer Wizard Page
    
    Contains inputs for the Driver and Parser that the user can define a 
    custom mix of driver/parser/options.
    '''
    def __init__(self, parent=None):
        super(CustomPage, self).__init__(parent)
        
        self._createLayout()
        
        self.registerField('driver', self._cbxDriver)
        self.registerField('parser', self._cbxParser)
        self.registerField('driveropt', self._txtDOpts)
        self.registerField('parseropt', self._txtPOpts)
    
        self.setTitle(self.tr('Setup Driver Options'))
        self.setSubTitle(self.tr('Select the Driver and Parser to use with your Dive Computer.'))
    
    def nextId(self):
        'Return the next Page Id'
        return Pages.Browse
    
    def _createLayout(self):
        'Create the Wizard Page Layout'
        
        self._cbxDriver = QComboBox()
        self._cbxDriver.setModel(DriverModel())
        self._lblDriver = QLabel(self.tr('&Driver:'))
        self._lblDriver.setBuddy(self._cbxDriver)
        
        self._cbxParser = QComboBox()
        self._cbxParser.setModel(ParserModel())
        self._lblParser = QLabel(self.tr('&Parser:'))
        self._lblParser.setBuddy(self._cbxParser)
        
        self._txtDOpts = QLineEdit()
        self._lblDOpts = QLabel(self.tr('Driver Options:'))
        self._lblDOpts.setBuddy(self._txtDOpts)
        
        self._txtPOpts = QLineEdit()
        self._lblPOpts = QLabel(self.tr('Parser Options:'))
        self._lblPOpts.setBuddy(self._txtPOpts)
        
        gbox = QGridLayout()
        gbox.addWidget(self._lblDriver, 0, 0)
        gbox.addWidget(self._cbxDriver, 0, 1)
        gbox.addWidget(self._lblParser, 1, 0)
        gbox.addWidget(self._cbxParser, 1, 1)
        gbox.addWidget(self._lblDOpts, 2, 0)
        gbox.addWidget(self._txtDOpts, 2, 1)
        gbox.addWidget(self._lblPOpts, 3, 0)
        gbox.addWidget(self._txtPOpts, 3, 1)
        
        vbox = QVBoxLayout()
        vbox.addLayout(gbox)
        vbox.addStretch()
        
        self.setLayout(vbox)
Ejemplo n.º 6
0
	def initUI(self):
		wordLabel=QLabel("&Wort:")
		responseLabel=QLabel("Symbol-Wort:")
		progressLabel=QLabel("Rechen-Fortschritt:")
		
		self.lineEdit=QLineEdit()
		self.updateButton=QPushButton("&Berechnen")
		self.autoUpdate=QCheckBox("&Auto-Berechnung")
		self.responseLabel=QLabel()
		wordLabel.setBuddy(self.lineEdit)
		self.tableWidget=QTableWidget()
		self.progressView=ProgressView()
		
		self.disableMaxLengthAction=QAction("Zeichenmaximum (Achtung!)",self)
		self.disableMaxLengthAction.setCheckable(True)
		self.disableMaxLengthAction.toggled.connect(self.updateMaxLength)
		self.disableMaxLengthAction.setChecked(True)
		
		self.setupTable()
		self.progressView.setProgress(self.thread.calculator.progress)
		self.progressView.abortButton.setIcon(QIcon.fromTheme("process-stopp",QIcon("Abort.png")))
		self.progressView.abortButton.setToolTip("Stoppe die Berechnung")
		self.lineEdit.setValidator(QRegExpValidator(QRegExp("[A-Za-z]+")))
		self.lineEdit.setToolTip("Nur Zeichen von A-Z")
		self.lineEdit.setContextMenuPolicy(Qt.ActionsContextMenu)
		self.lineEdit.addAction(self.disableMaxLengthAction)
		self.responseLabel.setSizePolicy(QSizePolicy.Preferred,QSizePolicy.Fixed)
		self.responseLabel.setFrameStyle(QFrame.StyledPanel|QFrame.Sunken)
		self.aboutButton=QPushButton(u"Über")
		f=self.responseLabel.font()
		f.setPointSize(24)
		self.responseLabel.setFont(f)
		
		self.lineEdit.returnPressed.connect(self.update)
		self.updateButton.clicked.connect(self.update)
		self.autoUpdate.stateChanged.connect(self.updateAuto)
		self.aboutButton.clicked.connect(self.about)
		
		layout=QGridLayout()
		layout.addWidget(wordLabel,0,0)
		layout.addWidget(self.lineEdit,0,1)
		layout.addWidget(self.updateButton,0,2)
		layout.addWidget(self.autoUpdate,1,1,1,2)
		layout.addWidget(responseLabel,2,0)
		layout.addWidget(self.responseLabel,2,1,1,2)
		layout.addWidget(self.tableWidget,3,0,1,3)
		layout.addWidget(progressLabel,4,0)
		layout.addWidget(self.progressView,5,0,1,3)
		layout.addWidget(self.aboutButton,6,2)
		self.setLayout(layout)
Ejemplo n.º 7
0
class Panel(QWidget):
    def __init__(self, state, parent=None):
        super().__init__(parent)
        self.state = state
        self.createWidgets()
        self.layoutWidgets()
        self.helpButton.clicked.connect(
            lambda: self.state.help("xix_ref_panel_index.html"))

    def clear(self):
        self.view.clear()

    def createWidgets(self):
        self.indexLabel = QLabel("&Index ")
        self.view = Views.All.View(self.state)
        self.tooltips.append((self.view, """
<p><b>Index view</b> (Alt+I)</p>
<p>This view shows all the index's entries.</p>
<p>The entries are always shown in the correct order in accordance with
the the chosen <b>Index→Options, Rules, Calculate Sort As Rules</b>, so
there's never a need to explicitly sort.</p>"""))
        self.indexLabel.setBuddy(self.view)
        self.gotoLabel = QLabel("Goto <font color=darkgreen>(Ctrl+T)</font>")
        self.gotoLineEdit = SelectAllLineEdit()
        self.gotoLabel.setBuddy(self.gotoLineEdit)
        self.tooltips.append((self.gotoLineEdit, """
<p><b>Goto (Ctrl+T)</b></p>
<p>Enter a few initial letters to goto the first main entry whose
term begins with those letters.</p>"""))
        self.state.editors.add(self.gotoLineEdit)
        self.helpButton = QToolButton()
        self.helpButton.setIcon(QIcon(":/help.svg"))
        self.helpButton.setFocusPolicy(Qt.NoFocus)

    def layoutWidgets(self):
        layout = QVBoxLayout()
        hbox = QHBoxLayout()
        hbox.addWidget(self.indexLabel)
        hbox.addSpacing(self.fontMetrics().width("W") * 4)
        hbox.addStretch()
        hbox.addWidget(self.gotoLabel)
        hbox.addWidget(self.gotoLineEdit, 1)
        hbox.addWidget(self.helpButton)
        layout.addLayout(hbox)
        layout.addWidget(self.view, 1)
        self.setLayout(layout)

    def updateDisplayFonts(self):
        self.view.updateDisplayFonts()
Ejemplo n.º 8
0
class IntroPage(QWizardPage):
    '''
    Introduction Wizard Page
    
    Contains the introduction text and a combo box to select either a pre-
    defined computer model or a custom computer type.
    '''
    def __init__(self, parent=None):
        super(IntroPage, self).__init__(parent)
        
        self._createLayout()
        
        self.registerField('type', self._cbxType)
        self.setTitle(self.tr('Add a Dive Computer'))
        self.setSubTitle(self.tr('Select the type of Dive Computer to add.  Make sure the computer is connected and ready to download before proceeding.'))

    def nextId(self):
        'Return the next Page Id'
        if self._cbxType.currentIndex() == len(ComputerTypes):
            return Pages.Custom
        else:
            return Pages.Browse
    
    def _createLayout(self):
        'Create the Wizard Page Layout'
        
        self._cbxType = QComboBox()
        self._lblType = QLabel(self.tr('Dive Computer &Type'))
        self._lblType.setBuddy(self._cbxType)
        
        for t in ComputerTypes:
            self._cbxType.addItem(t['name'])
        self._cbxType.addItem('Custom...')
        
        gbox = QGridLayout()
        gbox.addWidget(self._lblType, 0, 0)
        gbox.addWidget(self._cbxType, 0, 1)
        
        vbox = QVBoxLayout()
        vbox.addLayout(gbox)
        vbox.addStretch()
        
        self.setLayout(vbox)
Ejemplo n.º 9
0
	def __init__(self, root_node, parent=None):
		super(CopyDeviceDlg, self).__init__(parent)
		self.setWindowTitle("Duplicate Relief Device")

		area_label = QLabel("&Copy Relief Device To:")
		self.area_combobox = QComboBox()
		for area in root_node.children:
			self.area_combobox.addItem(area.name, area)
		area_label.setBuddy(self.area_combobox)
		button_box = QDialogButtonBox(QDialogButtonBox.Ok|QDialogButtonBox.Cancel)
			
		layout = QGridLayout()
		layout.addWidget(area_label, 0, 0)
		layout.addWidget(self.area_combobox, 0, 1)
		layout.addWidget(button_box, 1, 1)
		self.setLayout(layout)
		
		button_box.accepted.connect(self.accept)
		button_box.rejected.connect(self.reject)
Ejemplo n.º 10
0
	def __init__(self, root_node, parent=None):
		super(CopyScenarioDlg, self).__init__(parent)
		self.setWindowTitle("Duplicate Scenario")
		
		device_label = QLabel("&Copy Scenario To:")
		self.device_combobox = QComboBox()
		device_label.setBuddy(self.device_combobox)
		for area in root_node.children:
			for device in area.children:
				self.device_combobox.addItem(device.name, device)
		button_box = QDialogButtonBox(QDialogButtonBox.Ok|QDialogButtonBox.Cancel)
			
		layout = QGridLayout()
		layout.addWidget(device_label, 0, 0)
		layout.addWidget(self.device_combobox, 0, 1)
		layout.addWidget(button_box, 1, 1)
		self.setLayout(layout)
		
		button_box.accepted.connect(self.accept)
		button_box.rejected.connect(self.reject)
Ejemplo n.º 11
0
class managebkm(QDialog):
	def __init__(self, parent=None):
		super(managebkm, self).__init__(parent)
		appicom = QIcon(":/icons/njnlogo.png")
		self.setWindowIcon(appicom)
		self.setWindowTitle("Nigandu | Manage Book Marks")
		self.setFixedSize(463, 242)

		self.verticalLayoutWidget = QWidget(self)
		self.verticalLayoutWidget.setGeometry(QRect(350, 30, 101, 201))
		self.verticalLayoutWidget.setObjectName("verticalLayoutWidget")
		self.verticalLayout = QVBoxLayout(self.verticalLayoutWidget)
		self.verticalLayout.setContentsMargins(0, 0, 0, 0)
		self.verticalLayout.setObjectName("verticalLayout")

		self.sortbtn = QPushButton(self.verticalLayoutWidget)
		self.sortbtn.setText("&Sort")
		self.verticalLayout.addWidget(self.sortbtn)

		self.deletebtn = QPushButton(self.verticalLayoutWidget)
		self.deletebtn.setText("&Delete")
		self.verticalLayout.addWidget(self.deletebtn)

		self.deleteallbtn = QPushButton(self.verticalLayoutWidget)
		self.deleteallbtn.setText("Delete &All")
		self.verticalLayout.addWidget(self.deleteallbtn)

		self.closebtn = QPushButton(self.verticalLayoutWidget)
		self.closebtn.setText("&Close")
		self.verticalLayout.addWidget(self.closebtn)

		self.listWidget = QListWidget(self)
		self.listWidget.setGeometry(QRect(10, 30, 331, 201))

		self.label = QLabel(self)
		self.label.setGeometry(QRect(20, 10, 91, 25))
		font = QFont()
		font.setPointSize(10)
		self.label.setFont(font)
		self.label.setBuddy(self.listWidget)
		self.label.setText("Book Mark List:")
Ejemplo n.º 12
0
Archivo: gui.py Proyecto: caomw/ecto
 def __init__(self, name, tendril, parent=None):
     super(TendrilWidget,self).__init__(parent)
     hlayout = QHBoxLayout(self)
     label = QLabel("&" + name)
     hlayout.addWidget(label)
     self.thunker = TendrilThunker(tendril)
     if tendril.val == True or tendril.val == False:
         spacer = QSpacerItem(0, 0, hPolicy=QSizePolicy.Expanding, vPolicy=QSizePolicy.Minimum)
         hlayout.addItem(spacer)
         checkbox = QCheckBox(self)
         checkbox.setCheckState(Qt.Checked if tendril.val else Qt.Unchecked)
         checkbox.stateChanged.connect(self.thunker.update)
         label.setBuddy(checkbox)
         hlayout.addWidget(checkbox)
     else:
         edit = QLineEdit(str(tendril.val), self)
         edit.textChanged.connect(self.thunker.update)
         label.setBuddy(edit)
         hlayout.addWidget(edit)
     self.setLayout(hlayout)
     self.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
Ejemplo n.º 13
0
	def __init__(self, root_node, parent=None):
		super(AddDeviceDlg, self).__init__(parent)
		self.setWindowTitle("Add Relief Device")

		id_label = QLabel("&Relief Device ID:")
		self.id_lineedit = QLineEdit()
		self.id_lineedit.setMaxLength(200)
		id_label.setBuddy(self.id_lineedit)
		area_label = QLabel("Associated Relief Device &Area:")
		self.area_combobox = QComboBox()
		for area in root_node.children:
			self.area_combobox.addItem(area.name, area)
		area_label.setBuddy(self.area_combobox)
		color_label = QLabel("&Text Color:")
		self.color_combobox = QComboBox()
		for key in sorted(COLORS.keys()):
			pixmap = QPixmap(26, 26)
			pixmap.fill(COLORS[key])
			self.color_combobox.addItem(QIcon(pixmap), key)
		color_label.setBuddy(self.color_combobox)
		button_box = QDialogButtonBox(QDialogButtonBox.Ok|QDialogButtonBox.Cancel)
			
		layout = QGridLayout()
		layout.addWidget(id_label, 0, 0)
		layout.addWidget(self.id_lineedit, 0, 1)
		layout.addWidget(area_label, 1, 0)
		layout.addWidget(self.area_combobox, 1, 1)
		layout.addWidget(color_label, 2, 0)
		layout.addWidget(self.color_combobox, 2, 1)
		layout.addWidget(button_box, 3, 1)
		self.setLayout(layout)
		
		button_box.accepted.connect(self.accept)
		button_box.rejected.connect(self.reject)
Ejemplo n.º 14
0
    def layoutWidgets(self):
        form = QFormLayout()
        hbox = QHBoxLayout()
        hbox.addStretch()
        hbox.addWidget(self.formatPanel)
        form.addRow(hbox)
        form.addRow(self.titleLabel, self.titleTextEdit)
        form.addRow(self.noteLabel, self.noteTextEdit)

        vbox = QVBoxLayout()
        hbox = QHBoxLayout()
        hbox.addWidget(self.blankBeforeLabel)
        hbox.addWidget(self.blankBeforeSpinBox)
        hbox.addWidget(self.blankAfterLabel)
        hbox.addWidget(self.blankAfterSpinBox)
        hbox.addStretch()
        vbox.addLayout(hbox)
        hbox = QHBoxLayout()
        hbox.addWidget(self.sectionTitlesCheckBox)
        hbox.addStretch()
        hbox.addWidget(self.sectionSpecialTitleLabel)
        hbox.addWidget(self.sectionSpecialTitleTextEdit)
        vbox.addLayout(hbox)
        self.sectionsGroupBox.setLayout(vbox)
        form.addRow(self.sectionsGroupBox)

        hbox = QHBoxLayout()
        hbox.addWidget(self.stdFontComboBox, 1)
        hbox.addWidget(self.stdFontSizeSpinBox)
        hbox.addStretch()
        label = QLabel("&Std. Font")
        label.setBuddy(self.stdFontComboBox)
        form.addRow(label, hbox)
        hbox = QHBoxLayout()
        hbox.addWidget(self.altFontComboBox, 1)
        hbox.addWidget(self.altFontSizeSpinBox)
        hbox.addStretch()
        label = QLabel("&Alt. Font")
        label.setBuddy(self.altFontComboBox)
        form.addRow(label, hbox)
        hbox = QHBoxLayout()
        hbox.addWidget(self.monoFontComboBox, 1)
        hbox.addWidget(self.monoFontSizeSpinBox)
        hbox.addStretch()
        label = QLabel("&Mono. Font")
        label.setBuddy(self.monoFontComboBox)
        form.addRow(label, hbox)

        grid = QGridLayout()
        grid.addWidget(self.monoFontAsStrikeoutCheckbox, 0, 0, 1, 2)
        grid.addWidget(self.termPagesSepLabel, 0, 2)
        grid.addWidget(self.termPagesSepTextEdit, 0, 3)
        grid.addWidget(self.styleLabel, 1, 0)
        grid.addWidget(self.styleComboBox, 1, 1)
        grid.addWidget(self.runInSepLabel, 1, 2)
        grid.addWidget(self.runInSepTextEdit, 1, 3)
        form.addRow(grid)
        self.setLayout(form)
Ejemplo n.º 15
0
class FinishPage(QWizardPage):
    '''
    Finish Wizard Page
    
    Contains a summary of the computer and a space for the user to enter a 
    name for the Computer.
    '''
    def __init__(self, parent=None):
        super(FinishPage, self).__init__(parent)
        
        self._createLayout()
        
        self.registerField('name*', self._txtName)
        self.setTitle(self.tr('Name your Dive Computer'))
        self.setSubTitle(self.tr('Enter a name for the Dive Computer to finish adding the Dive Computer to the Logbook.'))
    
    def nextId(self):
        'Return the next Page Id'
        return -1
    
    def _createLayout(self):
        'Create the Wizard Page Layout'
        
        self._txtName = QLineEdit()
        self._lblName = QLabel(self.tr('Computer &Name:'))
        self._lblName.setBuddy(self._txtName)
        
        gbox = QGridLayout()
        gbox.addWidget(self._lblName, 0, 0)
        gbox.addWidget(self._txtName, 0, 1)
        
        vbox = QVBoxLayout()
        vbox.addLayout(gbox)
        vbox.addStretch()
        
        self.setLayout(vbox)
Ejemplo n.º 16
0
 def create_main_area(self, layout, url, username, password):
     url_label = QLabel("&URL des c't SESAM Sync Server:")
     self.url_edit = QLineEdit()
     if url:
         self.url_edit.setText(url)
     self.url_edit.setMaximumHeight(28)
     self.url_edit.textChanged.connect(self.url_changed)
     url_label.setBuddy(self.url_edit)
     layout.addWidget(url_label)
     layout.addWidget(self.url_edit)
     username_label = QLabel("&Benutzername:")
     self.username_edit = QLineEdit()
     if username:
         self.username_edit.setText(username)
     self.username_edit.setMaximumHeight(28)
     self.username_edit.textChanged.connect(self.save_settings)
     username_label.setBuddy(self.username_edit)
     layout.addWidget(username_label)
     layout.addWidget(self.username_edit)
     password_label = QLabel("&Passwort:")
     self.password_edit = QLineEdit()
     if password:
         self.password_edit.setText(password)
     self.password_edit.setEchoMode(QLineEdit.EchoMode.Password)
     self.password_edit.setMaximumHeight(28)
     self.password_edit.textChanged.connect(self.save_settings)
     password_label.setBuddy(self.password_edit)
     layout.addWidget(password_label)
     layout.addWidget(self.password_edit)
     self.test_button = QPushButton("Verbindung testen")
     self.test_button.clicked.connect(self.test_connection)
     layout.addWidget(self.test_button)
     self.message = QLabel("")
     if not self.certificate:
         self.message.setText(
             '<span style="font-size: 10px; color: #aa0000;">' +
             'Kein Zertifikat vorhanden.' + '</span>')
     layout.addWidget(self.message)
Ejemplo n.º 17
0
 def create_main_area(self, layout, url, username, password):
     url_label = QLabel("&URL des c't SESAM Sync Server:")
     self.url_edit = QLineEdit()
     if url:
         self.url_edit.setText(url)
     self.url_edit.setMaximumHeight(28)
     self.url_edit.textChanged.connect(self.url_changed)
     url_label.setBuddy(self.url_edit)
     layout.addWidget(url_label)
     layout.addWidget(self.url_edit)
     username_label = QLabel("&Benutzername:")
     self.username_edit = QLineEdit()
     if username:
         self.username_edit.setText(username)
     self.username_edit.setMaximumHeight(28)
     self.username_edit.textChanged.connect(self.save_settings)
     username_label.setBuddy(self.username_edit)
     layout.addWidget(username_label)
     layout.addWidget(self.username_edit)
     password_label = QLabel("&Passwort:")
     self.password_edit = QLineEdit()
     if password:
         self.password_edit.setText(password)
     self.password_edit.setEchoMode(QLineEdit.EchoMode.Password)
     self.password_edit.setMaximumHeight(28)
     self.password_edit.textChanged.connect(self.save_settings)
     password_label.setBuddy(self.password_edit)
     layout.addWidget(password_label)
     layout.addWidget(self.password_edit)
     self.test_button = QPushButton("Verbindung testen")
     self.test_button.clicked.connect(self.test_connection)
     layout.addWidget(self.test_button)
     self.message = QLabel("")
     if not self.certificate:
         self.message.setText('<span style="font-size: 10px; color: #aa0000;">' +
                              'Kein Zertifikat vorhanden.' +
                              '</span>')
     layout.addWidget(self.message)
Ejemplo n.º 18
0
 def layoutWidgets(self):
     form = QFormLayout()
     grid = QGridLayout()
     grid.addWidget(self.indexViewOnLeft, 0, 0)
     grid.addWidget(self.alwaysShowSortAsCheckBox, 1, 0)
     grid.addWidget(self.showNotesCheckBox, 2, 0)
     grid.addWidget(self.showMenuToolTipsCheckBox, 0, 1)
     grid.addWidget(self.showMainWindowToolTipsCheckBox, 1, 1)
     grid.addWidget(self.showDialogToolTipsCheckBox, 2, 1)
     grid.addWidget(self.keepHelpOnTopCheckBox, 3, 1)
     grid.addWidget(self.showSplashCheckBox, 4, 1)
     hbox = QHBoxLayout()
     hbox.addLayout(grid)
     hbox.addStretch()
     form.addRow(hbox)
     hbox = QHBoxLayout()
     hbox.addWidget(self.displaystdFontComboBox, 1)
     hbox.addWidget(self.displaystdFontSizeSpinBox)
     hbox.addStretch()
     label = QLabel("&Std. Font")
     label.setBuddy(self.displaystdFontComboBox)
     form.addRow(label, hbox)
     hbox = QHBoxLayout()
     hbox.addWidget(self.displayaltFontComboBox, 1)
     hbox.addWidget(self.displayaltFontSizeSpinBox)
     hbox.addStretch()
     label = QLabel("&Alt. Font")
     label.setBuddy(self.displayaltFontComboBox)
     form.addRow(label, hbox)
     hbox = QHBoxLayout()
     hbox.addWidget(self.displaymonoFontComboBox, 1)
     hbox.addWidget(self.displaymonoFontSizeSpinBox)
     hbox.addStretch()
     label = QLabel("&Mono. Font")
     label.setBuddy(self.displaymonoFontComboBox)
     form.addRow(label, hbox)
     self.setLayout(form)
Ejemplo n.º 19
0
class Panel(QWidget):

    def __init__(self, state, config, parent):
        super().__init__(parent)
        self.state = state
        self.config = config
        self.form = parent
        self.createWidgets()
        self.layoutWidgets()


    def createWidgets(self):
        self.formatPanel = Widgets.FormatPanel.Panel(self.state, self)
        formatActions = self.formatPanel.formatActions

        self.seePrefixLabel = QLabel("Pref&ix")
        self.seePrefixTextEdit = Widgets.LineEdit.SpacesHtmlLineEdit(
            self.state, 3, formatActions=formatActions)
        self.seePrefixLabel.setBuddy(self.seePrefixTextEdit)
        self.seePrefixTextEdit.setHtml(self.config.get(
                                       Gconf.Key.SubSeePrefix))
        self.form.tooltips.append((self.seePrefixTextEdit, """\
<p><b>See, Prefix</b></p>
<p>The text to separate a subentry's <i>see</i> cross-refs from the term
or pages that precede them.</p>{}""".format(BLANK_SPACE_HTML)))
        self.seeLabel = QLabel("T&ext")
        self.seeTextEdit = Widgets.LineEdit.SpacesHtmlLineEdit(
            self.state, 10, formatActions=formatActions)
        self.seeLabel.setBuddy(self.seeTextEdit)
        self.seeTextEdit.setHtml(self.config.get(Gconf.Key.SubSee))
        self.form.tooltips.append((self.seeTextEdit, """\
<p><b>See, Text</b></p>
<p>The text to indicate a subentry's <i>see</i>
cross-ref(s).</p>{}""".format(BLANK_SPACE_HTML)))
        self.seeSepLabel = QLabel("Sepa&rator")
        self.seeSepTextEdit = Widgets.LineEdit.SpacesHtmlLineEdit(
            self.state, 3, formatActions=formatActions)
        self.seeSepLabel.setBuddy(self.seeSepTextEdit)
        self.seeSepTextEdit.setHtml(self.config.get(
                                    Gconf.Key.SubSeeSeparator))
        self.form.tooltips.append((self.seeSepTextEdit, """\
<p><b>See, Separator</b></p>
<p>The text to separate each of a subentry's <i>see</i> cross-references if
there are more than one.</p>{}""".format(BLANK_SPACE_HTML)))
        self.seeSuffixLabel = QLabel("Su&ffix")
        self.seeSuffixTextEdit = Widgets.LineEdit.SpacesHtmlLineEdit(
            self.state, 3, formatActions=formatActions)
        self.seeSuffixLabel.setBuddy(self.seeSuffixTextEdit)
        self.seeSuffixTextEdit.setHtml(self.config.get(
                                       Gconf.Key.SubSeeSuffix))
        self.form.tooltips.append((self.seeSuffixTextEdit, """\
<p><b>See, Suffix</b></p>
<p>The text to follow a subentry's <i>see</i>
cross-references</p>{}""".format(BLANK_SPACE_HTML)))

        self.seeAlsoPrefixLabel = QLabel("&Prefix")
        self.seeAlsoPrefixTextEdit = Widgets.LineEdit.SpacesHtmlLineEdit(
            self.state, 3, formatActions=formatActions)
        self.seeAlsoPrefixLabel.setBuddy(self.seeAlsoPrefixTextEdit)
        self.seeAlsoPrefixTextEdit.setHtml(self.config.get(
                                           Gconf.Key.SubSeeAlsoPrefix))
        self.form.tooltips.append((self.seeAlsoPrefixTextEdit, """\
<p><b>See Also, Prefix</b></p>
<p>The text to separate a subentry's <i>see also</i> cross-refs from the
term or pages that precede them.</p>{}""".format(BLANK_SPACE_HTML)))
        self.seeAlsoLabel = QLabel("Te&xt")
        self.seeAlsoTextEdit = Widgets.LineEdit.SpacesHtmlLineEdit(
            self.state, 10, formatActions=formatActions)
        self.seeAlsoLabel.setBuddy(self.seeAlsoTextEdit)
        self.seeAlsoTextEdit.setHtml(self.config.get(Gconf.Key.SubSeeAlso))
        self.form.tooltips.append((self.seeAlsoTextEdit, """\
<p><b>See Also, Text</b></p>
<p>The text to indicate a subentry's <i>see also</i>
cross-ref(s).</p>{}""".format(BLANK_SPACE_HTML)))
        self.seeAlsoSepLabel = QLabel("&Separator")
        self.seeAlsoSepTextEdit = Widgets.LineEdit.SpacesHtmlLineEdit(
            self.state, 3, formatActions=formatActions)
        self.seeAlsoSepLabel.setBuddy(self.seeAlsoSepTextEdit)
        self.seeAlsoSepTextEdit.setHtml(self.config.get(
                                        Gconf.Key.SubSeeAlsoSeparator))
        self.form.tooltips.append((self.seeAlsoSepTextEdit, """\
<p><b>See Also, Separator</b></p>
<p>The text to separate each of a subentry's <i>see also</i>
cross-references if there are more than one.</p>{}""".format(
            BLANK_SPACE_HTML)))
        self.seeAlsoSuffixLabel = QLabel("S&uffix")
        self.seeAlsoSuffixTextEdit = Widgets.LineEdit.SpacesHtmlLineEdit(
            self.state, 3, formatActions=formatActions)
        self.seeAlsoSuffixLabel.setBuddy(self.seeAlsoSuffixTextEdit)
        self.seeAlsoSuffixTextEdit.setHtml(self.config.get(
                                           Gconf.Key.SubSeeAlsoSuffix))
        self.form.tooltips.append((self.seeAlsoSuffixTextEdit, """\
<p><b>See Also, Suffix</b></p>
<p>The text to follow a subentry's <i>see also</i>
cross-references</p>{}""".format(BLANK_SPACE_HTML)))
        self.seeAlsoPositionLabel = QLabel("P&osition")
        self.seeAlsoPositionComboBox = QComboBox()
        self.seeAlsoPositionLabel.setBuddy(self.seeAlsoPositionComboBox)
        seeAlsoPos = self.config.get(Gconf.Key.SubSeeAlsoPosition)
        index = -1
        for i, pos in enumerate(SeeAlsoPositionKind):
            self.seeAlsoPositionComboBox.addItem(pos.text, pos.value)
            if pos is seeAlsoPos:
                index = i
        self.seeAlsoPositionComboBox.setCurrentIndex(index)
        self.form.tooltips.append((self.seeAlsoPositionComboBox, """\
<p><b>Position</b></p>
<p>Where <i>see also</i> cross-references should appear in relation to the
subentry they belong to.</p>"""))

        self.formatPanel.state.editors = [
            self.seePrefixTextEdit, self.seeTextEdit,
            self.seeSepTextEdit, self.seeSuffixTextEdit,
            self.seeAlsoPrefixTextEdit, self.seeAlsoTextEdit,
            self.seeAlsoSepTextEdit, self.seeAlsoSuffixTextEdit]


    def layoutWidgets(self):
        layout = QVBoxLayout()
        hbox = QHBoxLayout()
        hbox.addStretch()
        hbox.addWidget(self.formatPanel)
        layout.addLayout(hbox)

        seeGroup = QGroupBox("See")
        form = QFormLayout()
        form.addRow(self.seeLabel, self.seeTextEdit)
        hbox = QHBoxLayout()
        hbox.addWidget(self.seePrefixTextEdit)
        hbox.addWidget(self.seeSepLabel)
        hbox.addWidget(self.seeSepTextEdit)
        hbox.addWidget(self.seeSuffixLabel)
        hbox.addWidget(self.seeSuffixTextEdit)
        form.addRow(self.seePrefixLabel, hbox)
        seeGroup.setLayout(form)
        layout.addWidget(seeGroup)

        alsoGroup = QGroupBox("See Also")
        form = QFormLayout()
        form.addRow(self.seeAlsoLabel, self.seeAlsoTextEdit)
        hbox = QHBoxLayout()
        hbox.addWidget(self.seeAlsoPrefixTextEdit)
        hbox.addWidget(self.seeAlsoSepLabel)
        hbox.addWidget(self.seeAlsoSepTextEdit)
        hbox.addWidget(self.seeAlsoSuffixLabel)
        hbox.addWidget(self.seeAlsoSuffixTextEdit)
        form.addRow(self.seeAlsoPrefixLabel, hbox)
        form.addRow(self.seeAlsoPositionLabel, self.seeAlsoPositionComboBox)
        alsoGroup.setLayout(form)
        layout.addWidget(alsoGroup)

        layout.addStretch(2)

        self.setLayout(layout)
Ejemplo n.º 20
0
class MainWindow(QWidget):
    # noinspection PyUnresolvedReferences
    def __init__(self, clipboard):
        super().__init__()
        self.clipboard = clipboard
        self.setWindowIcon(QIcon('Logo_rendered_edited.png'))
        self.layout = QBoxLayout(QBoxLayout.TopToBottom, self)
        self.generator = CtSesam()
        self.iterations = 4096
        # Master password
        self.master_password_label = QLabel("&Master-Passwort:")
        self.maser_password_edit = QLineEdit()
        self.maser_password_edit.setEchoMode(QLineEdit.EchoMode.Password)
        self.maser_password_edit.textChanged.connect(self.reset_iterations)
        self.maser_password_edit.returnPressed.connect(self.move_focus)
        self.maser_password_edit.setMaximumHeight(28)
        self.master_password_label.setBuddy(self.maser_password_edit)
        self.layout.addWidget(self.master_password_label)
        self.layout.addWidget(self.maser_password_edit)
        # Domain
        self.domain_label = QLabel("&Domain:")
        self.domain_edit = QLineEdit()
        self.domain_edit.textChanged.connect(self.reset_iterations)
        self.domain_edit.returnPressed.connect(self.move_focus)
        self.domain_edit.setMaximumHeight(28)
        self.domain_label.setBuddy(self.domain_edit)
        self.layout.addWidget(self.domain_label)
        self.layout.addWidget(self.domain_edit)
        # Username
        self.username_label = QLabel("&Username:"******"Sonderzeichen")
        self.special_characters_checkbox.setChecked(True)
        self.special_characters_checkbox.stateChanged.connect(self.reset_iterations)
        self.layout.addWidget(self.special_characters_checkbox)
        self.letters_checkbox = QCheckBox("Buchstaben")
        self.letters_checkbox.setChecked(True)
        self.letters_checkbox.stateChanged.connect(self.reset_iterations)
        self.layout.addWidget(self.letters_checkbox)
        self.digits_checkbox = QCheckBox("Zahlen")
        self.digits_checkbox.setChecked(True)
        self.digits_checkbox.stateChanged.connect(self.reset_iterations)
        self.layout.addWidget(self.digits_checkbox)
        # Length slider
        self.length_label = QLabel("&Länge:")
        self.length_display = QLabel()
        self.length_label_layout = QBoxLayout(QBoxLayout.LeftToRight)
        self.length_label_layout.addWidget(self.length_label)
        self.length_label_layout.addWidget(self.length_display)
        self.length_label_layout.addStretch()
        self.length_slider = QSlider(Qt.Horizontal)
        self.length_slider.setMinimum(4)
        self.length_slider.setMaximum(20)
        self.length_slider.setPageStep(1)
        self.length_slider.setValue(10)
        self.length_display.setText(str(self.length_slider.sliderPosition()))
        self.length_slider.valueChanged.connect(self.length_slider_changed)
        self.length_label.setBuddy(self.length_slider)
        self.layout.addLayout(self.length_label_layout)
        self.layout.addWidget(self.length_slider)
        # Button
        self.generate_button = QPushButton("Erzeugen")
        self.generate_button.clicked.connect(self.generate_password)
        self.generate_button.setAutoDefault(True)
        self.layout.addWidget(self.generate_button)
        # Password
        self.password_label = QLabel("&Passwort:")
        self.password = QLabel()
        self.password.setTextFormat(Qt.PlainText)
        self.password.setAlignment(Qt.AlignCenter)
        self.password.setFont(QFont("Helvetica", 18, QFont.Bold))
        self.password_label.setBuddy(self.password)
        self.layout.addWidget(self.password_label)
        self.layout.addWidget(self.password)
        # Iteration display
        self.message_label = QLabel()
        self.message_label.setTextFormat(Qt.RichText)
        self.message_label.setVisible(False)
        self.layout.addWidget(self.message_label)
        # Window layout
        self.layout.addStretch()
        self.setGeometry(0, 30, 300, 400)
        self.setWindowTitle("c't SESAM")
        self.maser_password_edit.setFocus()
        self.show()

    def length_slider_changed(self):
        self.length_display.setText(str(self.length_slider.sliderPosition()))
        self.reset_iterations()

    def reset_iterations(self):
        self.iterations = 4096
        self.message_label.setVisible(False)
        self.password.setText('')
        self.clipboard.setText('')

    def move_focus(self):
        line_edits = [self.maser_password_edit, self.domain_edit, self.username_edit]
        for i, edit in enumerate(line_edits):
            if edit.hasFocus() and i + 1 < len(line_edits):
                line_edits[i + 1].setFocus()
                return True
        self.generate_button.setFocus()

    def generate_password(self):
        if len(self.domain_edit.text()) <= 0:
            self.reset_iterations()
            self.message_label.setText(
                '<span style="font-size: 10px; color: #aa0000;">Bitte geben Sie eine Domain an.</span>')
            self.message_label.setVisible(True)
            return False
        if self.letters_checkbox.isChecked() or \
           self.digits_checkbox.isChecked() or \
           self.special_characters_checkbox.isChecked():
            self.generator.set_password_characters(
                use_letters=self.letters_checkbox.isChecked(),
                use_digits=self.digits_checkbox.isChecked(),
                use_special_characters=self.special_characters_checkbox.isChecked())
        else:
            self.reset_iterations()
            self.message_label.setText(
                '<span style="font-size: 10px; color: #aa0000;">Bei den aktuellen Einstellungen ' +
                'kann kein Passwort berechnet werden.</span>')
            self.message_label.setVisible(True)
            return False
        password = self.generator.generate(
            master_password=self.maser_password_edit.text(),
            domain=self.domain_edit.text(),
            username=self.username_edit.text(),
            length=self.length_slider.sliderPosition(),
            iterations=self.iterations
        )
        self.password.setText(password)
        self.password.setTextInteractionFlags(Qt.TextSelectableByMouse | Qt.TextSelectableByKeyboard)
        self.clipboard.setText(password)
        self.message_label.setText(
            '<span style="font-size: 10px; color: #888888;">Das Passwort wurde ' + str(self.iterations) +
            ' mal gehasht <br />und in die Zwischenablage kopiert.</span>')
        self.message_label.setVisible(True)
        self.iterations += 1
Ejemplo n.º 21
0
class Panel(QWidget):
    def __init__(self, state, parent=None):
        super().__init__(parent=parent)
        self.state = state
        self.createWidgets()
        self.layoutWidgets()
        self.createConnections()
        self.tooltips.append((self, """<p><b>Groups panel</b></p>
<p>This panel shows the groups the current entry belongs to.</p>"""))

    def createWidgets(self):
        self.label = QLabel("Gro&ups")
        self.groupsList = QListWidget()
        self.tooltips.append((self.groupsList, """
<p><b>Groups</b> (Alt+U)</p>
<p>A (possibly empty) list of the current entry's groups.</p>"""))
        self.label.setBuddy(self.groupsList)
        self.closeButton = QToolButton()
        self.closeButton.setIcon(QIcon(":/hide.svg"))
        self.closeButton.setFocusPolicy(Qt.NoFocus)
        self.tooltips.append((self.closeButton, """<p><b>Hide</b></p>
<p>Hide the Groups panel.</p>
<p>Use <b>Spelling→Show Suggestions and Groups</b> to show it
again.</p>"""))
        self.helpButton = QToolButton()
        self.helpButton.setIcon(QIcon(":/help.svg"))
        self.helpButton.setFocusPolicy(Qt.NoFocus)
        self.tooltips.append((self.helpButton, "Help on the Groups panel."))

    def layoutWidgets(self):
        layout = QVBoxLayout()
        hbox = QHBoxLayout()
        hbox.addWidget(self.label)
        hbox.addStretch()
        hbox.addWidget(self.closeButton)
        hbox.addWidget(self.helpButton)
        layout.addLayout(hbox)
        layout.addWidget(self.groupsList)
        self.setLayout(layout)

    def createConnections(self):
        self.closeButton.clicked.connect(self.state.window.closeGroups)
        self.helpButton.clicked.connect(self.help)
        self.groupsList.itemDoubleClicked.connect(
            self.state.viewFilteredPanel.setGroup)

    def updateUi(self):
        enable = bool(self.state.model) and self.state.mode not in {
            ModeKind.NO_INDEX, ModeKind.CHANGE
        }
        self.setEnabled(enable)
        if enable:
            (self.state.window.entryActions.addToNormalGroupAction.setEnabled(
                self.state.model.normalGroupCount()))
            (self.state.window.entryActions.addToLinkedGroupAction.setEnabled(
                self.state.model.linkedGroupCount()))
            self.state.window.entryActions.removeFromGroupAction.setEnabled(
                self.groupsList.currentItem() is not None)

    def updateGroups(self):
        self.groupsList.clear()
        eid = self.state.viewAllPanel.view.selectedEid
        if eid is not None:
            for gid, name, linked in self.state.model.groupsForEid(
                    eid, withLinks=True):
                item = QListWidgetItem(name)
                item.setData(Qt.UserRole, gid)
                item.setIcon(
                    QIcon(":/grouplink.svg" if linked else ":/groups.svg"))
                self.groupsList.addItem(item)
        if self.groupsList.count():
            self.groupsList.setCurrentRow(0)
        self.updateUi()
        self.state.viewFilteredPanel.groupChanged()

    def clear(self):
        self.groupsList.clear()
        self.updateUi()

    def help(self):
        self.state.help("xix_ref_panel_grp.html")

    def __getattr__(self, name):
        return getattr(self.groupsList, name)
Ejemplo n.º 22
0
class Panel(QWidget):
    def __init__(self, state, parent=None):
        super().__init__(parent)
        self.state = state
        self.entry = None
        self.saf = Saf.AUTO
        self.peid = ROOT
        self.createWidgets()
        self.layoutWidgets()
        self.createConnections()
        self.showOrHideNotes()
        self.showOrHideSortAs()
        self.termEdit.setFocus()

    def createWidgets(self):
        self.helpButton = QToolButton()
        self.helpButton.setIcon(QIcon(":/help.svg"))
        self.helpButton.setFocusPolicy(Qt.NoFocus)
        self.tooltips.append((self.helpButton, "Help on the Entry panel."))
        self.addingLabel = Widgets.Label.HtmlLabel(CANCEL_ADD)
        self.addingLabel.hide()
        self.termLabel = QLabel("&Term")
        self.termEdit = Widgets.LineEdit.HtmlLineEdit(self.state)
        self.tooltips.append((self.termEdit, """\
<p><b>Term editor</b> (Alt+T)</p>
<p>The entry's term text styled (e.g., <b>bold</b>, <i>italic</i>), as
it should appear in the final index.</p>"""))
        self.spellHighlighter = Widgets.SpellHighlighter.Highlighter(
            self.state, self.termEdit.document())
        self.termLabel.setBuddy(self.termEdit)
        self.pagesLabel = QLabel("&Pages")
        self.pagesEdit = Widgets.LineEdit.HtmlPagesLineEdit(self.state,
                                                            maxLines=3)
        self.tooltips.append((self.pagesEdit, """\
<p><b>Pages editor</b> (Alt+P)</p>
<p>The entry's pages styled (e.g., <b>bold</b>, <i>italic</i>), as they
should appear in the final index.</p> <p>The pages are automatically
sorted, and exact duplicates are automatically removed.</p> <p>See also
<b>Index→Combine Overlapping Pages</b> and <b>Index→Renumber
Pages</b>.</p>"""))
        self.pagesLabel.setBuddy(self.pagesEdit)
        self.calcSortAsCheckBox = QCheckBox("&Automatically Calculate Sort As")
        self.tooltips.append((self.calcSortAsCheckBox, """\
<p><b>Automatically Calculate Sort As</b> (Alt+A)</p>
<p>This checkbox controls how the Sort As text is created.</p>
<p>If checked, {} will either automatically create the sort as
text, or will present some choices from which to choose the sort as
text, depending on the term text.</p>
<p>If unchecked, the sort as text should be entered
manually.</p>""".format(QApplication.applicationName())))
        self.calcSortAsCheckBox.setChecked(True)
        self.sortAsHelpButton = QToolButton()
        self.sortAsHelpButton.setIcon(QIcon(":/help.svg"))
        self.sortAsHelpButton.setFocusPolicy(Qt.NoFocus)
        self.tooltips.append(
            (self.sortAsHelpButton, "Help on the Sort As text."))
        self.sortAsEdit = Widgets.LineEdit.LineEdit(self.state)
        self.tooltips.append((self.sortAsEdit, """\
<p><b>Sort As editor</b> (Alt+S)</p>
<p>The entry's sort as text.</p>
<p>If the <b>Automatically Calculate Sort As</b> checkbox is unchecked,
manually enter the sort as text to use for sorting the entry.</p>
<p>Main entry's are sorted using the sort as text, so it is easy to
force a non-standard ordering by entering a custom sort as text.</p>
<p>Subentries are also sorted using the sort as text, but the first word
of a subentry will be ignored for sorting purposes if it is in the
Ignore Subentry Function words list (see <b>Index→Ignore Subentry
Function words</b>) <i>and</i> the <b>Index→Options, Rules,
Ignore Subenty Function Words</b> checkbox is checked for this
index.</p>"""))
        self.sortAsEdit.setEnabled(False)
        self.sortAsLabel = QLabel("&Sort As")
        self.sortAsLabel.setBuddy(self.sortAsEdit)
        self.sortAsLabel.setEnabled(False)
        self.xrefLabel = QLabel("&Cross-references")
        self.xrefList = Widgets.List.HtmlListWidget(self.state, minLines=4)
        self.tooltips.append((self.xrefList, """\
<p><b>Cross-references list</b> (Alt+C)</p>
<p>The list of the entry's see and see also cross-references, both
generic and to other entries.</p>
<p>To add a cross-reference to an entry, circle the <i>to</i> entry
(<b>Entry→Circle</b>), then go to the <i>from</i> entry and click
<img src=":/xref-add.svg" width={0} height={0}> or press
<b>Entry→Add Cross-reference</b> (See also the <b>Entry</b>
menu.)</p>""".format(TOOLTIP_IMAGE_SIZE)))
        self.xrefLabel.setBuddy(self.xrefList)
        self.notesLabel = QLabel("&Notes")
        self.notesEdit = Widgets.LineEdit.MultilineHtmlEdit(self.state)
        self.tooltips.append((self.notesEdit, """\
<p><b>Notes editor</b> (Alt+N)</p>
<p>The entry's notes.</p>
<p>The notes shown here are never output as part of
the index so may be freely used for any purpose.</p>
<p>If the notes facility isn't wanted, the notes can be hidden by
unchecking the <b>Index→Options, General, Show Notes</b>
checkbox.</p>"""))
        self.notesLabel.setBuddy(self.notesEdit)

    def layoutWidgets(self):
        form = QFormLayout()
        form.addRow(self.addingLabel)
        hbox = QHBoxLayout()
        hbox.addWidget(self.termEdit, 1)
        hbox.addWidget(self.helpButton)
        form.addRow(self.termLabel, hbox)
        form.addRow(self.pagesLabel, self.pagesEdit)
        hbox = QHBoxLayout()
        hbox.addWidget(self.calcSortAsCheckBox, 1)
        hbox.addWidget(self.sortAsHelpButton)
        form.addRow(hbox)
        form.addRow(self.sortAsLabel, self.sortAsEdit)
        vbox = QVBoxLayout()
        vbox.addLayout(form)
        vbox.addWidget(self.xrefLabel)
        vbox.addWidget(self.xrefList, 1)
        vbox.addWidget(self.notesLabel)
        vbox.addWidget(self.notesEdit, 1)
        self.setLayout(vbox)

    def createConnections(self):
        self.helpButton.clicked.connect(self.help)
        self.sortAsHelpButton.clicked.connect(
            lambda: self.help("xix_ref_sortas.html"))
        self.termEdit.textChanged.connect(self.termChanged)
        self.termEdit.cursorPositionChanged.connect(self.maybeSetSuggestions)
        self.termEdit.textChanged.connect(self.updateMode)
        self.termEdit.lostFocus.connect(self.maybeSave)
        self.termEdit.enterPressed.connect(
            lambda: self.tabAndMaybeSave(self.pagesEdit))
        self.pagesEdit.textChanged.connect(self.updateMode)
        self.pagesEdit.lostFocus.connect(self.maybeSave)
        self.pagesEdit.enterPressed.connect(
            lambda: self.tabAndMaybeSave(self.calcSortAsCheckBox))
        self.calcSortAsCheckBox.toggled.connect(self.calcSortAsToggled)
        self.sortAsEdit.textChanged.connect(self.updateMode)
        self.sortAsEdit.lostFocus.connect(self.maybeSave)
        self.sortAsEdit.enterPressed.connect(
            lambda: self.tabAndMaybeSave(self.xrefList))
        self.notesEdit.textChanged.connect(self.updateMode)
        self.notesEdit.lostFocus.connect(self.maybeSave)

    def help(self, page="xix_ref_panel_entry.html"):
        self.state.help(page)

    def tabAndMaybeSave(self, widget):
        self.maybeSave()
        widget.setFocus()

    def updateUi(self):
        enable = self.state.mode not in {ModeKind.NO_INDEX, ModeKind.CHANGE}
        self.setEnabled(enable)
        if enable:
            enable = (self.state.mode in {ModeKind.ADD, ModeKind.EDIT}
                      or not self.termEdit.isEmpty())
            for widget in (self.termEdit, self.pagesEdit,
                           self.calcSortAsCheckBox, self.xrefList,
                           self.notesEdit):
                widget.setEnabled(enable)
            self.sortAsEdit.setEnabled(
                enable and not self.calcSortAsCheckBox.isChecked())
            if self.state.mode is ModeKind.ADD:
                self.state.window.modeLabel.setText(
                    "<font color=green>Adding</font>")

    def updateDisplayFonts(self):
        for widget in (self.termEdit, self.sortAsEdit, self.pagesEdit,
                       self.notesEdit, self.xrefList):
            widget.updateDisplayFonts()

    def populateEditors(self, editors):
        editors |= {
            self.termEdit, self.sortAsEdit, self.pagesEdit, self.notesEdit
        }

    def maybeSave(self):
        if self.hasChanged():
            if not bool(self.sortAsEdit.toPlainText().strip()):
                sortas = self.state.model.sortBy(self.termEdit.toHtml(),
                                                 self.saf, self.peid
                                                 is not ROOT)
                self.sortAsEdit.setPlainText(sortas)
            self.state.save()

    def hasChanged(self):
        term = self.termEdit.toHtml()
        sortas = self.sortAsEdit.toPlainText().strip()
        pages = self.pagesEdit.toHtml()
        notes = self.notesEdit.toHtml()
        if self.entry is None:
            return bool(term or sortas or pages or notes)
        return (self.entry.term != term or self.entry.sortas != sortas
                or self.entry.pages != pages or self.entry.notes != notes
                or self.entry.saf != self.saf)

    def updateMode(self):
        if (self.state.mode not in {
                ModeKind.NO_INDEX, ModeKind.ADD, ModeKind.EDIT, ModeKind.CHANGE
        } and self.hasChanged()):
            self.state.setMode(ModeKind.EDIT)

    def clearForm(self):
        self.state.spellPanel.clearSuggestions()
        self.state.groupsPanel.clear()
        positions = Positions(self.termEdit.textCursor().position(),
                              self.sortAsEdit.textCursor().position(),
                              self.pagesEdit.textCursor().position(),
                              self.notesEdit.textCursor().position())
        self.termEdit.clear()
        self.calcSortAsCheckBox.setChecked(True)
        self.sortAsEdit.clear()
        self.pagesEdit.clear()
        self.xrefList.clear()
        self.notesEdit.clear()
        return positions

    def setEntry(self, entry):
        positions = self.clearForm()
        self.entry = entry
        if entry is not None:
            self.termEdit.setHtml(entry.term, positions.term)
            self.saf = entry.saf or Saf.AUTO
            self.calcSortAsCheckBox.setChecked(self.saf != Saf.CUSTOM)
            self.sortAsEdit.setPlainText(entry.sortas, positions.sortas)
            self.pagesEdit.setHtml(entry.pages, positions.pages)
            self.notesEdit.setHtml(entry.notes, positions.notes)
            for xref in list(self.state.model.xrefs(entry.eid)):
                kind = "See" if xref.kind is XrefKind.SEE else "See also"
                term = Lib.elidePatchHtml(self.state.model.termPath(
                    xref.to_eid),
                                          self.state,
                                          maxlen=None)
                item = QListWidgetItem("{} <i>{}</i> {}".format(
                    XREF_INDICATOR, kind, term))
                item.setData(Qt.UserRole, xref)
                self.xrefList.addItem(item)
            for xref in list(self.state.model.generic_xrefs(entry.eid)):
                kind = ("See (generic)" if xref.kind is XrefKind.SEE_GENERIC
                        else "See also (generic)")
                item = QListWidgetItem("{} <i>{}</i> {}".format(
                    XREF_INDICATOR, kind, xref.term))
                item.setData(Qt.UserRole, xref)
                self.xrefList.addItem(item)
            if self.xrefList.count():
                self.xrefList.setCurrentRow(0)
            self.state.updateGotoEids(entry.eid)
        self.state.groupsPanel.updateGroups()
        self.state.updateNavigationStatus()
        self.state.setMode(ModeKind.VIEW)

    @property
    def unknownWords(self):
        return self.spellHighlighter.unknownWords

    def termChanged(self):
        if self.addingLabel.isVisible():
            self.addingLabel.setText(CANCEL_ADD)
            text = self.termEdit.toPlainText()
            if bool(self.state.model):
                while text:
                    eid = self.state.model.firstForPrefix(text)
                    if eid is not None:
                        term = Lib.elidePatchHtml(self.state.model.term(eid),
                                                  self.state)
                        self.addingLabel.setText(CANCEL_ADD +
                                                 " and goto “{}”".format(term))
                        break
                    text = text[:-1]
        self.maybeSetSuggestions()

    def maybeSetSuggestions(self):
        word, _ = self.termEdit.wordAndPosition()
        if word:
            if self.termEdit.hasFocus():
                replacement = self.state.model.autoReplacementFor(word)
                if replacement is not None:
                    self.termEdit.replaceWord(replacement)
                    return
            self.state.spellPanel.populateSuggestions(word)
        else:
            self.state.spellPanel.clearSuggestions()

    def rememberWord(self):
        word = self.findNearestUnknownWord()
        if word:
            Spell.add(word, self.state.language.value)
            self.state.model.addSpellWord(word)
            self.spellHighlighter.rehighlight()

    def ignoreWord(self):
        word = self.findNearestUnknownWord()
        if word:
            self.spellHighlighter.wordsToIgnore.add(word)
            self.spellHighlighter.rehighlight()

    def findNearestUnknownWord(self):
        pos = self.termEdit.textCursor().position()
        where = -1
        unknownWord = None
        unknownWords = sorted(self.unknownWords)
        for i, word in unknownWords:
            if i > where and i <= pos:
                where = i
                unknownWord = word
            if i > pos:
                break
        if unknownWord is None and unknownWords:
            unknownWord = unknownWords[-1][1]
        return unknownWord

    def completeWithSuggested(self):
        index = self.state.spellPanel.currentRow()
        self.complete(index)

    def complete(self, i):
        item = self.state.spellPanel.item(i)
        if item:
            word = self.state.spellPanel.item(i).text()
            self.completeWord(word)

    def completeWord(self, word):
        word = COMPLETE_WORD_RX.sub("", word)
        if word:
            self.termEdit.replaceWord(word)

    def showOrHideNotes(self):
        settings = QSettings()
        visible = bool(
            int(settings.value(Gopt.Key.ShowNotes, Gopt.Default.ShowNotes)))
        self.notesLabel.setVisible(visible)
        self.notesEdit.setVisible(visible)

    def showOrHideSortAs(self):
        settings = QSettings()
        alwaysShowSortAs = bool(
            int(
                settings.value(Gopt.Key.AlwaysShowSortAs,
                               Gopt.Default.AlwaysShowSortAs)))
        editable = not self.calcSortAsCheckBox.isChecked()
        visible = alwaysShowSortAs or editable
        for widget in (self.sortAsLabel, self.sortAsEdit):
            widget.setVisible(visible)
            widget.setEnabled(editable)

    def calcSortAsToggled(self):
        self.showOrHideSortAs()
        self.updateMode()
        if self.calcSortAsCheckBox.isChecked():
            saf = self.saf if self.saf != Saf.CUSTOM else Saf.AUTO
            self.state.calculateSortAs(saf, force=True)
        else:
            self.saf = Saf.CUSTOM
Ejemplo n.º 23
0
class Mixin:
    def createWidgets(self):
        settings = QSettings()

        self.searchLabel = QLabel("Search For")
        self.searchLineEdit = QLineEdit()
        self.tooltips.append((self.searchLineEdit, """\
<p><b>Search For editor</b></p>
<p>The text or regular expression to search for.</p>"""))
        self.searchLabel.setBuddy(self.searchLineEdit)
        self.replaceLabel = QLabel("Replace With")
        self.replaceLineEdit = QLineEdit()
        self.tooltips.append((self.replaceLineEdit, """\
<p><b>Replace With editor</b></p>
<p>The replacement text (which may include backreferences, \\1, \\2,
etc., if a regular expression search is being made).</p>"""))
        self.replaceLabel.setBuddy(self.replaceLineEdit)

        self.allEntriesRadioButton = QRadioButton("All Entries")
        self.allEntriesRadioButton.setChecked(
            bool(int(settings.value("RP/All", 1))))
        self.tooltips.append((self.allEntriesRadioButton, """\
<p><b>All Entries</b></p>
<p>If checked, the search will consider every entry in the index.</p>"""))
        self.filteredEntriesRadioButton = QRadioButton("Filtered Entries")
        self.filteredEntriesRadioButton.setChecked(
            bool(int(settings.value("RP/Filtered", 0))))
        self.tooltips.append((self.filteredEntriesRadioButton, """\
<p><b>Filtered Entries</b></p>
<p>If checked, the search will consider only those entries that are in
the current filtered view.</p>"""))
        self.considerLabel = QLabel("Consider")
        self.scopeGroup = QButtonGroup()
        self.scopeGroup.addButton(self.allEntriesRadioButton)
        self.scopeGroup.addButton(self.filteredEntriesRadioButton)

        self.literalRadioButton = QRadioButton("Literal")
        self.literalRadioButton.setChecked(
            bool(int(settings.value("RP/Literal", 1))))
        self.tooltips.append((self.literalRadioButton, """<p><b>Literal</b></p>
<p>If checked, the <b>Search For</b> text will be searched for
literally.</p>"""))
        self.regexRadioButton = QRadioButton("Regex")
        self.regexRadioButton.setChecked(
            bool(int(settings.value("RP/Regex", 0))))
        self.tooltips.append((self.regexRadioButton, """<p><b>Regex</b></p>
<p>If checked, the <b>Search For</b> text will be searched for
as a regular expression pattern.</p>"""))
        self.matchAsGroup = QButtonGroup()
        self.matchAsGroup.addButton(self.literalRadioButton)
        self.matchAsGroup.addButton(self.regexRadioButton)
        self.ignoreCaseCheckBox = QCheckBox("Ignore Case")
        self.ignoreCaseCheckBox.setChecked(
            bool(int(settings.value("RP/ICase", 0))))
        self.tooltips.append((self.ignoreCaseCheckBox, """\
<p><b>Ignore Case</b></p>
<p>If checked, the <b>Search For</b> text will be searched for
case-insensitively.</p>"""))
        self.wholeWordsCheckBox = QCheckBox("Whole Words")
        self.wholeWordsCheckBox.setChecked(
            bool(int(settings.value("RP/WW", 0))))
        self.tooltips.append((self.wholeWordsCheckBox, """\
<p><b>Whole Words</b></p>
<p>If checked&mdash;and when <b>Literal</b> is checked&mdash;the
<b>Search For</b> text will be matched as whole words.</p>
<p>For example, “habit” will not match “habitat” when whole words is
checked.</p>
<p>(For regular expressions use \\b before and after each word to get
whole word matches.)</p>"""))

        self.replaceInLabel = QLabel("Look In")
        self.replaceInTermsCheckBox = QCheckBox("Terms")
        self.replaceInTermsCheckBox.setChecked(
            bool(int(settings.value("RP/Terms", 1))))
        self.tooltips.append((self.replaceInTermsCheckBox, """\
<p><b>Terms</b></p>
<p>If checked, the search will look in term texts.</p>"""))
        self.replaceInPagesCheckBox = QCheckBox("Pages")
        self.replaceInPagesCheckBox.setChecked(
            bool(int(settings.value("RP/Pages", 0))))
        self.tooltips.append((self.replaceInPagesCheckBox, """\
<p><b>Pages</b></p>
<p>If checked, the search will look in pages texts.</p>"""))
        self.replaceInNotesCheckBox = QCheckBox("Notes")
        self.replaceInNotesCheckBox.setChecked(
            bool(int(settings.value("RP/Notes", 0))))
        self.tooltips.append((self.replaceInNotesCheckBox, """\
<p><b>Notes</b></p>
<p>If checked, the search will look in notes texts.</p>"""))
        self.startButton = QPushButton(QIcon(":/edit-find.svg"),
                                       "Start Search")
        self.tooltips.append((self.startButton, """<p><b>Start Search</b></p>
<p>Start the search from the first entry in the index or the first entry
in the filtered view's entries.</p>"""))
        self.replaceButton = QPushButton(QIcon(":/edit-find-replace.svg"),
                                         "Replace")
        self.tooltips.append((self.replaceButton, """<p><b>Replace</b></p>
<p>Replace the highlighted text with the <b>Replace With</b> text (using
backreferences if they are in the replacement text and a <b>Regex</b>
search is underway), and then try to find the next matching text.</p>"""))
        self.skipButton = QPushButton(QIcon(":/skip.svg"), "S&kip")
        self.tooltips.append((self.skipButton, """<p><b>Skip</b></p>
<p>Skip the highlighted text and try to find the next matching
text.</p>"""))
        self.stopButton = QPushButton(QIcon(":/process-stop.svg"),
                                      "Stop Search")
        self.tooltips.append((self.stopButton, """<p><b>Stop Search</b></p>
<p>Stop the current search. This allows the search options to be
changed.</p>"""))
        self.closeButton = QToolButton()
        self.closeButton.setIcon(QIcon(":/hide.svg"))
        self.closeButton.setFocusPolicy(Qt.NoFocus)
        self.tooltips.append((self.closeButton, """<p><b>Hide</b></p>
<p>Hide the Search and Replace panel.</p>
<p>Press <b>Ctrl+H</b> or click <img src=":/edit-find-replace.svg"
width={0} height={0}> or click <b>Edit→Search and Replace</b> to show it
again.</p>""".format(TOOLTIP_IMAGE_SIZE)))
        self.helpButton = QToolButton()
        self.helpButton.setIcon(QIcon(":/help.svg"))
        self.helpButton.setFocusPolicy(Qt.NoFocus)
        self.tooltips.append(
            (self.helpButton, "Help on the Search and Replace panel."))

    def layoutWidgets(self):
        form = QFormLayout()
        hbox = QHBoxLayout()
        hbox.addWidget(self.searchLineEdit)
        hbox.addWidget(self.closeButton)
        form.addRow(self.searchLabel, hbox)
        hbox = QHBoxLayout()
        hbox.addWidget(self.replaceLineEdit)
        hbox.addWidget(self.helpButton)
        form.addRow(self.replaceLabel, hbox)
        hbox = QHBoxLayout()
        hbox.addWidget(self.allEntriesRadioButton)
        hbox.addWidget(self.filteredEntriesRadioButton)
        hbox.addStretch()
        form.addRow(self.considerLabel, hbox)
        hbox = QHBoxLayout()
        hbox.addWidget(self.literalRadioButton)
        hbox.addWidget(self.regexRadioButton)
        hbox.addStretch(1)
        hbox.addWidget(self.ignoreCaseCheckBox)
        hbox.addWidget(self.wholeWordsCheckBox)
        hbox.addStretch(5)
        form.addRow(QLabel("Match"), hbox)
        hbox = QHBoxLayout()
        hbox.addWidget(self.replaceInTermsCheckBox)
        hbox.addWidget(self.replaceInPagesCheckBox)
        hbox.addWidget(self.replaceInNotesCheckBox)
        hbox.addStretch()
        form.addRow(self.replaceInLabel, hbox)
        hbox = QHBoxLayout()
        hbox.addWidget(self.startButton)
        hbox.addWidget(self.replaceButton)
        hbox.addWidget(self.skipButton)
        hbox.addWidget(self.stopButton)
        hbox.addStretch()
        form.addRow(hbox)
        self.setLayout(form)

    def createConnections(self):
        self.helpButton.clicked.connect(self.help)
        self.stopButton.clicked.connect(self.stop)
        self.startButton.clicked.connect(self.start)
        self.replaceButton.clicked.connect(self.replace)
        self.skipButton.clicked.connect(self.skip)
        self.searchLineEdit.textChanged.connect(self.updateUi)
        self.searchLineEdit.returnPressed.connect(self.doAction)
        self.replaceLineEdit.textChanged.connect(self.updateUi)
        self.replaceLineEdit.returnPressed.connect(self.doAction)
        for button in (self.literalRadioButton, self.regexRadioButton,
                       self.ignoreCaseCheckBox, self.wholeWordsCheckBox,
                       self.replaceInTermsCheckBox,
                       self.replaceInPagesCheckBox,
                       self.replaceInNotesCheckBox):
            button.clicked.connect(self.updateUi)

    def doAction(self):
        button = None
        if self.skipButton.isEnabled():
            button = self.skipButton
        elif self.startButton.isEnabled():
            button = self.startButton
        if button is not None:
            button.setFocus()
            button.click()
        if self.skipButton.isEnabled():
            self.skipButton.setFocus()

    def help(self):
        self.state.help("xix_ref_panel_replace.html")
Ejemplo n.º 24
0
class TransferPanel(QWidget):
    '''
    Transfer Panel
    
    This Panel is the main dialog box for the Dive Computer Transfer GUI
    '''
    def __init__(self, parent=None):
        super(TransferPanel, self).__init__(parent)
        
        self._logbook = None
        self._logbookName = 'None'
        self._logbookPath = None
        
        self._createLayout()
        
        self._readSettings()
        self.setWindowTitle(self.tr('DC Transfer - %s') % self._logbookName)
        
    def _createLayout(self):
        'Create the Widget Layout'
        
        self._txtLogbook = QLineEdit()
        self._txtLogbook.setReadOnly(True)
        self._lblLogbook = QLabel(self.tr('&Logbook File:'))
        self._lblLogbook.setBuddy(self._txtLogbook)
        self._btnBrowse = QPushButton('...')
        self._btnBrowse.clicked.connect(self._btnBrowseClicked)
        self._btnBrowse.setStyleSheet('QPushButton { min-width: 24px; max-width: 24px; }')
        self._btnBrowse.setToolTip(self.tr('Browse for a Logbook'))
        
        self._cbxComputer = QComboBox()
        self._lblComputer = QLabel(self.tr('Dive &Computer:'))
        self._lblComputer.setBuddy(self._cbxComputer)
        self._btnAddComputer = QPushButton(QPixmap(':/icons/list-add.png'), self.tr(''))
        self._btnAddComputer.setStyleSheet('QPushButton { min-width: 24px; min-height: 24; max-width: 24px; max-height: 24; }')
        self._btnAddComputer.clicked.connect(self._btnAddComputerClicked)
        self._btnRemoveComputer = QPushButton(QPixmap(':/icons/list-remove.png'), self.tr(''))
        self._btnRemoveComputer.setStyleSheet('QPushButton { min-width: 24px; min-height: 24; max-width: 24px; max-height: 24; }')
        self._btnRemoveComputer.clicked.connect(self._btnRemoveComputerClicked)
        
        hbox = QHBoxLayout()
        hbox.addWidget(self._btnAddComputer)
        hbox.addWidget(self._btnRemoveComputer)
        
        gbox = QGridLayout()
        gbox.addWidget(self._lblLogbook, 0, 0)
        gbox.addWidget(self._txtLogbook, 0, 1)
        gbox.addWidget(self._btnBrowse, 0, 2)
        gbox.addWidget(self._lblComputer, 1, 0)
        gbox.addWidget(self._cbxComputer, 1, 1)
        gbox.addLayout(hbox, 1, 2)
        gbox.setColumnStretch(1, 1)
        
        self._pbTransfer = QProgressBar()
        self._pbTransfer.reset()
        self._txtStatus = QTextEdit()
        self._txtStatus.setReadOnly(True)
        
        self._btnTransfer = QPushButton(self.tr('&Transfer Dives'))
        self._btnTransfer.clicked.connect(self._btnTransferClicked)
        
        self._btnExit = QPushButton(self.tr('E&xit'))
        self._btnExit.clicked.connect(self.close)
        
        hbox = QHBoxLayout()
        hbox.addWidget(self._btnTransfer)
        hbox.addStretch()
        hbox.addWidget(self._btnExit)
        
        vbox = QVBoxLayout()
        vbox.addLayout(gbox)
        vbox.addWidget(self._pbTransfer)
        vbox.addWidget(self._txtStatus)
        vbox.addLayout(hbox)
        
        self.setLayout(vbox)
        
    def _closeLogbook(self):
        'Close the current Logbook'
        if self._logbook is None:
            return
        
        self._logbook = None
        self._logbookName = 'None'
        self._logbookPath = None
        
        self._txtLogbook.clear()
        self._cbxComputer.setModel(None)
        
        self._writeSettings()
        self.setWindowTitle(self.tr('DC Transfer - %s') % self._logbookName)
        
    def _openLogbook(self, path):
        'Open an existing Logbook'
        if self._logbook is not None:
            self._closeLogbook()
            
        if not os.path.exists(path):
            QMessageBox.critical(self, self.tr('Missing Logbook'), 
                self.tr('Logbook File "%s" does not exist.') % path)
            return
        
        #TODO: Handle a Schema Upgrade in a user-friendly manner
        self._logbook = Logbook(path, auto_update=False)
        self._logbookName = os.path.basename(path)
        self._logbookPath = path
        
        self._txtLogbook.setText(self._logbookPath)
        self._cbxComputer.setModel(DiveComputersModel(self._logbook))
        
        self._writeSettings()
        self.setWindowTitle(self.tr('DC Transfer - %s') % self._logbookName)
        
    def _readSettings(self):
        'Read main window settings from the configuration'
        settings = QSettings()
        settings.beginGroup('MainWindow')
        max = settings.value('max')
        size = settings.value('size')
        pos = settings.value('pos')
        file = settings.value('file')
        settings.endGroup()
        
        # Size and Position the Main Window
        if size is not None:
            self.resize(size)
        if pos is not None:
            self.move(pos)
            
        # HAX because QVariant is not exposed in PySide and the default
        # coercion to string is just stupid
        if max is not None and (max == 'true'):
            self.showMaximized()
        
        # Open the Logbook
        if file is not None:
            self._openLogbook(file)
        
    def _writeSettings(self):
        'Write settings to the configuration'
        settings = QSettings()
        settings.beginGroup('MainWindow')
        settings.setValue('pos', self.pos())
        settings.setValue('size', self.size())
        settings.setValue('max', self.isMaximized())
        settings.setValue('file', self._logbookPath)
        settings.endGroup()
        
    def closeEvent(self, e):
        'Intercept an OnClose event'
        self._writeSettings()
        e.accept()
        
    #--------------------------------------------------------------------------
    # Slots
    
    @QtCore.Slot()
    def _btnAddComputerClicked(self):
        'Add a Dive Computer'
        dc = AddDiveComputerWizard.RunWizard(self)
        
        if dc is not None:
            self._logbook.session.add(dc)
            self._logbook.session.commit()
            self._cbxComputer.model().reload()
            self._cbxComputer.setCurrentIndex(self._cbxComputer.findText(dc.name))
    
    @QtCore.Slot()
    def _btnRemoveComputerClicked(self):
        'Remove a Dive Computer'
        idx = self._cbxComputer.currentIndex()
        dc = self._cbxComputer.itemData(idx, Qt.UserRole+0)
        if QMessageBox.question(self, self.tr('Delete Dive Computer?'), 
                    self.tr('Are you sure you want to delete "%s"?') % dc.name,
                    QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) == QMessageBox.Yes:
            self._logbook.session.delete(dc)
            self._logbook.session.commit()
            self._cbxComputer.model().reload()
    
    @QtCore.Slot()
    def _btnBrowseClicked(self):
        'Browse for a Logbook File'
        if self._logbook is not None:
            dir = os.path.dirname(self._logbookPath)
        else:
            dir = os.path.expanduser('~')
        
        fn = QFileDialog.getOpenFileName(self,
            caption=self.tr('Select a Logbook file'), dir=dir,
            filter='Logbook Files (*.lbk);;All Files(*.*)')[0]    
        if fn == '':
            return
        if not os.path.exists(fn):
            if QMessageBox.question(self, self.tr('Create new Logbook?'), 
                    self.tr('Logbook "%s" does not exist. Would you like to create it?') % os.path.basename(fn),
                    QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) != QMessageBox.Yes:
                return
            Logbook.Create(fn)
        self._openLogbook(fn)
        
    @QtCore.Slot()
    def _btnTransferClicked(self):
        'Transfer Dives'
        idx = self._cbxComputer.currentIndex()
        dc = self._cbxComputer.itemData(idx, Qt.UserRole+0)
        
        if self._logbook.session.dirty:
            print "Flushing dirty session"
            self._logbook.rollback()
        
        self._txtLogbook.setEnabled(False)
        self._btnBrowse.setEnabled(False)
        self._cbxComputer.setEnabled(False)
        self._btnAddComputer.setEnabled(False)
        self._btnRemoveComputer.setEnabled(False)
        self._btnTransfer.setEnabled(False)
        self._btnExit.setEnabled(False)
        
        self._txtStatus.clear()
        
        thread = QThread(self)
        
        #FIXME: ZOMG HAX: Garbage Collector will eat TransferWorker when moveToThread is called
        #NOTE: Qt.QueuedConnection is important...
        self.worker = None
        self.worker = TransferWorker(dc)
        thread.started.connect(self.worker.start, Qt.QueuedConnection)
        self.worker.moveToThread(thread)
        self.worker.finished.connect(self._transferFinished, Qt.QueuedConnection)
        self.worker.finished.connect(self.worker.deleteLater, Qt.QueuedConnection)
        self.worker.finished.connect(thread.deleteLater, Qt.QueuedConnection)
        self.worker.progress.connect(self._transferProgress, Qt.QueuedConnection)
        self.worker.started.connect(self._transferStart, Qt.QueuedConnection)
        self.worker.status.connect(self._transferStatus, Qt.QueuedConnection)
        
        thread.start()
        
    @QtCore.Slot(str)
    def _transferStatus(self, msg):
        'Transfer Status Message'
        self._txtStatus.append(msg)
        
    @QtCore.Slot(int)
    def _transferStart(self, nBytes):
        'Transfer Thread Stated'
        if nBytes > 0:
            self._pbTransfer.setMaximum(nBytes)
        else:
            self._pbTransfer.setMaximum(100)
        self._pbTransfer.reset()
        
    @QtCore.Slot(int)
    def _transferProgress(self, nTransferred):
        'Transfer Thread Progress Event'
        self._pbTransfer.setValue(nTransferred)
        
    @QtCore.Slot(models.Dive)
    def _transferParsed(self, dive):
        'Transfer Thread Parsed Dive'
        self._logbook.session.add(dive)
        
    @QtCore.Slot()
    def _transferFinished(self):
        'Transfer Thread Finished'
        self._logbook.session.commit()
        
        self._txtLogbook.setEnabled(True)
        self._btnBrowse.setEnabled(True)
        self._cbxComputer.setEnabled(True)
        self._btnAddComputer.setEnabled(True)
        self._btnRemoveComputer.setEnabled(True)
        self._btnTransfer.setEnabled(True)
        self._btnExit.setEnabled(True)
Ejemplo n.º 25
0
class Form(QDialog):
    def __init__(self, state, parent=None):
        super().__init__(parent)
        Lib.prepareModalDialog(self)
        self.state = state
        self.setWindowTitle("Renumber Pages — {}".format(
            QApplication.applicationName()))
        self.createWidgets()
        self.layoutWidgets()
        self.createConnections()
        self.romanStartSpinBox.setFocus()
        self.updateUi()
        settings = QSettings()
        self.updateToolTips(
            bool(
                int(
                    settings.value(Gopt.Key.ShowDialogToolTips,
                                   Gopt.Default.ShowDialogToolTips))))

    def createWidgets(self):
        self.romanStartLabel = QLabel("&Roman from")
        self.romanStartSpinBox = Widgets.RomanSpinBox.SpinBox()
        self.tooltips.append((self.romanStartSpinBox, """\
<p><b>Roman from</b></p>
<p>The first roman page number to change.</p>"""))
        self.romanStartLabel.setBuddy(self.romanStartSpinBox)
        self.romanEndLabel = QLabel("to")
        self.romanEndSpinBox = Widgets.RomanSpinBox.SpinBox()
        self.romanEndSpinBox.setValue(200)
        self.tooltips.append((self.romanEndSpinBox, """\
<p><b>Roman, to</b></p>
<p>The last roman page number to change.</p>"""))
        self.romanChangeLabel = QLabel("change")
        self.romanChangeSpinBox = Widgets.ChangeSpinBox.SpinBox()
        self.romanChangeSpinBox.setRange(-100, 100)
        self.romanChangeSpinBox.setValue(0)
        self.romanChangeSpinBox.setMinimumWidth(
            self.romanChangeSpinBox.fontMetrics().width("W(no change)W"))
        self.tooltips.append((self.romanChangeSpinBox, """\
<p><b>Roman, change</b></p>
<p>The amount to change the roman page numbers in the Roman from&ndash;to
range.</p>"""))
        self.decimalStartLabel = QLabel("&Decimal from")
        self.decimalStartSpinBox = QSpinBox()
        self.decimalStartSpinBox.setAlignment(Qt.AlignRight)
        self.decimalStartLabel.setBuddy(self.decimalStartSpinBox)
        self.decimalStartSpinBox.setRange(1, 10000)
        self.tooltips.append((self.decimalStartSpinBox, """\
<p><b>Decimal from</b></p>
<p>The first decimal page number to change.</p>"""))
        self.decimalEndLabel = QLabel("to")
        self.decimalEndSpinBox = QSpinBox()
        self.decimalEndSpinBox.setAlignment(Qt.AlignRight)
        self.decimalEndSpinBox.setRange(1, 10000)
        self.decimalEndSpinBox.setValue(2000)
        self.tooltips.append((self.decimalEndSpinBox, """\
<p><b>Decimal, to</b></p>
<p>The last decimal page number to change.</p>"""))
        self.decimalChangeLabel = QLabel("change")
        self.decimalChangeSpinBox = Widgets.ChangeSpinBox.SpinBox()
        self.decimalChangeSpinBox.setRange(-100, 100)
        self.decimalChangeSpinBox.setValue(0)
        self.tooltips.append((self.decimalChangeSpinBox, """\
<p><b>Decimal, change</b></p>
<p>The amount to change the decimal page numbers in the Decimal
from&ndash;to range.</p>"""))

        self.buttonBox = QDialogButtonBox()
        self.renumberButton = QPushButton(QIcon(":/renumberpages.svg"),
                                          "Re&number")
        self.tooltips.append((self.renumberButton, """\
<p><b>Renumber</b></p>
<p>Renumber roman and decimal page numbers within the given ranges by
the specified amounts of change throughout the entire index.</p>"""))
        self.buttonBox.addButton(self.renumberButton,
                                 QDialogButtonBox.ActionRole)
        self.closeButton = QPushButton(QIcon(":/dialog-close.svg"), "&Cancel")
        self.tooltips.append((self.closeButton, """<p><b>Cancel</b></p>
<p>Close the dialog without making any changes to the index.</p>"""))
        self.buttonBox.addButton(self.closeButton, QDialogButtonBox.RejectRole)
        self.helpButton = QPushButton(QIcon(":/help.svg"), "Help")
        self.tooltips.append(
            (self.helpButton, "Help on the Renumber Pages dialog"))
        self.buttonBox.addButton(self.helpButton, QDialogButtonBox.HelpRole)

    def layoutWidgets(self):
        grid = QGridLayout()
        grid.addWidget(self.romanStartLabel, 0, 0)
        grid.addWidget(self.romanStartSpinBox, 0, 1)
        grid.addWidget(self.romanEndLabel, 0, 2)
        grid.addWidget(self.romanEndSpinBox, 0, 3)
        grid.addWidget(self.romanChangeLabel, 0, 4)
        grid.addWidget(self.romanChangeSpinBox, 0, 5)
        grid.addWidget(self.decimalStartLabel, 1, 0)
        grid.addWidget(self.decimalStartSpinBox, 1, 1)
        grid.addWidget(self.decimalEndLabel, 1, 2)
        grid.addWidget(self.decimalEndSpinBox, 1, 3)
        grid.addWidget(self.decimalChangeLabel, 1, 4)
        grid.addWidget(self.decimalChangeSpinBox, 1, 5)
        hbox = QHBoxLayout()
        hbox.addLayout(grid)
        hbox.addStretch()
        layout = QVBoxLayout()
        layout.addLayout(hbox)
        layout.addStretch()
        layout.addWidget(self.buttonBox)
        self.setLayout(layout)

    def createConnections(self):
        self.buttonBox.rejected.connect(self.reject)
        self.renumberButton.clicked.connect(self.renumber)
        for spinbox in (self.romanStartSpinBox, self.romanEndSpinBox,
                        self.romanChangeSpinBox, self.decimalStartSpinBox,
                        self.decimalEndSpinBox, self.decimalChangeSpinBox):
            spinbox.valueChanged.connect(self.updateUi)
        self.helpButton.clicked.connect(self.help)

    def updateUi(self):
        self._synchronize(self.romanStartSpinBox, self.romanEndSpinBox)
        self._synchronize(self.decimalStartSpinBox, self.decimalEndSpinBox)
        changeRoman = (
            (self.romanStartSpinBox.value() != self.romanEndSpinBox.value())
            and self.romanChangeSpinBox.value() != 0)
        changeDecimal = ((self.decimalStartSpinBox.value() !=
                          self.decimalEndSpinBox.value())
                         and self.decimalChangeSpinBox.value() != 0)
        self.renumberButton.setEnabled(changeRoman or changeDecimal)
        self._setPrefix(self.romanChangeSpinBox)
        self._setPrefix(self.decimalChangeSpinBox)

    def _synchronize(self, startSpinBox, endSpinBox):
        value = startSpinBox.value()
        if endSpinBox.value() < value:
            endSpinBox.setValue(value)

    def _setPrefix(self, spinbox):
        spinbox.setPrefix("+" if spinbox.value() > 0 else "")

    def help(self):
        self.state.help("xix_ref_dlg_renumpages.html")

    def renumber(self):  # No need to restore focus widget
        options = RenumberOptions(self.romanStartSpinBox.value(),
                                  self.romanEndSpinBox.value(),
                                  self.romanChangeSpinBox.value(),
                                  self.decimalStartSpinBox.value(),
                                  self.decimalEndSpinBox.value(),
                                  self.decimalChangeSpinBox.value())
        with Lib.DisableUI(self):
            self.state.model.renumber(options,
                                      self.state.window.reportProgress)
        message = "Renumber pages"
        if self.state.model.canUndo:
            self.state.model.can_undo.emit(True, message)
        if self.state.model.canRedo:
            self.state.model.can_redo.emit(True, message)
        self.state.updateUi()
        say("Renumbered pages", SAY_TIMEOUT)
        self.accept()
Ejemplo n.º 26
0
class Panel(QWidget):
    def __init__(self, state, parent=None):
        super().__init__(parent=parent)
        self.state = state
        self.createWidgets()
        self.layoutWidgets()
        self.createConnections()
        self.initialize()

    def createWidgets(self):
        self.label = QLabel("Suggestions")
        self.spellList = Widgets.List.HtmlListWidget(self.state)
        self.tooltips.append((self.spellList, """
<p><b>Suggestions</b> (Alt+N,Tab)</p>
<p>A (possibly empty) list of completions or replacements for the word
being typed in the <b>Term</b> editor.</p>"""))
        self.label.setBuddy(self.spellList)
        self.closeButton = QToolButton()
        self.closeButton.setIcon(QIcon(":/hide.svg"))
        self.closeButton.setFocusPolicy(Qt.NoFocus)
        self.tooltips.append((self.closeButton, """<p><b>Hide</b></p>
<p>Hide the Suggestions panel.</p>
<p>Use <b>Spelling→Show Suggestions and Groups</b> to show it
again.</p>"""))
        self.helpButton = QToolButton()
        self.helpButton.setIcon(QIcon(":/help.svg"))
        self.helpButton.setFocusPolicy(Qt.NoFocus)
        self.tooltips.append(
            (self.helpButton, "Help on the Suggestions panel."))

    def layoutWidgets(self):
        layout = QVBoxLayout()
        hbox = QHBoxLayout()
        hbox.addWidget(self.label)
        hbox.addStretch()
        hbox.addWidget(self.closeButton)
        hbox.addWidget(self.helpButton)
        layout.addLayout(hbox)
        layout.addWidget(self.spellList)
        self.setLayout(layout)

    def createConnections(self):
        self.closeButton.clicked.connect(self.state.window.closeSuggestions)
        self.helpButton.clicked.connect(self.help)

    def initialize(self):
        self.spellList.itemDoubleClicked.connect(self.complete)
        self.tooltips.append((self, """<p><b>Suggestions panel</b></p>
<p>When the text cursor is at the end of a word in the term line edit,
any suggestions for completing the word are listed here. To accept a
suggestion press <b>Ctrl+<i>number</i></b> or click one of the
<b>Spelling→Replace</b> menu options.</p>"""))

    def complete(self, item):
        self.state.entryPanel.completeWord(item.text())

    def updateUi(self):
        enable = self.state.mode not in {ModeKind.NO_INDEX, ModeKind.CHANGE}
        self.setEnabled(enable)

    def populateSuggestions(self, word):
        self.clearSuggestions()
        self.spellList.clear()
        actions = self.state.window.spellingActions.completionActions
        suggestions = Spell.suggest(word, self.state.language.value)
        try:
            suggestions.remove(word)
        except ValueError:
            pass  # OK if word isn't in suggestions
        for i, suggestion in enumerate(suggestions):
            if i < 9:
                text = "[Ctrl+{}] {}".format(i + 1, suggestion)
                actions[i].setText("&{} Replace with “{}”".format(
                    i + 1, suggestion))
                actions[i].setVisible(True)
            else:
                text = suggestion
            self.spellList.addItem(text)
        self.spellList.setCurrentRow(0 if self.spellList.count() else -1)
        self.state.window.spellingActions.updateUi()

    def clearSuggestions(self):
        self.spellList.clear()
        for action in self.state.window.spellingActions.completionActions:
            action.setVisible(False)
        self.state.window.spellingActions.updateUi()

    def help(self):
        self.state.help("xix_ref_panel_sug.html")

    def __getattr__(self, name):
        return getattr(self.spellList, name)
Ejemplo n.º 27
0
class Form(QDialog):  # Only use if there's a model present
    def __init__(self, state, parent=None):
        super().__init__(parent)
        Lib.prepareModalDialog(self)
        self.state = state
        self.formatActions = None
        self.extension = None
        self.markup = None
        self.dirty = False
        self.setWindowTitle("Custom Markup — {}".format(
            QApplication.applicationName()))
        self.createWidgets()
        self.layoutWidgets()
        self.createConnections()
        self.refresh()
        settings = QSettings()
        self.updateToolTips(
            bool(
                int(
                    settings.value(Gopt.Key.ShowDialogToolTips,
                                   Gopt.Default.ShowDialogToolTips))))

    def createWidgets(self):
        self.extensionLabel = QLabel("&Extension")
        self.extensionComboBox = QComboBox()
        for markup in self.state.model.markups():
            self.extensionComboBox.addItem(markup)
        self.tooltips.append((self.extensionComboBox, """\
<p><b>Extension</b></p>
<p>Choose the file extension to view and edit its custom markup.</p>"""))
        self.extensionLabel.setBuddy(self.extensionComboBox)
        self.helpButton = QPushButton(QIcon(":/help.svg"), "Help")
        self.tooltips.append(
            (self.helpButton, "Help on the Custom Markup dialog"))
        self.addButton = QPushButton(QIcon(":/add.svg"), "&Add...")
        self.tooltips.append((self.addButton, """\
<p><b>Add</b></p>
<p>Add a new custom markup to the index.</p>"""))
        self.deleteButton = QPushButton(QIcon(":/delete.svg"), "&Delete...")
        self.tooltips.append((self.deleteButton, """\
<p><b>Delete</b></p>
<p>Permanently delete the custom markup from the index's <tt>.xix</tt>
file. (Note that <tt>.ucp</tt> custom markup cannot be deleted.)</p>"""))
        self.closeButton = QPushButton(QIcon(":/dialog-close.svg"), "&Close")
        self.tooltips.append((self.closeButton, """<p><b>Close</b></p>
<p>Close the dialog.</p>"""))
        self.tabWidget = QTabWidget()
        self.documentPanel = CustomMarkupPanels.Document.Panel(
            self.state, self)
        self.characterPanel = CustomMarkupPanels.Character.Panel(
            self.state, self)
        self.tabWidget.addTab(self.documentPanel, "D&ocument")
        self.tabWidget.addTab(self.characterPanel, "C&haracter")

    def layoutWidgets(self):
        buttonBox = QDialogButtonBox()
        buttonBox.addButton(self.helpButton, QDialogButtonBox.HelpRole)
        buttonBox.addButton(self.addButton, QDialogButtonBox.ActionRole)
        buttonBox.addButton(self.deleteButton, QDialogButtonBox.ActionRole)
        buttonBox.addButton(self.closeButton, QDialogButtonBox.AcceptRole)
        hbox = QHBoxLayout()
        hbox.addWidget(self.extensionLabel)
        hbox.addWidget(self.extensionComboBox)
        hbox.addStretch()
        hbox.addWidget(buttonBox)

        vbox = QVBoxLayout()
        vbox.addLayout(hbox)
        vbox.addWidget(self.tabWidget, 1)

        self.setLayout(vbox)

    def createConnections(self):
        self.helpButton.clicked.connect(self.help)
        self.extensionComboBox.currentIndexChanged.connect(self.refresh)
        self.addButton.clicked.connect(self.add)
        self.deleteButton.clicked.connect(self.delete)
        self.closeButton.clicked.connect(self.accept)
        self.documentPanel.changed.connect(self.setDirty)
        self.characterPanel.changed.connect(self.setDirty)

    def help(self):
        self.state.help("xix_ref_dlg_markup.html")

    def setDirty(self):
        self.dirty = True

    def refresh(self):
        self.save()
        self.extension = self.extensionComboBox.currentText()
        if self.extension not in self.state.model.markups():
            self.markup = Output.Markup.user_markup()
        else:
            self.markup = self.state.model.markup(self.extension)
        self.documentPanel.populateFromMarkup(self.markup)
        self.characterPanel.populateFromMarkup(self.markup)
        self.deleteButton.setEnabled(self.extension != ".ucp")

    def save(self):
        if self.dirty and self.extension is not None:
            self.documentPanel.updateMarkup(self.markup)
            self.characterPanel.updateMarkup(self.markup)
            self.state.model.updateMarkup(self.extension, self.markup)
        self.dirty = False

    def add(self):  # No need to restore focus widget
        self.save()
        with Lib.DisableUI(self, forModalDialog=True):
            extension, ok = QInputDialog.getText(
                self, "Add Custom Markup -— {}".format(
                    QApplication.applicationName()), "Extension")
        if ok and extension and extension.strip():
            extension = extension.strip()
            if not extension.startswith("."):
                extension = "." + extension
            index = self.extensionComboBox.findText(extension, Qt.MatchExactly)
            if index != -1:
                self.extensionComboBox.setCurrentIndex(index)
            else:
                self.extension = extension
                self.markup = Output.Markup.user_markup()
                self.state.model.updateMarkup(self.extension, self.markup)
                self.extensionComboBox.addItem(extension)
                self.extensionComboBox.setCurrentIndex(
                    self.extensionComboBox.count() - 1)

    def delete(self):  # No need to restore focus widget
        index = self.extensionComboBox.currentIndex()
        if index == -1:
            return
        with Lib.Qt.DisableUI(self, forModalDialog=True):
            extension = self.extensionComboBox.currentText()
            reply = QMessageBox.question(
                self, "Delete Custom Markup — {}".format(
                    QApplication.applicationName()), """<p>Delete “{}”?<p>
<font color=red>Warning: deleting custom markup cannot be undone.</font>""".
                format(extension), QMessageBox.Yes | QMessageBox.No)
        if reply == QMessageBox.Yes:
            self.extensionComboBox.removeItem(index)
            if index < self.extensionComboBox.count():
                self.extensionComboBox.setCurrentIndex(index)
            else:
                self.extensionComboBox.setCurrentIndex(max(0, index - 1))
            self.state.model.deleteMarkup(extension)

    def reject(self):
        self.accept()

    def accept(self):
        self.save()
        super().accept()
Ejemplo n.º 28
0
class Panel(QWidget):
    def __init__(self, state, parent=None):
        super().__init__(parent)
        self.state = state
        self.createWidgets()
        self.layoutWidgets()
        self.clear()

    def clear(self):
        self.matchTexts = []
        self.prevFilter = None
        self.view.clear()
        self.filterComboBox.setCurrentIndex(0)
        self.filterTextComboBox.clear()
        self.filterTextIndex = -1

    def createWidgets(self):
        self.helpButton = QToolButton()
        self.helpButton.setIcon(QIcon(":/help.svg"))
        self.helpButton.setFocusPolicy(Qt.NoFocus)
        self.helpButton.clicked.connect(self.help)
        self.tooltips.append(
            (self.helpButton,
             """Help on the Suggestions or Filtered panel."""))
        self.view = Views.Filtered.View(self.state)
        self.tooltips.append((self.view, """<p><b>Filtered view</b></p>
<p>This view shows any entries that match the current <b>Filter</b>.</p>
<p>Press <b>F3</b> or click <img src=":/goto-found.svg" width={0}
height={0}> or click <b>Goto→Filtered</b> to go to the current filtered
entry.</p>""".format(TOOLTIP_IMAGE_SIZE)))
        self.view.match = ""
        self.filterLabel = QLabel(
            "Filter <font color=darkgreen>(Ctrl+F)</font>")
        self.filterComboBox = QComboBox()
        self.filterComboBox.setMaxVisibleItems(24)
        self.tooltips.append((self.filterComboBox, """\
<p><b>Filter combobox</b></p>
<p>Use this combobox to choose the filter to use.</p>
<p>The <b>Terms Matching</b>, <b>Pages Matching</b>, and <b>Notes
Matching</b> filters need a match text.</p>"""))
        self.filterLabel.setBuddy(self.filterComboBox)
        for filter in FilterKind:
            if not filter.isCheck:
                self.filterComboBox.addItem(filter.text, filter)
        self.filterComboBox.currentIndexChanged[int].connect(self.query)
        self.filterTextComboBox = ComboBox()
        self.filterTextComboBox.setEditable(True)
        self.filterTextComboBox.setDuplicatesEnabled(False)
        self.filterTextComboBox.currentIndexChanged[str].connect(self.setMatch)
        self.tooltips.append((self.filterTextComboBox, """\
<p><b>Filter Match editor</b></p>
<p>The text to match when using a <b>Terms Matching</b>, <b>Pages
Matching</b>, or <b>Notes Matching</b> filter.</p>
<p>For terms and notes, the filtered entries are chosen by
case-insensitively comparing with the match word or words.</p> <p>Add a
<tt>*</tt> after a word to match any words that begin with the text
preceding the <tt>*</tt>.</p> <p>For example, “comp*” will match
“compress”, “compulsory”, “computer”, “computed”, etc.</p>
<p>For pages, enter them as you would for an entry's pages, e.g.,
<tt>199,202-5</tt> to match entries whose pages equal or include
<tt>199,202,203,204,205</tt>, whether explicitly, or within page
ranges.</p>"""))
        self.view.pane.clickLine.connect(self.state.updateNavigationStatus)

    def layoutWidgets(self):
        layout = QVBoxLayout()
        hbox = QHBoxLayout()
        hbox.addWidget(self.filterLabel)
        hbox.addWidget(self.filterComboBox, 1)
        hbox.addWidget(self.filterTextComboBox, 2)
        hbox.addWidget(self.helpButton)
        layout.addLayout(hbox)
        layout.addWidget(self.view, 1)
        self.setLayout(layout)

    def setMatch(self, match=None):
        filter = FilterKind(
            self.filterComboBox.itemData(self.filterComboBox.currentIndex()))
        if match is None:
            match = self.filterTextComboBox.currentText()
        arg = match
        if filter in {
                FilterKind.IN_NORMAL_GROUP, FilterKind.IN_LINKED_GROUP,
                FilterKind.PAGES_ORDER
        }:
            arg = self.filterTextComboBox.itemData(
                self.filterTextComboBox.currentIndex())
        elif filter is FilterKind.ENTRIES_WITH_PAGES:
            arg = Pages.searchablePages(match)
        self.view.query(filter, arg)
        if match:
            with Lib.BlockSignals(self.filterTextComboBox):
                index = self.filterTextComboBox.findText(match)
                if index == -1:
                    self.filterTextComboBox.addItem(match)
                    self.filterTextIndex = (self.filterTextComboBox.count() -
                                            1)
                else:
                    self.filterTextIndex = index

    def requery(self):
        filterIndex = self.filterComboBox.currentIndex()
        if -1 < self.filterTextIndex < self.filterTextComboBox.count():
            textIndex = self.filterTextIndex
        else:
            textIndex = self.filterTextComboBox.currentIndex()
        eid = self.view.selectedEid
        self.filterComboBox.setCurrentIndex(0)
        self.filterTextComboBox.setCurrentIndex(0)
        QTimer.singleShot(0,
                          lambda index=filterIndex: self.filterComboBox.
                          setCurrentIndex(index))
        QTimer.singleShot(10,
                          lambda index=textIndex: self.filterTextComboBox.
                          setCurrentIndex(index))
        if eid is not None:
            QTimer.singleShot(20, lambda eid=eid: self.view.gotoEid(eid))

    def query(self):
        filter = FilterKind(
            self.filterComboBox.itemData(self.filterComboBox.currentIndex()))
        if filter in {
                FilterKind.IN_NORMAL_GROUP, FilterKind.IN_LINKED_GROUP,
                FilterKind.PAGES_ORDER
        }:
            self._setGroupOrPagesOrder()
        elif filter in {
                FilterKind.ENTRIES_WITH_PAGES, FilterKind.TERMS_MATCHING,
                FilterKind.NOTES_MATCHING
        }:
            self.filterTextComboBox.setEditable(True)
            self.filterTextComboBox.setEnabled(True)
            if self.matchTexts:
                with Lib.BlockSignals(self.filterTextComboBox):
                    self.filterTextComboBox.clear()
                    self.filterTextComboBox.addItems(self.matchTexts)
                self.matchTexts = []
            self.setMatch()
        else:
            self.filterTextComboBox.setEnabled(False)
            self.view.query(filter)
        self.prevFilter = filter

    def _setGroupOrPagesOrder(self, gid=None):
        self.filterTextComboBox.setEditable(False)
        self.filterTextComboBox.setEnabled(True)
        items = []
        filter = FilterKind(
            self.filterComboBox.itemData(self.filterComboBox.currentIndex()))
        if filter is FilterKind.IN_NORMAL_GROUP:
            items = list(self.state.model.normalGroups())
        elif filter is FilterKind.IN_LINKED_GROUP:
            items = list(self.state.model.linkedGroups())
        elif filter is FilterKind.PAGES_ORDER:
            items = [(int(x), x.text) for x in PagesOrderKind]
        if self.prevFilter not in {
                FilterKind.IN_NORMAL_GROUP, FilterKind.IN_LINKED_GROUP,
                FilterKind.PAGES_ORDER
        }:
            self.matchTexts = []
            for i in range(self.filterTextComboBox.count()):
                self.matchTexts.append(self.filterTextComboBox.itemText(i))
        with Lib.BlockSignals(self.filterTextComboBox):
            index = None
            self.filterTextComboBox.clear()
            for i, (itemId, name) in enumerate(items):
                self.filterTextComboBox.addItem(name, itemId)
                if gid is not None and gid == itemId:
                    index = i
            if index is not None:
                self.filterTextComboBox.setCurrentIndex(index)
        self.setMatch()

    def updateDisplayFonts(self):
        self.view.updateDisplayFonts()

    def help(self):
        self.state.help("xix_ref_panel_filter.html")

    def setGroup(self, groupItem=None):
        if groupItem is None:
            groupItem = self.state.groupsPanel.groupsList.currentItem()
        if groupItem is not None:
            gid = groupItem.data(Qt.UserRole)
            kind = (FilterKind.IN_LINKED_GROUP
                    if self.state.model.isLinkedGroup(gid) else
                    FilterKind.IN_NORMAL_GROUP)
            for i in range(self.filterComboBox.count()):
                if FilterKind(self.filterComboBox.itemData(i)) is kind:
                    self.filterComboBox.setCurrentIndex(i)
                    break
            self._setGroupOrPagesOrder(gid)

    def groupChanged(self):
        filter = FilterKind(
            self.filterComboBox.itemData(self.filterComboBox.currentIndex()))
        if filter in {FilterKind.IN_NORMAL_GROUP, FilterKind.IN_LINKED_GROUP}:
            self.view.refresh()
Ejemplo n.º 29
0
class Panel(QWidget):
    def __init__(self, state, config, parent):
        super().__init__(parent)
        self.state = state
        self.config = config
        self.form = parent
        self.createWidgets()
        self.layoutWidgets()
        self.createConnections()

    def createWidgets(self):
        self.formatPanel = Widgets.FormatPanel.Panel(self.state,
                                                     self,
                                                     editableFontSize=True)
        formatActions = self.formatPanel.formatActions

        self.titleLabel = QLabel("&Index Title")
        self.titleTextEdit = Widgets.LineEdit.HtmlLineEdit(
            self.state, formatActions=formatActions)
        self.titleLabel.setBuddy(self.titleTextEdit)
        self.titleTextEdit.setHtml(self.config.get(Gconf.Key.Title))
        self.form.tooltips.append((self.titleTextEdit, """\
<p><b>Index Title</b></p>
<p>The index's title. Leave blank if the title is to be added directly
in the output file.</p>"""))

        self.noteLabel = QLabel("Index &Note")
        self.noteTextEdit = Widgets.LineEdit.MultilineHtmlEdit(
            self.state, maxLines=8, formatActions=formatActions)
        self.noteLabel.setBuddy(self.noteTextEdit)
        self.noteTextEdit.setLineWrapMode(QTextEdit.FixedColumnWidth)
        self.noteTextEdit.setLineWrapColumnOrWidth(60)
        self.noteTextEdit.setWordWrapMode(QTextOption.WordWrap)
        self.noteTextEdit.setHtml(self.config.get(Gconf.Key.Note))
        self.form.tooltips.append((self.noteTextEdit, """\
<p><b>Index Note</b></p>
<p>The index's note. Leave blank if no note is required or if the note
is to be added directly in the output file.</p>"""))

        self.sectionsGroupBox = QGroupBox("Sections")
        self.blankBeforeLabel = QLabel("&Blank Lines Before")
        self.blankBeforeSpinBox = QSpinBox()
        self.blankBeforeSpinBox.setAlignment(Qt.AlignRight)
        self.blankBeforeLabel.setBuddy(self.blankBeforeSpinBox)
        self.blankBeforeSpinBox.setRange(0, 3)
        self.blankBeforeSpinBox.setValue(
            self.config.get(Gconf.Key.SectionPreLines))
        self.form.tooltips.append((self.blankBeforeSpinBox, """\
<p><b>Blank Lines Before</b></p>
<p>How many blank lines to output before a section. (A section is a
distinct part of the index, e.g., the ‘A’s.)</p>"""))
        self.blankAfterLabel = QLabel("Blank &Lines After")
        self.blankAfterSpinBox = QSpinBox()
        self.blankAfterSpinBox.setAlignment(Qt.AlignRight)
        self.blankAfterLabel.setBuddy(self.blankAfterSpinBox)
        self.blankAfterSpinBox.setRange(0, 3)
        self.blankAfterSpinBox.setValue(
            self.config.get(Gconf.Key.SectionPostLines))
        self.form.tooltips.append((self.blankAfterSpinBox, """\
<p><b>Blank Lines After</b></p>
<p>How many blank lines to output before after section's title. (A
section is a distinct part of the index, e.g., the ‘A’s.)</p>"""))
        self.sectionTitlesCheckBox = QCheckBox("&Output Titles")
        self.sectionTitlesCheckBox.setChecked(
            self.config.get(Gconf.Key.SectionTitles))
        self.form.tooltips.append((self.sectionTitlesCheckBox, """\
<p><b>Output Titles</b></p>
<p>If checked, section titles are output before each section, e.g., ‘A’,
before the As, ‘B’, before the Bs, and so on.</p>"""))
        self.sectionSpecialTitleLabel = QLabel("Special Section &Title")
        self.sectionSpecialTitleTextEdit = Widgets.LineEdit.HtmlLineEdit(
            self.state, formatActions=formatActions)
        self.sectionSpecialTitleLabel.setBuddy(
            self.sectionSpecialTitleTextEdit)
        self.sectionSpecialTitleTextEdit.setHtml(
            self.config.get(Gconf.Key.SectionSpecialTitle))
        self.form.tooltips.append((self.sectionSpecialTitleTextEdit, """\
<p><b>Special Section Title</b></p>
<p>If there are entries which precede the ‘A’ section, then this section
title will be used for them.</p>
<p>Note that even if this title isn't used, its font name and size will
be used for all the other section titles.</p>"""))

        size = self.font().pointSize() + (1 if WIN else 2)
        family = self.config.get(Gconf.Key.StdFont)
        size = self.config.get(Gconf.Key.StdFontSize, size)
        Lib.createFontBoxesFor(self,
                               "Std",
                               family,
                               size,
                               tooltips=self.form.tooltips,
                               which="Std.")
        self.onStdFontChange(False)
        family = self.config.get(Gconf.Key.AltFont)
        size = self.config.get(Gconf.Key.AltFontSize, size)
        Lib.createFontBoxesFor(self,
                               "Alt",
                               family,
                               size,
                               tooltips=self.form.tooltips,
                               which="Alt.")
        self.onAltFontChange(False)
        family = self.config.get(Gconf.Key.MonoFont)
        size = self.config.get(Gconf.Key.MonoFontSize, size)
        Lib.createFontBoxesFor(self,
                               "Mono",
                               family,
                               size,
                               mono=True,
                               tooltips=self.form.tooltips,
                               which="Mono.")
        self.onMonoFontChange(False)

        self.monoFontAsStrikeoutCheckbox = QCheckBox(
            "Output Mono. &Font as Strikeout")
        self.form.tooltips.append((self.monoFontAsStrikeoutCheckbox, """\
<p><b>Output Mono. Font as Strikeout</b></p>
<p>If checked, any text in the index that is styled as mono. font
family will be output using the std. font family&mdash;but with
<s>strikeout</s>.</p>"""))
        self.monoFontAsStrikeoutCheckbox.setChecked(
            self.config.get(Gconf.Key.MonoFontAsStrikeout))

        self.styleLabel = QLabel("St&yle")
        self.styleComboBox = QComboBox()
        self.styleLabel.setBuddy(self.styleComboBox)
        oldStyle = self.config.get(Gconf.Key.Style)
        index = -1
        for i, style in enumerate(StyleKind):
            self.styleComboBox.addItem(style.text, style.value)
            if style is oldStyle:
                index = i
        self.styleComboBox.setCurrentIndex(index)
        self.form.tooltips.append((self.styleComboBox, """\
<p><b>Style</b></p>
<p>The style of index to output.</p>"""))

        self.termPagesSepLabel = QLabel("T&erm-Pages Separator")
        self.termPagesSepTextEdit = Widgets.LineEdit.SpacesHtmlLineEdit(
            self.state, 3, formatActions=formatActions)
        self.termPagesSepLabel.setBuddy(self.termPagesSepTextEdit)
        self.termPagesSepTextEdit.setHtml(
            self.config.get(Gconf.Key.TermPagesSeparator))
        self.form.tooltips.append((self.termPagesSepTextEdit, """\
<p><b>Term-Pages Separator</b></p>
<p>The separator text to use between the end of an entry's term and its
pages.</p>{}""".format(BLANK_SPACE_HTML)))

        self.runInSepLabel = QLabel("&Run-in Separator")
        self.runInSepTextEdit = Widgets.LineEdit.SpacesHtmlLineEdit(
            self.state, 3, formatActions=formatActions)
        self.runInSepLabel.setBuddy(self.runInSepTextEdit)
        self.runInSepTextEdit.setHtml(self.config.get(
            Gconf.Key.RunInSeparator))
        self.form.tooltips.append((self.runInSepTextEdit, """\
<p><b>Run-in Separator</b></p>
<p>The separator text to use between run-in entries (for run-in style
index output).</p>{}""".format(BLANK_SPACE_HTML)))

        self.formatPanel.state.editors = [
            self.titleTextEdit, self.noteTextEdit,
            self.sectionSpecialTitleTextEdit, self.termPagesSepTextEdit,
            self.runInSepTextEdit
        ]

    def layoutWidgets(self):
        form = QFormLayout()
        hbox = QHBoxLayout()
        hbox.addStretch()
        hbox.addWidget(self.formatPanel)
        form.addRow(hbox)
        form.addRow(self.titleLabel, self.titleTextEdit)
        form.addRow(self.noteLabel, self.noteTextEdit)

        vbox = QVBoxLayout()
        hbox = QHBoxLayout()
        hbox.addWidget(self.blankBeforeLabel)
        hbox.addWidget(self.blankBeforeSpinBox)
        hbox.addWidget(self.blankAfterLabel)
        hbox.addWidget(self.blankAfterSpinBox)
        hbox.addStretch()
        vbox.addLayout(hbox)
        hbox = QHBoxLayout()
        hbox.addWidget(self.sectionTitlesCheckBox)
        hbox.addStretch()
        hbox.addWidget(self.sectionSpecialTitleLabel)
        hbox.addWidget(self.sectionSpecialTitleTextEdit)
        vbox.addLayout(hbox)
        self.sectionsGroupBox.setLayout(vbox)
        form.addRow(self.sectionsGroupBox)

        hbox = QHBoxLayout()
        hbox.addWidget(self.stdFontComboBox, 1)
        hbox.addWidget(self.stdFontSizeSpinBox)
        hbox.addStretch()
        label = QLabel("&Std. Font")
        label.setBuddy(self.stdFontComboBox)
        form.addRow(label, hbox)
        hbox = QHBoxLayout()
        hbox.addWidget(self.altFontComboBox, 1)
        hbox.addWidget(self.altFontSizeSpinBox)
        hbox.addStretch()
        label = QLabel("&Alt. Font")
        label.setBuddy(self.altFontComboBox)
        form.addRow(label, hbox)
        hbox = QHBoxLayout()
        hbox.addWidget(self.monoFontComboBox, 1)
        hbox.addWidget(self.monoFontSizeSpinBox)
        hbox.addStretch()
        label = QLabel("&Mono. Font")
        label.setBuddy(self.monoFontComboBox)
        form.addRow(label, hbox)

        grid = QGridLayout()
        grid.addWidget(self.monoFontAsStrikeoutCheckbox, 0, 0, 1, 2)
        grid.addWidget(self.termPagesSepLabel, 0, 2)
        grid.addWidget(self.termPagesSepTextEdit, 0, 3)
        grid.addWidget(self.styleLabel, 1, 0)
        grid.addWidget(self.styleComboBox, 1, 1)
        grid.addWidget(self.runInSepLabel, 1, 2)
        grid.addWidget(self.runInSepTextEdit, 1, 3)
        form.addRow(grid)
        self.setLayout(form)

    def createConnections(self):
        self.stdFontComboBox.currentFontChanged.connect(self.onStdFontChange)
        self.stdFontSizeSpinBox.valueChanged[int].connect(self.onStdFontChange)
        self.altFontComboBox.currentFontChanged.connect(self.onAltFontChange)
        self.altFontSizeSpinBox.valueChanged[int].connect(self.onAltFontChange)
        self.monoFontComboBox.currentFontChanged.connect(self.onMonoFontChange)
        self.monoFontSizeSpinBox.valueChanged[int].connect(
            self.onMonoFontChange)

    def onStdFontChange(self, propagate=True):
        font = QFont(self.stdFontComboBox.currentFont())
        font.setPointSize(self.stdFontSizeSpinBox.value())
        if propagate and bool(self.state.model):
            self.state.model.setConfig(Gconf.Key.StdFont, font.family())
            self.state.model.setConfig(Gconf.Key.StdFontSize, font.pointSize())

    def onAltFontChange(self, propagate=True):
        font = QFont(self.altFontComboBox.currentFont())
        font.setPointSize(self.altFontSizeSpinBox.value())
        if propagate and bool(self.state.model):
            self.state.model.setConfig(Gconf.Key.AltFont, font.family())
            self.state.model.setConfig(Gconf.Key.AltFontSize, font.pointSize())

    def onMonoFontChange(self, propagate=True):
        font = QFont(self.monoFontComboBox.currentFont())
        font.setPointSize(self.monoFontSizeSpinBox.value())
        if propagate and bool(self.state.model):
            self.state.model.setConfig(Gconf.Key.MonoFont, font.family())
            self.state.model.setConfig(Gconf.Key.MonoFontSize,
                                       font.pointSize())
Ejemplo n.º 30
0
class Form(QDialog):
    def __init__(self, state, parent=None):
        super().__init__(parent)
        Lib.prepareModalDialog(self)
        self.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Expanding)
        self.setWindowTitle("Copy Character — {}".format(
            QApplication.applicationName()))
        QShortcut(QKeySequence(QKeySequence.FindNext), self, self.findNext)
        self.state = state
        self.createWidgets()
        self.layoutWidgets()
        self.createConnections()
        self.findSizes(self.fontComboBox.currentFont())
        self.setToFamily(self.state.stdFontFamily)
        self.setToNearestSize(self.state.stdFontSize)
        settings = QSettings()
        self.updateToolTips(
            bool(
                int(
                    settings.value(Gopt.Key.ShowDialogToolTips,
                                   Gopt.Default.ShowDialogToolTips))))

    def createWidgets(self):
        self.fontLabel = QLabel("Fon&t:")
        self.fontComboBox = QFontComboBox()
        self.tooltips.append((self.fontComboBox, """\
<p><b>Font</b></p>
<p>The font for displaying the characters.</p>"""))
        self.fontLabel.setBuddy(self.fontComboBox)
        self.sizeLabel = QLabel("&Size:")
        self.sizeComboBox = QComboBox()
        self.tooltips.append((self.sizeComboBox, """\
<p><b>Size</b></p>
<p>The size of font for displaying the characters.</p>"""))
        self.sizeLabel.setBuddy(self.sizeComboBox)
        self.scrollArea = QScrollArea()
        self.scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.panel = Panel()
        self.scrollArea.setWidget(self.panel)
        self.copyTextLabel = QLabel("Copy T&ext")
        self.copyTextLineEdit = QLineEdit()
        self.tooltips.append((self.copyTextLineEdit, """\
<p><b>Copy Text editor</b></p>
<p>The text for copying to the clipboard when <b>Copy</b> is
pressed.</p>"""))
        self.copyTextLabel.setBuddy(self.copyTextLineEdit)
        self.findTextLabel = QLabel("&Find Text")
        self.findTextLineEdit = QLineEdit()
        self.tooltips.append((self.findTextLineEdit, """\
<p><b>Find Text editor</b></p>
<p>The name or partial name of Unicode characters to be found, e.g.,
“star” will match many characters, including U+22C6 “Star
operator”.</p>"""))
        self.findTextLabel.setBuddy(self.findTextLineEdit)
        self.buttonBox = QDialogButtonBox()
        self.addSelectedButton = QPushButton(QIcon(":/add.svg"),
                                             "&Add Selected")
        self.tooltips.append((self.addSelectedButton, """\
<p><b>Add Selected</b></p>
<p>Append the selected character to the <b>Copy Text</b> editor.</p>"""))
        self.buttonBox.addButton(self.addSelectedButton,
                                 QDialogButtonBox.ActionRole)
        self.findNextButton = QPushButton(QIcon(":/edit-find.svg"),
                                          "Find &Next")
        self.tooltips.append((self.findNextButton, """\
<p><b>Find Next</b></p>
<p>Find the next character whose Unicode name contains or equals the
<b>Find Text</b>.</p>"""))
        self.buttonBox.addButton(self.findNextButton,
                                 QDialogButtonBox.ActionRole)
        self.helpButton = QPushButton(QIcon(":/help.svg"), "Help")
        self.tooltips.append(
            (self.helpButton, "Help on the Copy Character dialog"))
        self.buttonBox.addButton(self.helpButton, QDialogButtonBox.HelpRole)
        self.closeButton = QPushButton(QIcon(":/dialog-close.svg"), "&Close")
        self.tooltips.append((self.closeButton, """<p><b>Cancel</b></p>
<p>Close the dialog.</p>"""))
        self.buttonBox.addButton(self.closeButton, QDialogButtonBox.RejectRole)

    def layoutWidgets(self):
        topLayout = QHBoxLayout()
        topLayout.addWidget(self.fontLabel)
        topLayout.addWidget(self.fontComboBox, 1)
        topLayout.addWidget(self.sizeLabel)
        topLayout.addWidget(self.sizeComboBox)

        bottomLayout = QHBoxLayout()
        bottomLayout.addWidget(self.copyTextLabel)
        bottomLayout.addWidget(self.copyTextLineEdit)
        bottomLayout.addWidget(self.findTextLabel)
        bottomLayout.addWidget(self.findTextLineEdit)

        layout = QVBoxLayout()
        layout.addLayout(topLayout)
        layout.addWidget(self.scrollArea, 1)
        layout.addLayout(bottomLayout)
        layout.addWidget(self.buttonBox)
        self.setLayout(layout)

    def createConnections(self):
        self.fontComboBox.activated[str].connect(self.panel.updateFont)
        self.sizeComboBox.currentIndexChanged[str].connect(
            self.panel.updateSize)
        self.panel.characterSelected.connect(self.copyTextLineEdit.insert)
        self.panel.fontResized.connect(self.updateSize)
        self.addSelectedButton.clicked.connect(self.addSelected)
        self.helpButton.clicked.connect(self.help)
        self.buttonBox.rejected.connect(self.accept)
        self.findNextButton.clicked.connect(self.findNext)
        self.findTextLineEdit.returnPressed.connect(self.findNext)

    def help(self):
        self.state.help("xix_ref_dlg_copychr.html")

    def findSizes(self, font):
        fontDatabase = QFontDatabase()
        currentSize = self.sizeComboBox.currentText()
        with Lib.BlockSignals(self.sizeComboBox):
            self.sizeComboBox.clear()
            if fontDatabase.isSmoothlyScalable(font.family(),
                                               fontDatabase.styleString(font)):
                for size in QFontDatabase.standardSizes():
                    self.sizeComboBox.addItem(str(size))
            else:
                for size in fontDatabase.smoothSizes(
                        font.family(), fontDatabase.styleString(font)):
                    self.sizeComboBox.addItem(str(size))
            self.sizeComboBox.setEditable(False)
        sizeIndex = self.sizeComboBox.findText(currentSize)
        if sizeIndex == -1:
            self.sizeComboBox.setCurrentIndex(
                max(0,
                    self.sizeComboBox.count() / 3))
        else:
            self.sizeComboBox.setCurrentIndex(sizeIndex)

    def accept(self):
        clipboard = QApplication.clipboard()
        text = self.copyTextLineEdit.text() or self.panel.currentChar
        clipboard.setText(text, QClipboard.Clipboard)
        clipboard.setText(text, QClipboard.Selection)
        if text:
            say("Copied “{}” to the clipboard".format(text), SAY_TIMEOUT)
        super().accept()

    def addSelected(self):
        char = self.panel.currentChar
        if char:
            self.copyTextLineEdit.setText(self.copyTextLineEdit.text() + char)
        self.findNextButton.setFocus()

    def setToFamily(self, family):
        family = family.casefold()
        for i in range(self.fontComboBox.count()):
            if self.fontComboBox.itemText(i).casefold() == family:
                self.fontComboBox.setCurrentIndex(i)
                break

    def setToNearestSize(self, size):
        below = 0
        belowIndex = -1
        above = 999
        aboveIndex = -1
        for i in range(self.sizeComboBox.count()):
            sz = int(self.sizeComboBox.itemText(i))
            if sz == size:
                self.sizeComboBox.setCurrentIndex(i)
                break
            if sz < size and sz > below:
                below = sz
                belowIndex = i
            if sz > size and sz < above:
                above = sz
                aboveIndex = i
        else:
            if abs(size - below) < abs(size - above):
                self.sizeComboBox.setCurrentIndex(belowIndex)
            else:
                self.sizeComboBox.setCurrentIndex(aboveIndex)

    def findNext(self):
        text = self.findTextLineEdit.text().strip().casefold()
        if text:
            start = self.panel.currentChar
            start = ord(start) if start else ord(" ")
            for i in range(start + 1, MAX_CHAR):
                try:
                    char = chr(i)
                    name = unicodedata.name(char).casefold()
                    if text in name:
                        self.panel.currentChar = char
                        self.panel.update()
                        y = (self.panel.squareSize * i) // COLUMNS
                        self.scrollArea.ensureVisible(0, y)
                        break
                except ValueError:
                    pass
            else:
                self.panel.currentChar = " "
                self.findNext()

    def keyPressEvent(self, event):
        key = event.key()
        if key in {Qt.Key_Enter, Qt.Key_Return}:
            if self.findTextLineEdit.text().strip():
                self.findNext()
            else:
                self.addSelectedButton.setFocus()

    def updateSize(self, squareSize):
        self.setMinimumWidth((COLUMNS + (1.5 if WIN else 1)) * squareSize)
Ejemplo n.º 31
0
class MainWindow(QWidget, object):
    master_password_label = None
    master_password_edit = None
    domain_label = None
    domain_edit = None
    username_label = None
    username_edit = None
    strength_label = None
    strength_selector = None
    password_label = None
    password = None
    sync_button = None
    clipboard_button = None
    setting = None
    decrypt_kgk_task = None
    settings_window = None

    def __init__(self):
        super(MainWindow, self).__init__()
        self.nam = QNetworkAccessManager()
        self.setWindowIcon(QIcon(os.path.join('icons', 'Logo_rendered_edited.png')))
        layout = QBoxLayout(QBoxLayout.TopToBottom)
        layout.setContentsMargins(0, 0, 0, 0)
        self.preference_manager = PreferenceManager()
        self.kgk_manager = KgkManager()
        self.kgk_manager.set_preference_manager(self.preference_manager)
        self.settings_manager = PasswordSettingsManager(self.preference_manager)
        self.setting_dirty = True
        # Header bar
        header_bar = QFrame()
        header_bar.setStyleSheet(
            "QWidget { background: rgb(40, 40, 40); } " +
            "QToolButton { background: rgb(40, 40, 40); }" +
            "QToolTip { color: rgb(255, 255, 255); background-color: rgb(20, 20, 20); " +
            "border: 1px solid white; }")
        header_bar.setAutoFillBackground(True)
        header_bar.setFixedHeight(45)
        header_bar_layout = QBoxLayout(QBoxLayout.LeftToRight)
        header_bar_layout.addStretch()
        header_bar.setLayout(header_bar_layout)
        layout.addWidget(header_bar)
        self.create_header_bar(header_bar_layout)
        # Widget area
        main_area = QFrame()
        main_layout = QBoxLayout(QBoxLayout.TopToBottom)
        main_area.setLayout(main_layout)
        layout.addWidget(main_area)
        self.create_main_area(main_layout)
        # Window layout
        layout.addStretch()
        main_layout.addStretch()
        self.setLayout(layout)
        settings = QSettings()
        size = settings.value("MainWindow/size")
        if not size:
            size = QSize(350, 450)
        self.resize(size)
        position = settings.value("MainWindow/pos")
        if not position:
            position = QPoint(0, 24)
        self.move(position)
        self.setWindowTitle("c't SESAM")
        self.master_password_edit.setFocus()
        self.show()

    # noinspection PyUnresolvedReferences
    def create_header_bar(self, layout):
        self.sync_button = QToolButton()
        self.sync_button.setIconSize(QSize(30, 30))
        self.sync_button.setIcon(QIcon(os.path.join("icons", "ic_action_sync.png")))
        self.sync_button.setStyleSheet("border: 0px;")
        self.sync_button.setToolTip("Sync")
        self.sync_button.clicked.connect(self.sync_clicked)
        self.sync_button.setVisible(False)
        layout.addWidget(self.sync_button)
        self.clipboard_button = QToolButton()
        self.clipboard_button.setIconSize(QSize(30, 30))
        self.clipboard_button.setIcon(QIcon(os.path.join("icons", "ic_action_copy.png")))
        self.clipboard_button.setStyleSheet("border: 0px;")
        self.clipboard_button.setToolTip("in die Zwischenablage")
        self.clipboard_button.clicked.connect(self.copy_to_clipboard)
        self.clipboard_button.setVisible(False)
        layout.addWidget(self.clipboard_button)

    # noinspection PyUnresolvedReferences
    def create_main_area(self, layout):
        # Master password
        master_password_label = QLabel("&Master-Passwort:")
        self.master_password_edit = QLineEdit()
        self.master_password_edit.setEchoMode(QLineEdit.EchoMode.Password)
        self.master_password_edit.textChanged.connect(self.masterpassword_changed)
        self.master_password_edit.returnPressed.connect(self.move_focus)
        self.master_password_edit.editingFinished.connect(self.masterpassword_entered)
        self.master_password_edit.setMaximumHeight(28)
        master_password_label.setBuddy(self.master_password_edit)
        layout.addWidget(master_password_label)
        layout.addWidget(self.master_password_edit)
        # Domain
        domain_label = QLabel("&Domain:")
        self.domain_edit = QComboBox()
        self.domain_edit.setEditable(True)
        self.domain_edit.textChanged.connect(self.domain_changed)
        self.domain_edit.currentIndexChanged.connect(self.domain_changed)
        self.domain_edit.lineEdit().editingFinished.connect(self.domain_entered)
        self.domain_edit.lineEdit().returnPressed.connect(self.move_focus)
        self.domain_edit.setMaximumHeight(28)
        domain_label.setBuddy(self.domain_edit)
        layout.addWidget(domain_label)
        layout.addWidget(self.domain_edit)
        # Username
        self.username_label = QLabel("&Username:"******"&Passwortstärke:")
        self.strength_label.setVisible(False)
        self.strength_selector = PasswordStrengthSelector()
        self.strength_selector.set_min_length(4)
        self.strength_selector.set_max_length(36)
        self.strength_selector.setMinimumHeight(60)
        self.strength_selector.set_length(12)
        self.strength_selector.set_complexity(6)
        self.strength_selector.strength_changed.connect(self.strength_changed)
        self.strength_selector.setVisible(False)
        self.strength_label.setBuddy(self.strength_selector)
        layout.addWidget(self.strength_label)
        layout.addWidget(self.strength_selector)
        # Password
        self.password_label = QLabel("&Passwort:")
        self.password_label.setVisible(False)
        self.password = QLabel()
        self.password.setTextFormat(Qt.PlainText)
        self.password.setAlignment(Qt.AlignCenter)
        self.password.setFont(QFont("Helvetica", 18, QFont.Bold))
        self.password.setVisible(False)
        self.password_label.setBuddy(self.password)
        layout.addWidget(self.password_label)
        layout.addWidget(self.password)

    def set_masterpassword(self, masterpassword):
        self.master_password_edit.setText(masterpassword)

    def set_domain(self, domain):
        self.domain_edit.lineEdit().setText(domain)

    def closeEvent(self, *args, **kwargs):
        settings = QSettings()
        settings.setValue("MainWindow/size", self.size())
        settings.setValue("MainWindow/pos", self.pos())
        settings.sync()

    def masterpassword_changed(self):
        self.kgk_manager.reset()
        self.decrypt_kgk_task = None
        self.clipboard_button.setVisible(False)
        if len(self.master_password_edit.text()) > 0:
            self.sync_button.setVisible(True)
        else:
            self.sync_button.setVisible(False)

    def masterpassword_entered(self):
        if len(self.master_password_edit.text()) > 0 and not self.decrypt_kgk_task:
            self.kgk_manager.get_kgk_crypter_salt()
            self.decrypt_kgk_task = DecryptKgkTask(
                self.master_password_edit.text(),
                self.preference_manager,
                self.kgk_manager,
                self.settings_manager,
                self.domain_edit)

    def set_visibilities(self):
        if len(self.domain_edit.lineEdit().text()) > 0:
            self.username_label.setVisible(True)
            self.username_edit.setVisible(True)
            self.strength_label.setVisible(True)
            self.strength_selector.setVisible(True)
            self.password_label.setVisible(True)
            self.password.setVisible(True)
        else:
            self.username_label.setVisible(False)
            self.username_edit.setVisible(False)
            self.strength_label.setVisible(False)
            self.strength_selector.setVisible(False)
            self.password_label.setVisible(False)
            self.password.setVisible(False)
            self.clipboard_button.setVisible(False)

    def domain_changed(self):
        self.setting_dirty = True
        self.password.setText("")
        self.clipboard_button.setVisible(False)
        self.set_visibilities()
        if self.kgk_manager.has_kgk() and (not self.decrypt_kgk_task or not self.decrypt_kgk_task.is_running()) and \
           len(self.domain_edit.lineEdit().text()) > 0 and \
           self.domain_edit.lineEdit().text() in self.settings_manager.get_domain_list():
            self.domain_entered()

    def domain_entered(self):
        self.setting_dirty = self.domain_edit.lineEdit().text() not in self.settings_manager.get_domain_list()
        self.setting = self.settings_manager.get_setting(self.domain_edit.lineEdit().text())
        self.username_edit.blockSignals(True)
        self.username_edit.setText(self.setting.get_username())
        self.username_edit.blockSignals(False)
        self.strength_selector.blockSignals(True)
        self.strength_selector.set_length(self.setting.get_length())
        self.strength_selector.set_complexity(self.setting.get_complexity())
        self.strength_selector.set_extra_count(len(self.setting.get_extra_character_set()))
        self.strength_selector.blockSignals(False)
        self.generate_password()

    def move_focus(self):
        line_edits = [self.master_password_edit, self.domain_edit, self.username_edit]
        for i, edit in enumerate(line_edits):
            if edit.hasFocus() and i + 1 < len(line_edits):
                line_edits[i + 1].setFocus()
                return True
        self.generate_button.setFocus()

    def generate_password(self):
        if not self.kgk_manager.has_kgk():
            self.kgk_manager.create_new_kgk()
            self.kgk_manager.create_and_save_new_kgk_block()
        if not self.kgk_manager.kgk_crypter or not self.kgk_manager.salt:
            self.kgk_manager.get_kgk_crypter(self.master_password_edit.text().encode('utf-8'),
                                             self.kgk_manager.get_kgk_crypter_salt())
        if self.setting_dirty:
            self.setting.new_salt()
            self.setting.calculate_template()
        self.settings_manager.set_setting(self.setting)
        if not self.setting.get_legacy_password():
            generator = CtSesam(self.setting.get_domain(),
                                self.setting.get_username(),
                                self.kgk_manager.get_kgk(),
                                self.setting.get_salt(),
                                self.setting.get_iterations())
            password = generator.generate(self.setting)
        else:
            password = self.setting.get_legacy_password()
        self.password.setText(password)
        self.password.setTextInteractionFlags(Qt.TextSelectableByMouse | Qt.TextSelectableByKeyboard)
        self.clipboard_button.setVisible(True)
        self.settings_manager.store_local_settings(self.kgk_manager)
        self.setting_dirty = False

    def copy_to_clipboard(self):
        QApplication.clipboard().setText(self.password.text())

    def username_changed(self):
        if self.setting:
            if self.setting.get_username() != self.username_edit.text():
                self.setting.set_username(self.username_edit.text())
                self.setting_dirty = True
            self.generate_password()

    def strength_changed(self, complexity, length):
        if self.setting:
            if self.setting.get_length() != length:
                self.setting.set_length(length)
                self.setting_dirty = True
            if self.setting.get_complexity() != complexity:
                self.setting.set_complexity(complexity)
                self.setting_dirty = True
            self.generate_password()

    def migrate_local_domains(self, new_kgk_manager):
        for domain in self.settings_manager.get_domain_list():
            setting = self.settings_manager.get_setting(domain)
            generator = CtSesam(setting.get_domain(),
                                setting.get_username(),
                                self.kgk_manager.get_kgk(),
                                setting.get_salt(),
                                setting.get_iterations())
            setting.set_legacy_password(generator.generate(setting))
            self.settings_manager.set_setting(setting)
        self.kgk_manager = new_kgk_manager
        self.settings_manager.store_local_settings(self.kgk_manager)

    # noinspection PyUnresolvedReferences
    def sync_clicked(self):
        self.masterpassword_entered()
        if not self.settings_manager.sync_manager.has_settings():
            self.show_sync_settings()
        else:
            pull_successful, data = self.settings_manager.sync_manager.pull()
            if pull_successful and len(data) > 0:
                remote_kgk_manager = KgkManager()
                remote_kgk_manager.update_from_blob(self.master_password_edit.text().encode('utf-8'), b64decode(data))
                if len(self.preference_manager.get_kgk_block()) == 112 and \
                   remote_kgk_manager.has_kgk() and self.kgk_manager.has_kgk() and \
                   self.kgk_manager.get_kgk() != remote_kgk_manager.get_kgk():
                    if len(self.settings_manager.get_domain_list()) > 0:
                        print("Lokal und auf dem Server gibt es unterschiedliche KGKs. Das ist ein Problem!")
                    self.migrate_local_domains(remote_kgk_manager)
                else:
                    if len(self.preference_manager.get_kgk_block()) != 112:
                        self.kgk_manager = remote_kgk_manager
                        self.kgk_manager.set_preference_manager(self.preference_manager)
                        self.kgk_manager.store_local_kgk_block()
                    self.settings_manager.update_from_export_data(remote_kgk_manager, b64decode(data))
                    self.domain_edit.blockSignals(True)
                    current_domain = self.domain_edit.lineEdit().text()
                    for i in reversed(range(self.domain_edit.count())):
                        self.domain_edit.removeItem(i)
                    self.domain_edit.insertItems(0, self.settings_manager.get_domain_list())
                    self.domain_edit.blockSignals(False)
                    self.domain_edit.setEditText(current_domain)
            self.settings_manager.store_settings(self.kgk_manager)

    # noinspection PyUnresolvedReferences
    def show_sync_settings(self, url=None, username=None, password=None):
        self.settings_window = SettingsWindow(
            self.settings_manager.sync_manager,
            self.nam,
            url=self.settings_manager.sync_manager.server_address,
            username=self.settings_manager.sync_manager.username,
            password=self.settings_manager.sync_manager.password,
            certificate=self.settings_manager.sync_manager.certificate)
        self.settings_window.finished.connect(self.sync_clicked)
Ejemplo n.º 32
0
class Panel(QWidget):

    def __init__(self, state, config, parent):
        super().__init__(parent)
        self.state = state
        self.config = config
        self.form = parent
        self.createWidgets()
        self.layoutWidgets()
        self.createConnections()


    def createWidgets(self):
        settings = QSettings()

        self.txtGroupBox = QGroupBox("Plain Text Format (.txt)")
        self.indentLabel = QLabel("&Indent")
        self.indentComboBox = QComboBox()
        self.indentLabel.setBuddy(self.indentComboBox)
        oldIndent = IndentKind.TAB
        oldIndent = self.config.get(Gconf.Key.Indent, oldIndent)
        index = -1
        for i, indent in enumerate(IndentKind):
            text = indent.name.replace("_", " ").title()
            self.indentComboBox.addItem(text, indent.value)
            if indent is oldIndent:
                index = i
        self.indentComboBox.setCurrentIndex(index)
        self.form.tooltips.append((self.indentComboBox, """\
<p><b>Indent</b></p>
<p>The indentation to use when outputting an indented-style index in
plain text format for each level of indentation.</p>"""))

        self.rtfGroupBox = QGroupBox("Rich Text Format (.rtf)")
        self.rtfIndentLabel = QLabel("I&ndent")
        self.rtfIndentComboBox = QComboBox()
        self.rtfIndentLabel.setBuddy(self.rtfIndentComboBox)
        oldIndent = IndentKind(int(settings.value(Gopt.Key.IndentRTF,
                                                  Gopt.Default.IndentRTF)))
        index = -1
        for i, indent in enumerate(IndentKind):
            text = ("Indent" if i == 0 else
                    indent.name.replace("_", " ").title())
            self.rtfIndentComboBox.addItem(text, indent.value)
            if indent is oldIndent:
                index = i
        self.rtfIndentComboBox.setCurrentIndex(index)
        self.form.tooltips.append((self.rtfIndentComboBox, """\
<p><b>Indent</b></p>
<p>The indentation to use when outputting an indented-style index in
rich text format for each level of indentation.</p>"""))

        self.pdfGroupBox = QGroupBox("Portable Document Format (.pdf)")
        self.paperSizeLabel = QLabel("Paper Size")
        self.letterRadioButton = QRadioButton("&Letter")
        self.a4RadioButton = QRadioButton("&A4")
        size = PaperSizeKind(int(settings.value(Gopt.Key.PaperSize,
                                                Gopt.Default.PaperSize)))
        if size is PaperSizeKind.LETTER:
            self.letterRadioButton.setChecked(True)
        else:
            self.a4RadioButton.setChecked(True)
        self.form.tooltips.append((self.letterRadioButton, """\
<p><b>Paper Size, Letter</b></p>
<p>If checked, when outputting a PDF of the index, US Letter
8.5"x11"-sized pages will be used.</p>"""))
        self.form.tooltips.append((self.a4RadioButton, """\
<p><b>Paper Size, A4</b></p>
<p>If checked, when outputting a PDF of the index, European A4-sized
pages will be used.</p>"""))


    def layoutWidgets(self):
        hbox = QHBoxLayout()
        hbox.addWidget(self.indentLabel)
        hbox.addWidget(self.indentComboBox)
        hbox.addStretch()
        self.txtGroupBox.setLayout(hbox)

        hbox = QHBoxLayout()
        hbox.addWidget(self.rtfIndentLabel)
        hbox.addWidget(self.rtfIndentComboBox)
        hbox.addStretch()
        self.rtfGroupBox.setLayout(hbox)

        hbox = QHBoxLayout()
        hbox.addWidget(self.paperSizeLabel)
        hbox.addWidget(self.letterRadioButton)
        hbox.addWidget(self.a4RadioButton)
        hbox.addStretch()
        self.pdfGroupBox.setLayout(hbox)

        vbox = QVBoxLayout()
        vbox.addWidget(self.rtfGroupBox)
        vbox.addWidget(self.txtGroupBox)
        vbox.addWidget(self.pdfGroupBox)
        vbox.addStretch()

        self.setLayout(vbox)


    def createConnections(self):
        self.indentComboBox.currentIndexChanged.connect(self.setIndent)
        self.rtfIndentComboBox.currentIndexChanged.connect(
            self.setIndentRTF)


    def setIndent(self, index):
        index = self.indentComboBox.currentIndex()
        indent = int(self.indentComboBox.itemData(index))
        if bool(self.state.model):
            self.state.model.setConfig(Gconf.Key.Indent, indent)


    def setIndentRTF(self, index):
        index = self.rtfIndentComboBox.currentIndex()
        indent = int(self.rtfIndentComboBox.itemData(index))
        settings = QSettings()
        settings.setValue(Gopt.Key.IndentRTF, indent)
Ejemplo n.º 33
0
class WidgetBridge(object):
    __metaclass__ = WidgetBridgeFactory

    def __init__(self, parent, kind, path, **kwargs):
        self.parent = parent
        self.name = path
        propname = path.split(".")[-1]
        self.property = getattr(kind, propname)
        self.config = dict(self.property.config)
        self.config.update(kwargs)
        self.converter = self.config.get("displayconverter")
        if not self.converter:
            self.converter = DisplayConverter(
                                 suffix = self.config.get("suffix"),
                                 label = self.config.get("verbose_name", propname)
                             )
        if hasattr(self, "getDisplayConverter"):
            self.converter = self.getDisplayConverter(self.converter)
        self.converter.setProperty(self.property)
        self.choices = self.config.get("choices")
        self.hasLabel = self.config.get("has_label", True)
        self.assigned = None
        self.container = None
        self.suffix = None
        self.label = None
        self.widget = self.create()
        if not self.container:
            self.container = self.widget

    def getWidgetType(self):
        return self._qttype if hasattr(self, "_qttype") else None

    def create(self):
        self.widget = self._createWidget()
        if hasattr(self, "customize") and callable(self.customize):
            self.customize(self.widget)
        if self.converter.suffix(None):
            self.container = QWidget(self.parent)
            self.suffix = QLabel("", self.parent)
            hbox = QHBoxLayout(self.container)
            hbox.addWidget(self.widget)
            hbox.addWidget(self.suffix)
            hbox.addStretch(1)
            hbox.setContentsMargins(QMargins(0, 0, 0, 0))
        if self.converter.label(None) and self.hasLabel:
            self.label = QLabel(self.parent)
            self.label.setBuddy(self.widget)
        return self.widget

    def _createWidget(self):
        return self.getWidgetType()(parent = self.parent)

    def setValue(self, instance):
        if self.label:
            self.label.setText(str(self.converter.label(instance)) + ":")
        if self.suffix:
            self.suffix.setText(str(self.converter.suffix(instance)))
        value = getattr(instance, self.property.name)
        displayvalue = self.converter.to_display(value, instance)
        self.assigned = displayvalue
        self.apply(displayvalue)

    def apply(self, value):
        self.widget.setText(str(value))

    def getValue(self, instance):
        displayvalue = self.retrieve()
        value = self.converter.from_display(displayvalue, instance)
        return value

    def retrieve(self):
        return self._pytype(self.widget.text())

    def isModified(self):
        return self.assigned != self.retrieve()