Example #1
0
    def getWidgetFromParameter(self, param):
        if isinstance(param, ParameterBands):
            strings = self.getAvailableValuesOfType(ParameterBands)
            options = [(self.resolveValueDescription(s), s) for s in strings]
            item = QComboBox()
            item.setEditable(True)
            for desc, val in options:
                item.addItem(desc, val)
            item.setEditText(unicode(param.default or ""))
        else:
            item = ModelerParametersDialog.getWidgetFromParameter(self, param)

        return item
Example #2
0
class QuickWatch(QToolBar):
    def __init__(self, parent, distributedObjects):
        QToolBar.__init__(self, "QuickWatch")
        self.config = QuickWatchConfig()
        distributedObjects.configStore.registerConfigSet(self.config)

        self.setObjectName("QuickWatch")
        parent.addToolBar(self)
        self.watchedit = QComboBox()
        self.watchedit.setFixedHeight(28)
        self.watchedit.setInsertPolicy(QComboBox.NoInsert)
        self.watchedit.setEditable(True)
        self.watchedit.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        self.addWidget(self.watchedit)
        self.distributedObjects = distributedObjects
        self.addAction(Icons.watch, "Add to Watch", self.addToWatch)
        self.addAction(Icons.datagraph, "Add to Data Graph", self.addToDG)
        self.watchedit.lineEdit().returnPressed.connect(self.returnPressed)

    def __addCurrentText(self):
        text = self.watchedit.lineEdit().text()
        idx = self.watchedit.findText(text)
        if idx == -1:
            self.watchedit.addItem(text)
        self.watchedit.setEditText("")

    def returnPressed(self):
        if self.config.addTo.value == "Watch View":
            self.addToWatch()
        elif self.config.addTo.value == "Data Graph View":
            self.addToDG()

    def addToWatch(self):
        self.distributedObjects.watchModel.addVar(
            self.watchedit.lineEdit().text())
        self.__addCurrentText()

    def addToDG(self):
        self.distributedObjects.datagraphController.addWatch(
            self.watchedit.lineEdit().text())
        self.__addCurrentText()
Example #3
0
class QuickWatch(QToolBar):
    def __init__(self, parent, distributedObjects):
        QToolBar.__init__(self, "QuickWatch")
        self.config = QuickWatchConfig()
        distributedObjects.configStore.registerConfigSet(self.config)

        self.setObjectName("QuickWatch")
        parent.addToolBar(self)
        self.watchedit = QComboBox()
        self.watchedit.setFixedHeight(28)
        self.watchedit.setInsertPolicy(QComboBox.NoInsert)
        self.watchedit.setEditable(True)
        self.watchedit.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        self.addWidget(self.watchedit)
        self.distributedObjects = distributedObjects
        self.addAction(Icons.watch, "Add to Watch", self.addToWatch)
        self.addAction(Icons.datagraph, "Add to Data Graph", self.addToDG)
        self.watchedit.lineEdit().returnPressed.connect(self.returnPressed)

    def __addCurrentText(self):
        text = self.watchedit.lineEdit().text()
        idx = self.watchedit.findText(text)
        if idx == -1:
            self.watchedit.addItem(text)
        self.watchedit.setEditText("")

    def returnPressed(self):
        if self.config.addTo.value == "Watch View":
            self.addToWatch()
        elif self.config.addTo.value == "Data Graph View":
            self.addToDG()

    def addToWatch(self):
        self.distributedObjects.watchModel.addVar(self.watchedit.lineEdit().text())
        self.__addCurrentText()

    def addToDG(self):
        self.distributedObjects.datagraphController.addWatch(self.watchedit.lineEdit().text())
        self.__addCurrentText()
Example #4
0
class Printing(preferences.Group):
    def __init__(self, page):
        super(Printing, self).__init__(page)
        
        layout = QGridLayout(spacing=1)
        self.setLayout(layout)
        
        self.messageLabel = QLabel(wordWrap=True)
        self.printCommandLabel = QLabel()
        self.printCommand = widgets.urlrequester.UrlRequester()
        self.printCommand.setFileMode(QFileDialog.ExistingFile)
        self.printCommand.changed.connect(page.changed)
        self.printDialogCheck = QCheckBox(toggled=page.changed)
        self.resolutionLabel = QLabel()
        self.resolution = QComboBox(editable=True, editTextChanged=page.changed)
        self.resolution.addItems("300 600 1200".split())
        self.resolution.lineEdit().setInputMask("9000")

        layout.addWidget(self.messageLabel, 0, 0, 1, 2)
        layout.addWidget(self.printCommandLabel, 1, 0)
        layout.addWidget(self.printCommand, 1, 1)
        layout.addWidget(self.printDialogCheck, 2, 0, 1, 2)
        layout.addWidget(self.resolutionLabel, 3, 0)
        layout.addWidget(self.resolution, 3, 1)
        
        app.translateUI(self)
    
    def translateUI(self):
        self.setTitle(_("Printing Music"))
        self.messageLabel.setText(_(
            "Here you can enter a command to print a PDF or PostScript file. "
            "See the Help page for more information about printing music."))
        self.printCommandLabel.setText(_("Printing command:"))
        self.printCommand.setToolTip('<qt>' + _(
            "The printing command is used to print a PostScript or PDF file. "
            "On Linux you don't need this, but on Windows and Mac OS X you can "
            "provide a command to avoid that PDF documents are being printed "
            "using raster images, which is less optimal.\n"
            "<code>$pdf</code> gets replaced with the PDF filename, or alternatively, "
            "<code>$ps</code> is replaced with the PostScript filename. "
            "<code>$printer</code> is replaced with the printer's name to use."))
        self.printDialogCheck.setText(_("Use Frescobaldi's print dialog"))
        self.printDialogCheck.setToolTip('<qt>' + _(
            "If enabled, Frescobaldi will show the print dialog and create a "
            "PDF or PostScript document containing only the selected pages "
            "to print. Otherwise, the command is called directly and is expected "
            "to show a print dialog itself."))
        self.resolutionLabel.setText(_("Resolution:"))
        self.resolution.setToolTip(_(
            "Set the resolution if Frescobaldi prints using raster images."))
    
    def loadSettings(self):
        s = QSettings()
        s.beginGroup("helper_applications")
        self.printCommand.setPath(s.value("printcommand", "", type("")))
        self.printDialogCheck.setChecked(s.value("printcommand/dialog", False, bool))
        with qutil.signalsBlocked(self.resolution):
            self.resolution.setEditText(format(s.value("printcommand/dpi", 300, int)))
    
    def saveSettings(self):
        s= QSettings()
        s.beginGroup("helper_applications")
        s.setValue("printcommand", self.printCommand.path())
        s.setValue("printcommand/dialog", self.printDialogCheck.isChecked())
        s.setValue("printcommand/dpi", int(self.resolution.currentText()))
Example #5
0
 def getWidgetFromParameter(self, param):
     if isinstance(param, ParameterRaster):
         item = QComboBox()
         layers = self.getAvailableValuesOfType(ParameterRaster, OutputRaster)
         if param.optional:
             item.addItem(self.NOT_SELECTED, None)
         for layer in layers:
             item.addItem(self.resolveValueDescription(layer), layer)
     elif isinstance(param, ParameterVector):
         item = QComboBox()
         layers = self.getAvailableValuesOfType(ParameterVector, OutputVector)
         if param.optional:
             item.addItem(self.NOT_SELECTED, None)
         for layer in layers:
             item.addItem(self.resolveValueDescription(layer), layer)
     elif isinstance(param, ParameterTable):
         item = QComboBox()
         tables = self.getAvailableValuesOfType(ParameterTable, OutputTable)
         layers = self.getAvailableValuesOfType(ParameterVector, OutputVector)
         if param.optional:
             item.addItem(self.NOT_SELECTED, None)
         for table in tables:
             item.addItem(self.resolveValueDescription(table), table)
         for layer in layers:
             item.addItem(self.resolveValueDescription(layer), layer)
     elif isinstance(param, ParameterBoolean):
         item = QComboBox()
         item.addItem('Yes')
         item.addItem('No')
         bools = self.getAvailableValuesOfType(ParameterBoolean, None)
         for b in bools:
             item.addItem(self.resolveValueDescription(b), b)
     elif isinstance(param, ParameterSelection):
         item = QComboBox()
         item.addItems(param.options)
         item.setCurrentIndex(param.default)
     elif isinstance(param, ParameterFixedTable):
         item = FixedTablePanel(param)
     elif isinstance(param, ParameterRange):
         item = RangePanel(param)
     elif isinstance(param, ParameterMultipleInput):
         if param.datatype == ParameterMultipleInput.TYPE_VECTOR_ANY:
             options = self.getAvailableValuesOfType(ParameterVector, OutputVector)
         else:
             options = self.getAvailableValuesOfType(ParameterRaster, OutputRaster)
         opts = []
         for opt in options:
             opts.append(self.resolveValueDescription(opt))
         item = MultipleInputPanel(opts)
     elif isinstance(param, ParameterString):
         strings = self.getAvailableValuesOfType(ParameterString, OutputString)
         options = [(self.resolveValueDescription(s), s) for s in strings]
         if param.multiline:
             item = MultilineTextPanel(options)
             item.setText(unicode(param.default))
         else:
             item = QComboBox()
             item.setEditable(True)
             for desc, val in options:
                 item.addItem(desc, val)
             item.setEditText(unicode(param.default))
     elif isinstance(param, ParameterTableField):
         item = QComboBox()
         item.setEditable(True)
         fields = self.getAvailableValuesOfType(ParameterTableField, None)
         for f in fields:
             item.addItem(self.resolveValueDescription(f), f)
     elif isinstance(param, ParameterNumber):
         item = QComboBox()
         item.setEditable(True)
         numbers = self.getAvailableValuesOfType(ParameterNumber, OutputNumber)
         for n in numbers:
             item.addItem(self.resolveValueDescription(n), n)
         item.setEditText(unicode(param.default))
     elif isinstance(param, ParameterCrs):
         item = CrsSelectionPanel(param.default)
     elif isinstance(param, ParameterExtent):
         item = QComboBox()
         item.setEditable(True)
         extents = self.getAvailableValuesOfType(ParameterExtent, OutputExtent)
         if self.canUseAutoExtent():
             item.addItem(self.USE_MIN_COVERING_EXTENT, None)
         for ex in extents:
             item.addItem(self.resolveValueDescription(ex), ex)
         if not self.canUseAutoExtent():
             item.setEditText(unicode(param.default))
     elif isinstance(param, ParameterFile):
         item = QComboBox()
         item.setEditable(True)
         files = self.getAvailableValuesOfType(ParameterFile, OutputFile)
         for f in files:
             item.addItem(self.resolveValueDescription(f), f)
     elif isinstance(param, ParameterGeometryPredicate):
         item = GeometryPredicateSelectionPanel(param.enabledPredicates)
     else:
         item = QLineEdit()
         try:
             item.setText(unicode(param.default))
         except:
             pass
     return item
Example #6
0
class Dialog(QDialog):
    def __init__(self, parent=None):
        super(Dialog, self).__init__(parent)
        self._filename = None
        self._page = None
        self._rect = None
        self.imageViewer = widgets.imageviewer.ImageViewer()
        self.dpiLabel = QLabel()
        self.dpiCombo = QComboBox(insertPolicy=QComboBox.NoInsert, editable=True)
        self.dpiCombo.lineEdit().setCompleter(None)
        self.dpiCombo.setValidator(QDoubleValidator(10.0, 1200.0, 4, self.dpiCombo))
        self.dpiCombo.addItems([format(i) for i in (72, 100, 200, 300, 600, 1200)])
        
        self.colorButton = widgets.colorbutton.ColorButton()
        self.colorButton.setColor(QColor(Qt.white))
        self.crop = QCheckBox()
        self.antialias = QCheckBox(checked=True)
        self.dragfile = QPushButton(icons.get("image-x-generic"), None, None)
        self.fileDragger = FileDragger(self.dragfile)
        self.buttons = QDialogButtonBox(QDialogButtonBox.Close)
        self.copyButton = self.buttons.addButton('', QDialogButtonBox.ApplyRole)
        self.copyButton.setIcon(icons.get('edit-copy'))
        self.saveButton = self.buttons.addButton('', QDialogButtonBox.ApplyRole)
        self.saveButton.setIcon(icons.get('document-save'))
        
        layout = QVBoxLayout()
        self.setLayout(layout)
        
        layout.addWidget(self.imageViewer)
        
        controls = QHBoxLayout()
        layout.addLayout(controls)
        controls.addWidget(self.dpiLabel)
        controls.addWidget(self.dpiCombo)
        controls.addWidget(self.colorButton)
        controls.addWidget(self.crop)
        controls.addWidget(self.antialias)
        controls.addStretch()
        controls.addWidget(self.dragfile)
        layout.addWidget(widgets.Separator())
        layout.addWidget(self.buttons)

        app.translateUI(self)
        self.readSettings()
        self.finished.connect(self.writeSettings)
        self.dpiCombo.editTextChanged.connect(self.drawImage)
        self.colorButton.colorChanged.connect(self.drawImage)
        self.antialias.toggled.connect(self.drawImage)
        self.crop.toggled.connect(self.cropImage)
        self.buttons.rejected.connect(self.reject)
        self.copyButton.clicked.connect(self.copyToClipboard)
        self.saveButton.clicked.connect(self.saveAs)
        qutil.saveDialogSize(self, "copy_image/dialog/size", QSize(480, 320))
    
    def translateUI(self):
        self.setCaption()
        self.dpiLabel.setText(_("DPI:"))
        self.colorButton.setToolTip(_("Paper Color"))
        self.crop.setText(_("Auto-crop"))
        self.antialias.setText(_("Antialias"))
        self.dragfile.setText(_("Drag"))
        self.dragfile.setToolTip(_("Drag the image as a PNG file."))
        self.copyButton.setText(_("&Copy to Clipboard"))
        self.saveButton.setText(_("&Save As..."))
        self.imageViewer.setWhatsThis(_(
            #xgettext:no-python-format
            "<p>\n"
            "Clicking toggles the display between 100% size and window size. "
            "Drag to copy the image to another application. "
            "Drag with Ctrl (or {command}) to scroll a large image.\n"
            "</p>\n"
            "<p>\n"
            "You can also drag the small picture icon in the bottom right, "
            "which drags the actual file on disk, e.g. to an e-mail message.\n"
            "</p>").format(command="\u2318"))
        
    def readSettings(self):
        s = QSettings()
        s.beginGroup('copy_image')
        self.dpiCombo.setEditText(s.value("dpi", "100", type("")))
        self.colorButton.setColor(s.value("papercolor", QColor(Qt.white), QColor))
        self.crop.setChecked(s.value("autocrop", False, bool))
        self.antialias.setChecked(s.value("antialias", True, bool))
    
    def writeSettings(self):
        s = QSettings()
        s.beginGroup('copy_image')
        s.setValue("dpi", self.dpiCombo.currentText())
        s.setValue("papercolor", self.colorButton.color())
        s.setValue("autocrop", self.crop.isChecked())
        s.setValue("antialias", self.antialias.isChecked())
    
    def setCaption(self):
        if self._filename:
            filename = os.path.basename(self._filename)
        else:
            filename = _("<unknown>")
        title = _("Image from {filename}").format(filename = filename)
        self.setWindowTitle(app.caption(title))
        
    def setPage(self, page, rect):
        self._page = page
        self._rect = rect
        self._filename = documents.filename(page.document())
        self.fileDragger.basename = os.path.splitext(os.path.basename(self._filename))[0]
        self.setCaption()
        self.drawImage()

    def drawImage(self):
        dpi = float(self.dpiCombo.currentText() or '100')
        dpi = max(dpi, self.dpiCombo.validator().bottom())
        dpi = min(dpi, self.dpiCombo.validator().top())
        options = qpopplerview.RenderOptions()
        options.setPaperColor(self.colorButton.color())
        if self.antialias.isChecked():
            if popplerqt4:
                options.setRenderHint(
                    popplerqt4.Poppler.Document.Antialiasing |
                    popplerqt4.Poppler.Document.TextAntialiasing)
        else:
            options.setRenderHint(0)
        self._image = self._page.image(self._rect, dpi, dpi, options)
        self.cropImage()
    
    def cropImage(self):
        image = self._image
        if self.crop.isChecked():
            image = image.copy(autoCropRect(image))
        self.imageViewer.setImage(image)
        self.fileDragger.setImage(image)
    
    def copyToClipboard(self):
        QApplication.clipboard().setImage(self.imageViewer.image())

    def saveAs(self):
        if self._filename and not self.imageViewer.image().isNull():
            filename = os.path.splitext(self._filename)[0] + ".png"
        else:
            filename = 'image.png'
        filename = QFileDialog.getSaveFileName(self,
            _("Save Image As"), filename)
        if filename:
            if not self.imageViewer.image().save(filename):
                QMessageBox.critical(self, _("Error"), _(
                    "Could not save the image."))
            else:
                self.fileDragger.currentFile = filename
Example #7
0
 def getWidgetFromParameter(self, param):
     if isinstance(param, ParameterRaster):
         item = QComboBox()
         layers = self.getAvailableValuesOfType(ParameterRaster, OutputRaster)
         if param.optional:
             item.addItem(self.NOT_SELECTED, None)
         for layer in layers:
             item.addItem(self.resolveValueDescription(layer), layer)
     elif isinstance(param, ParameterVector):
         item = QComboBox()
         layers = self.getAvailableValuesOfType(ParameterVector, OutputVector)
         if param.optional:
             item.addItem(self.NOT_SELECTED, None)
         for layer in layers:
             item.addItem(self.resolveValueDescription(layer), layer)
     elif isinstance(param, ParameterTable):
         item = QComboBox()
         tables = self.getAvailableValuesOfType(ParameterTable, OutputTable)
         layers = self.getAvailableValuesOfType(ParameterVector, OutputVector)
         if param.optional:
             item.addItem(self.NOT_SELECTED, None)
         for table in tables:
             item.addItem(self.resolveValueDescription(table), table)
         for layer in layers:
             item.addItem(self.resolveValueDescription(layer), layer)
     elif isinstance(param, ParameterBoolean):
         item = QComboBox()
         item.addItem('Yes')
         item.addItem('No')
         bools = self.getAvailableValuesOfType(ParameterBoolean, None)
         for b in bools:
             item.addItem(self.resolveValueDescription(b), b)
     elif isinstance(param, ParameterSelection):
         item = QComboBox()
         item.addItems(param.options)
     elif isinstance(param, ParameterFixedTable):
         item = FixedTablePanel(param)
     elif isinstance(param, ParameterRange):
         item = RangePanel(param)
     elif isinstance(param, ParameterMultipleInput):
         if param.datatype == ParameterMultipleInput.TYPE_VECTOR_ANY:
             options = self.getAvailableValuesOfType(ParameterVector, OutputVector)
         else:
             options = self.getAvailableValuesOfType(ParameterRaster, OutputRaster)
         opts = []
         for opt in options:
             opts.append(self.resolveValueDescription(opt))
         item = MultipleInputPanel(opts)
     elif isinstance(param, ParameterString):
         strings = self.getAvailableValuesOfType(ParameterString, OutputString)
         options = [(self.resolveValueDescription(s), s) for s in strings]
         if param.multiline:
             item = MultilineTextPanel(options)
             item.setText(unicode(param.default))
         else:
             item = QComboBox()
             item.setEditable(True)
             for desc, val in options:
                 item.addItem(desc, val)
             item.setEditText(unicode(param.default))
     elif isinstance(param, ParameterTableField):
         item = QComboBox()
         item.setEditable(True)
         fields = self.getAvailableValuesOfType(ParameterTableField, None)
         for f in fields:
             item.addItem(self.resolveValueDescription(f), f)
     elif isinstance(param, ParameterNumber):
         item = QComboBox()
         item.setEditable(True)
         numbers = self.getAvailableValuesOfType(ParameterNumber, OutputNumber)
         for n in numbers:
             item.addItem(self.resolveValueDescription(n), n)
         item.setEditText(str(param.default))
     elif isinstance(param, ParameterCrs):
         item = CrsSelectionPanel(param.default)
     elif isinstance(param, ParameterExtent):
         item = QComboBox()
         item.setEditable(True)
         extents = self.getAvailableValuesOfType(ParameterExtent, OutputExtent)
         if self.canUseAutoExtent():
             item.addItem(self.USE_MIN_COVERING_EXTENT, None)
         for ex in extents:
             item.addItem(self.resolveValueDescription(ex), ex)
         if not self.canUseAutoExtent():
             item.setEditText(str(param.default))
     elif isinstance(param, ParameterFile):
         item = QComboBox()
         item.setEditable(True)
         files = self.getAvailableValuesOfType(ParameterFile, OutputFile)
         for f in files:
             item.addItem(self.resolveValueDescription(f), f)
     elif isinstance(param, ParameterGeometryPredicate):
         item = GeometryPredicateSelectionPanel(param.enabledPredicates)
     else:
         item = QLineEdit()
         try:
             item.setText(str(param.default))
         except:
             pass
     return item
Example #8
0
class FindInFilesDialog(QDialog, object):
    """ find in files dialog implementation """

    inProject = 0
    inDirectory = 1
    inOpenFiles = 2

    def __init__(self, where, what="", dirPath="", filters=[], parent=None):

        QDialog.__init__(self, parent)

        mainWindow = GlobalData().mainWindow
        self.editorsManager = mainWindow.editorsManagerWidget.editorsManager

        self.__cancelRequest = False
        self.__inProgress = False
        self.searchRegexp = None
        self.searchResults = []

        # Avoid pylint complains
        self.findCombo = None
        self.caseCheckBox = None
        self.wordCheckBox = None
        self.regexpCheckBox = None
        self.projectRButton = None
        self.openFilesRButton = None
        self.dirRButton = None
        self.dirEditCombo = None
        self.dirSelectButton = None
        self.filterCombo = None
        self.fileLabel = None
        self.progressBar = None
        self.findButton = None

        self.__createLayout()
        self.setWindowTitle("Find in files")

        # Restore the combo box values
        project = GlobalData().project
        if project.fileName != "":
            self.findFilesWhat = project.findFilesWhat
            self.findFilesDirs = project.findFilesDirs
            self.findFilesMasks = project.findFilesMasks
        else:
            settings = Settings()
            self.findFilesWhat = settings.findFilesWhat
            self.findFilesDirs = settings.findFilesDirs
            self.findFilesMasks = settings.findFilesMasks
        self.findCombo.addItems(self.findFilesWhat)
        self.findCombo.setEditText("")
        self.dirEditCombo.addItems(self.findFilesDirs)
        self.dirEditCombo.setEditText("")
        self.filterCombo.addItems(self.findFilesMasks)
        self.filterCombo.setEditText("")

        if where == self.inProject:
            self.setSearchInProject(what, filters)
        elif where == self.inDirectory:
            self.setSearchInDirectory(what, dirPath, filters)
        else:
            self.setSearchInOpenFiles(what, filters)

        return

    def __createLayout(self):
        """ Creates the dialog layout """

        self.resize(600, 300)
        self.setSizeGripEnabled(True)

        verticalLayout = QVBoxLayout(self)
        gridLayout = QGridLayout()

        # Combo box for the text to search
        findLabel = QLabel(self)
        findLabel.setText("Find text:")
        self.findCombo = QComboBox(self)
        self.__tuneCombo(self.findCombo)
        self.findCombo.lineEdit().setToolTip(
            "Regular expression to search for")
        self.findCombo.editTextChanged.connect(self.__someTextChanged)

        gridLayout.addWidget(findLabel, 0, 0, 1, 1)
        gridLayout.addWidget(self.findCombo, 0, 1, 1, 1)
        verticalLayout.addLayout(gridLayout)

        # Check boxes
        horizontalCBLayout = QHBoxLayout()
        self.caseCheckBox = QCheckBox(self)
        self.caseCheckBox.setText("Match &case")
        horizontalCBLayout.addWidget(self.caseCheckBox)
        self.wordCheckBox = QCheckBox(self)
        self.wordCheckBox.setText("Match whole &word")
        horizontalCBLayout.addWidget(self.wordCheckBox)
        self.regexpCheckBox = QCheckBox(self)
        self.regexpCheckBox.setText("Regular &expression")
        horizontalCBLayout.addWidget(self.regexpCheckBox)

        verticalLayout.addLayout(horizontalCBLayout)

        # Files groupbox
        filesGroupbox = QGroupBox(self)
        filesGroupbox.setTitle("Find in")
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            filesGroupbox.sizePolicy().hasHeightForWidth())
        filesGroupbox.setSizePolicy(sizePolicy)

        gridLayoutFG = QGridLayout(filesGroupbox)
        self.projectRButton = QRadioButton(filesGroupbox)
        self.projectRButton.setText("&Project")
        gridLayoutFG.addWidget(self.projectRButton, 0, 0)
        self.projectRButton.clicked.connect(self.__projectClicked)

        self.openFilesRButton = QRadioButton(filesGroupbox)
        self.openFilesRButton.setText("&Opened files only")
        gridLayoutFG.addWidget(self.openFilesRButton, 1, 0)
        self.openFilesRButton.clicked.connect(self.__openFilesOnlyClicked)

        self.dirRButton = QRadioButton(filesGroupbox)
        self.dirRButton.setText("&Directory tree")
        gridLayoutFG.addWidget(self.dirRButton, 2, 0)
        self.dirRButton.clicked.connect(self.__dirClicked)

        self.dirEditCombo = QComboBox(filesGroupbox)
        self.__tuneCombo(self.dirEditCombo)
        self.dirEditCombo.lineEdit().setToolTip("Directory to search in")
        gridLayoutFG.addWidget(self.dirEditCombo, 2, 1)
        self.dirEditCombo.editTextChanged.connect(self.__someTextChanged)

        self.dirSelectButton = QPushButton(filesGroupbox)
        self.dirSelectButton.setText("...")
        gridLayoutFG.addWidget(self.dirSelectButton, 2, 2)
        self.dirSelectButton.clicked.connect(self.__selectDirClicked)

        filterLabel = QLabel(filesGroupbox)
        filterLabel.setText("Files filter:")
        gridLayoutFG.addWidget(filterLabel, 3, 0)
        self.filterCombo = QComboBox(filesGroupbox)
        self.__tuneCombo(self.filterCombo)
        self.filterCombo.lineEdit().setToolTip("File names regular expression")
        gridLayoutFG.addWidget(self.filterCombo, 3, 1)
        self.filterCombo.editTextChanged.connect(self.__someTextChanged)

        verticalLayout.addWidget(filesGroupbox)

        # File label
        self.fileLabel = FitPathLabel(self)
        self.fileLabel.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Fixed)
        verticalLayout.addWidget(self.fileLabel)

        # Progress bar
        self.progressBar = QProgressBar(self)
        self.progressBar.setValue(0)
        self.progressBar.setOrientation(Qt.Horizontal)
        verticalLayout.addWidget(self.progressBar)

        # Buttons at the bottom
        buttonBox = QDialogButtonBox(self)
        buttonBox.setOrientation(Qt.Horizontal)
        buttonBox.setStandardButtons(QDialogButtonBox.Cancel)
        self.findButton = buttonBox.addButton("Find",
                                              QDialogButtonBox.AcceptRole)
        self.findButton.setDefault(True)
        self.findButton.clicked.connect(self.__process)
        verticalLayout.addWidget(buttonBox)

        buttonBox.rejected.connect(self.__onClose)
        return

    @staticmethod
    def __tuneCombo(comboBox):
        " Sets the common settings for a combo box "
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth( \
                            comboBox.sizePolicy().hasHeightForWidth() )
        comboBox.setSizePolicy(sizePolicy)
        comboBox.setEditable(True)
        comboBox.setInsertPolicy(QComboBox.InsertAtTop)
        comboBox.setAutoCompletion(False)
        comboBox.setDuplicatesEnabled(False)
        return

    def __onClose(self):
        " Triggered when the close button is clicked "

        self.__cancelRequest = True
        if not self.__inProgress:
            self.close()
        return

    def setSearchInProject(self, what="", filters=[]):
        " Set search ready for the whole project "

        if GlobalData().project.fileName == "":
            # No project loaded, fallback to opened files
            self.setSearchInOpenFiles(what, filters)
            return

        # Select the project radio button
        self.projectRButton.setEnabled(True)
        self.projectRButton.setChecked(True)
        self.dirEditCombo.setEnabled(False)
        self.dirSelectButton.setEnabled(False)

        openedFiles = self.editorsManager.getTextEditors()
        self.openFilesRButton.setEnabled(len(openedFiles) != 0)

        self.setFilters(filters)

        self.findCombo.setEditText(what)
        self.findCombo.lineEdit().selectAll()
        self.findCombo.setFocus()

        # Check searchability
        self.__testSearchability()
        return

    def setSearchInOpenFiles(self, what="", filters=[]):
        " Sets search ready for the opened files "

        openedFiles = self.editorsManager.getTextEditors()
        if len(openedFiles) == 0:
            # No opened files, fallback to search in dir
            self.setSearchInDirectory(what, "", filters)
            return

        # Select the radio buttons
        self.projectRButton.setEnabled(GlobalData().project.fileName != "")
        self.openFilesRButton.setEnabled(True)
        self.openFilesRButton.setChecked(True)
        self.dirEditCombo.setEnabled(False)
        self.dirSelectButton.setEnabled(False)

        self.setFilters(filters)

        self.findCombo.setEditText(what)
        self.findCombo.lineEdit().selectAll()
        self.findCombo.setFocus()

        # Check searchability
        self.__testSearchability()
        return

    def setSearchInDirectory(self, what="", dirPath="", filters=[]):
        " Sets search ready for the given directory "

        # Select radio buttons
        self.projectRButton.setEnabled(GlobalData().project.fileName != "")
        openedFiles = self.editorsManager.getTextEditors()
        self.openFilesRButton.setEnabled(len(openedFiles) != 0)
        self.dirRButton.setEnabled(True)
        self.dirRButton.setChecked(True)
        self.dirEditCombo.setEnabled(True)
        self.dirSelectButton.setEnabled(True)
        self.dirEditCombo.setEditText(dirPath)

        self.setFilters(filters)

        self.findCombo.setEditText(what)
        self.findCombo.lineEdit().selectAll()
        self.findCombo.setFocus()

        # Check searchability
        self.__testSearchability()
        return

    def setFilters(self, filters):
        " Sets up the filters "

        # Set filters if provided
        if filters:
            self.filterCombo.setEditText(";".join(filters))
        else:
            self.filterCombo.setEditText("")
        return

    def __testSearchability(self):
        " Tests the searchability and sets the Find button status "

        startTime = time.time()
        if self.findCombo.currentText().strip() == "":
            self.findButton.setEnabled(False)
            self.findButton.setToolTip("No text to search")
            return

        if self.dirRButton.isChecked():
            dirname = self.dirEditCombo.currentText().strip()
            if dirname == "":
                self.findButton.setEnabled(False)
                self.findButton.setToolTip("No directory path")
                return
            if not os.path.isdir(dirname):
                self.findButton.setEnabled(False)
                self.findButton.setToolTip("Path is not a directory")
                return

        # Now we need to match file names if there is a filter
        filtersText = self.filterCombo.currentText().strip()
        if filtersText == "":
            self.findButton.setEnabled(True)
            self.findButton.setToolTip("Find in files")
            return

        # Need to check the files match
        try:
            filterRe = re.compile(filtersText, re.IGNORECASE)
        except:
            self.findButton.setEnabled(False)
            self.findButton.setToolTip( "Incorrect files " \
                                        "filter regular expression" )
            return

        matched = False
        tooLong = False
        if self.projectRButton.isChecked():
            # Whole project
            for fname in GlobalData().project.filesList:
                if fname.endswith(sep):
                    continue
                matched = filterRe.match(fname)
                if matched:
                    break
                # Check the time, it might took too long
                if time.time() - startTime > 0.1:
                    tooLong = True
                    break

        elif self.openFilesRButton.isChecked():
            # Opened files
            openedFiles = self.editorsManager.getTextEditors()
            for record in openedFiles:
                matched = filterRe.match(record[1])
                if matched:
                    break
                # Check the time, it might took too long
                if time.time() - startTime > 0.1:
                    tooLong = True
                    break

        else:
            # Search in the dir
            if not dirname.endswith(sep):
                dirname += sep
            matched, tooLong = self.__matchInDir(dirname, filterRe, startTime)

        if matched:
            self.findButton.setEnabled(True)
            self.findButton.setToolTip("Find in files")
        else:
            if tooLong:
                self.findButton.setEnabled(True)
                self.findButton.setToolTip("Find in files")
            else:
                self.findButton.setEnabled(False)
                self.findButton.setToolTip("No files matched to search in")
        return

    @staticmethod
    def __matchInDir(path, filterRe, startTime):
        " Provides the 'match' and 'too long' statuses "
        matched = False
        tooLong = False
        for item in os.listdir(path):
            if time.time() - startTime > 0.1:
                tooLong = True
                return matched, tooLong
            if os.path.isdir(path + item):
                dname = path + item + sep
                matched, tooLong = FindInFilesDialog.__matchInDir(
                    dname, filterRe, startTime)
                if matched or tooLong:
                    return matched, tooLong
                continue
            if filterRe.match(path + item):
                matched = True
                return matched, tooLong
        return matched, tooLong

    def __projectClicked(self):
        " project radio button clicked "
        self.dirEditCombo.setEnabled(False)
        self.dirSelectButton.setEnabled(False)
        self.__testSearchability()
        return

    def __openFilesOnlyClicked(self):
        " open files only radio button clicked "
        self.dirEditCombo.setEnabled(False)
        self.dirSelectButton.setEnabled(False)
        self.__testSearchability()
        return

    def __dirClicked(self):
        " dir radio button clicked "
        self.dirEditCombo.setEnabled(True)
        self.dirSelectButton.setEnabled(True)
        self.dirEditCombo.setFocus()
        self.__testSearchability()
        return

    def __someTextChanged(self, text):
        " Text to search, filter or dir name has been changed "
        self.__testSearchability()
        return

    def __selectDirClicked(self):
        " The user selects a directory "
        dirName = QFileDialog.getExistingDirectory(
            self, "Select directory to search in",
            self.dirEditCombo.currentText(),
            QFileDialog.Options(QFileDialog.ShowDirsOnly))

        if dirName:
            self.dirEditCombo.setEditText(os.path.normpath(dirName))
        self.__testSearchability()
        return

    def __projectFiles(self, filterRe):
        " Project files list respecting the mask "
        mainWindow = GlobalData().mainWindow
        files = []
        for fname in GlobalData().project.filesList:
            if fname.endswith(sep):
                continue
            if filterRe is None or filterRe.match(fname):
                widget = mainWindow.getWidgetForFileName(fname)
                if widget is None:
                    # Do not check for broken symlinks
                    if isFileSearchable(fname, False):
                        files.append(ItemToSearchIn(fname, ""))
                else:
                    if widget.getType() in \
                                [ MainWindowTabWidgetBase.PlainTextEditor ]:
                        files.append(ItemToSearchIn(fname, widget.getUUID()))
            QApplication.processEvents()
            if self.__cancelRequest:
                raise Exception("Cancel request")
        return files

    def __openedFiles(self, filterRe):
        " Currently opened editor buffers "

        files = []
        openedFiles = self.editorsManager.getTextEditors()
        for record in openedFiles:
            uuid = record[0]
            fname = record[1]
            if filterRe is None or filterRe.match(fname):
                files.append(ItemToSearchIn(fname, uuid))
            QApplication.processEvents()
            if self.__cancelRequest:
                raise Exception("Cancel request")
        return files

    def __dirFiles(self, path, filterRe, files):
        " Files recursively for the dir "
        for item in os.listdir(path):
            QApplication.processEvents()
            if self.__cancelRequest:
                raise Exception("Cancel request")
            if os.path.isdir(path + item):
                if item in [".svn", ".cvs"]:
                    # It does not make sense to search in revision control dirs
                    continue
                anotherDir, isLoop = resolveLink(path + item)
                if not isLoop:
                    self.__dirFiles(anotherDir + sep, filterRe, files)
                continue
            if not os.path.isfile(path + item):
                continue
            realItem, isLoop = resolveLink(path + item)
            if isLoop:
                continue
            if filterRe is None or filterRe.match(realItem):
                found = False
                for itm in files:
                    if itm.fileName == realItem:
                        found = True
                        break
                if not found:
                    mainWindow = GlobalData().mainWindow
                    widget = mainWindow.getWidgetForFileName(realItem)
                    if widget is None:
                        if isFileSearchable(realItem):
                            files.append(ItemToSearchIn(realItem, ""))
                    else:
                        if widget.getType() in \
                                    [ MainWindowTabWidgetBase.PlainTextEditor ]:
                            files.append(
                                ItemToSearchIn(realItem, widget.getUUID()))
        return

    def __buildFilesList(self):
        " Builds the list of files to search in "
        filtersText = self.filterCombo.currentText().strip()
        if filtersText != "":
            filterRe = re.compile(filtersText, re.IGNORECASE)
        else:
            filterRe = None

        if self.projectRButton.isChecked():
            return self.__projectFiles(filterRe)

        if self.openFilesRButton.isChecked():
            return self.__openedFiles(filterRe)

        dirname = os.path.realpath(self.dirEditCombo.currentText().strip())
        files = []
        self.__dirFiles(dirname + sep, filterRe, files)
        return files

    def __process(self):
        " Search process "

        # Add entries to the combo box if required
        regexpText = self.findCombo.currentText()
        if regexpText in self.findFilesWhat:
            self.findFilesWhat.remove(regexpText)
        self.findFilesWhat.insert(0, regexpText)
        if len(self.findFilesWhat) > 32:
            self.findFilesWhat = self.findFilesWhat[:32]
        self.findCombo.clear()
        self.findCombo.addItems(self.findFilesWhat)

        filtersText = self.filterCombo.currentText().strip()
        if filtersText in self.findFilesMasks:
            self.findFilesMasks.remove(filtersText)
        self.findFilesMasks.insert(0, filtersText)
        if len(self.findFilesMasks) > 32:
            self.findFilesMasks = self.findFilesMasks[:32]
        self.filterCombo.clear()
        self.filterCombo.addItems(self.findFilesMasks)

        if self.dirRButton.isChecked():
            dirText = self.dirEditCombo.currentText().strip()
            if dirText in self.findFilesDirs:
                self.findFilesDirs.remove(dirText)
            self.findFilesDirs.insert(0, dirText)
            if len(self.findFilesDirs) > 32:
                self.findFilesDirs = self.findFilesDirs[:32]
            self.dirEditCombo.clear()
            self.dirEditCombo.addItems(self.findFilesDirs)

        # Save the combo values for further usage
        if GlobalData().project.fileName != "":
            GlobalData().project.setFindInFilesHistory(self.findFilesWhat,
                                                       self.findFilesDirs,
                                                       self.findFilesMasks)
        else:
            Settings().findFilesWhat = self.findFilesWhat
            Settings().findFilesDirs = self.findFilesDirs
            Settings().findFilesMasks = self.findFilesMasks

        self.__inProgress = True
        numberOfMatches = 0
        self.searchResults = []
        self.searchRegexp = None

        # Form the regexp to search
        if not self.regexpCheckBox.isChecked():
            regexpText = re.escape(regexpText)
        if self.wordCheckBox.isChecked():
            regexpText = "\\b%s\\b" % regexpText
        flags = re.UNICODE | re.LOCALE
        if not self.caseCheckBox.isChecked():
            flags |= re.IGNORECASE

        try:
            self.searchRegexp = re.compile(regexpText, flags)
        except:
            logging.error("Invalid search expression")
            self.close()
            return

        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        self.fileLabel.setPath('Building list of files to search in...')
        QApplication.processEvents()
        try:
            files = self.__buildFilesList()
        except Exception, exc:
            if "Cancel request" in str(exc):
                QApplication.restoreOverrideCursor()
                self.close()
                return
            else:
                QApplication.restoreOverrideCursor()
                logging.error(str(exc))
                self.close()
                return
        QApplication.restoreOverrideCursor()
        QApplication.processEvents()

        if len(files) == 0:
            self.fileLabel.setPath('No files to search in')
            return

        self.progressBar.setRange(0, len(files))

        index = 1
        for item in files:

            if self.__cancelRequest:
                self.__inProgress = False
                self.close()
                return

            self.fileLabel.setPath( 'Matches: ' + str( numberOfMatches ) + \
                                    ' Processing: ' + item.fileName )

            item.search(self.searchRegexp)
            found = len(item.matches)
            if found > 0:
                numberOfMatches += found
                self.searchResults.append(item)

            self.progressBar.setValue(index)
            index += 1

            QApplication.processEvents()

        if numberOfMatches == 0:
            if len(files) == 1:
                self.fileLabel.setPath("No matches in 1 file.")
            else:
                self.fileLabel.setPath( "No matches in " + \
                                        str( len( files ) ) + " files." )
            self.__inProgress = False
        else:
            self.close()
        return
class ScoreProperties(object):
    """This is only the base class, it should be mixed in with a widget or a different way."""

    def createWidgets(self):
        """Creates all widgets."""
        self.createKeySignatureWidget()
        self.createTimeSignatureWidget()
        self.createPickupWidget()
        self.createMetronomeWidget()
        self.createTempoWidget()
        
    def layoutWidgets(self, layout):
        """Adds all widgets to a vertical layout."""
        self.layoutKeySignatureWidget(layout)
        self.layoutTimeSignatureWidget(layout)
        self.layoutPickupWidget(layout)
        self.layoutMetronomeWidget(layout)
        self.layoutTempoWidget(layout)
        
    def translateWidgets(self):
        self.translateKeySignatureWidget()
        self.translateTimeSignatureWidget()
        self.translatePickupWidget()
        self.tranlateMetronomeWidget()
        self.translateTempoWidget()
    
    def ly(self, node, builder):
        """Adds appropriate LilyPond command nodes to the parent node.
        
        Settings from the builder are used where that makes sense.
        All widgets must be present.
        
        """
        self.lyKeySignature(node, builder)
        self.lyTimeSignature(node, builder)
        self.lyPickup(node, builder)
        self.lyTempo(node, builder)
    
    def globalSection(self, builder):
        """Returns a sequential expression between { } containing the output of ly()."""
        seq = ly.dom.Seq()
        self.ly(seq, builder)
        return seq
        
    # Key signature
    def createKeySignatureWidget(self):
        self.keySignatureLabel = QLabel()
        self.keyNote = QComboBox()
        self.keyNote.setModel(listmodel.ListModel(keyNames['nederlands'], self.keyNote))
        self.keyMode = QComboBox()
        self.keyMode.setModel(listmodel.ListModel(modes, self.keyMode, display=listmodel.translate_index(1)))
        self.keySignatureLabel.setBuddy(self.keyNote)
        
    def translateKeySignatureWidget(self):
        self.keySignatureLabel.setText(_("Key signature:"))
        self.keyMode.model().update()
    
    def layoutKeySignatureWidget(self, layout):
        """Adds our widgets to a layout, assuming it is a QVBoxLayout."""
        box = QHBoxLayout()
        box.addWidget(self.keySignatureLabel)
        box.addWidget(self.keyNote)
        box.addWidget(self.keyMode)
        layout.addLayout(box)

    def setPitchLanguage(self, language='nederlands'):
        self.keyNote.model()._data = keyNames[language or 'nederlands']
        self.keyNote.model().update()
    
    def lyKeySignature(self, node, builder):
        """Adds the key signature to the ly.dom node parent."""
        note, alter = keys[self.keyNote.currentIndex()]
        alter = fractions.Fraction(alter, 2)
        mode = modes[self.keyMode.currentIndex()][0]
        ly.dom.KeySignature(note, alter, mode, node).after = 1
        
    # Time signature
    def createTimeSignatureWidget(self):
        self.timeSignatureLabel = QLabel()
        self.timeSignature = QComboBox(editable=True)
        icons = {
            '(4/4)': symbols.icon('time_c44'),
            '(2/2)': symbols.icon('time_c22'),
        }
        self.timeSignature.setModel(listmodel.ListModel(timeSignaturePresets, self.timeSignature,
            icon=icons.get))
        self.timeSignature.setCompleter(None)
        self.timeSignatureLabel.setBuddy(self.timeSignature)
    
    def translateTimeSignatureWidget(self):
        self.timeSignatureLabel.setText(_("Time signature:"))
    
    def layoutTimeSignatureWidget(self, layout):
        """Adds our widgets to a layout, assuming it is a QVBoxLayout."""
        box = QHBoxLayout()
        box.addWidget(self.timeSignatureLabel)
        box.addWidget(self.timeSignature)
        layout.addLayout(box)
    
    def lyTimeSignature(self, node, builder):
        """Adds the time signature to the ly.dom node parent."""
        sig = self.timeSignature.currentText().strip()
        if '+' in sig:
            pass # TODO: implement support for \compoundMeter
        else:
            if sig == '(2/2)':
                ly.dom.TimeSignature(2, 2, node).after = 1
            elif sig == '(4/4)':
                ly.dom.TimeSignature(4, 4, node).after = 1
            else:
                match = re.search(r'(\d+).*?(\d+)', sig)
                if match:
                    if builder.lyVersion >= (2, 11, 44):
                        ly.dom.Line(r"\numericTimeSignature", node)
                    else:
                        ly.dom.Line(r"\override Staff.TimeSignature #'style = #'()", node)
                    num, beat = map(int, match.group(1, 2))
                    ly.dom.TimeSignature(num, beat, node).after = 1

    # Pickup bar
    def createPickupWidget(self):
        self.pickupLabel = QLabel()
        self.pickup = QComboBox()
        pickups = ['']
        pickups.extend(durations)
        self.pickup.setModel(listmodel.ListModel(pickups, self.pickup,
            display = lambda item: item or _("None"),
            icon = lambda item: symbols.icon('note_{0}'.format(item.replace('.', 'd'))) if item else None))
        self.pickup.view().setIconSize(QSize(22, 22))
        self.pickupLabel.setBuddy(self.pickup)
        
    def translatePickupWidget(self):
        self.pickupLabel.setText(_("Pickup measure:"))
        self.pickup.model().update()
        
    def layoutPickupWidget(self, layout):
        box = QHBoxLayout()
        box.addWidget(self.pickupLabel)
        box.addWidget(self.pickup)
        layout.addLayout(box)
    
    def lyPickup(self, node, builder):
        if self.pickup.currentIndex() > 0:
            dur, dots = partialDurations[self.pickup.currentIndex() - 1]
            ly.dom.Partial(dur, dots, parent=node)
    
    # Metronome value
    def createMetronomeWidget(self):
        self.metronomeLabel = QLabel()
        self.metronomeNote = QComboBox()
        self.metronomeNote.setModel(listmodel.ListModel(durations, display=None,
            icon = lambda item: symbols.icon('note_{0}'.format(item.replace('.', 'd')))))
        self.metronomeNote.setCurrentIndex(durations.index('4'))
        self.metronomeNote.view().setIconSize(QSize(22, 22))
        self.metronomeEqualSign = QLabel('=')
        self.metronomeEqualSign.setFixedWidth(self.metronomeEqualSign.minimumSizeHint().width())
        self.metronomeValue = QComboBox(editable=True)
        self.metronomeValue.setModel(listmodel.ListModel(metronomeValues, self.metronomeValue,
            display=format))
        self.metronomeValue.setCompleter(None)
        self.metronomeValue.setValidator(QIntValidator(0, 999, self.metronomeValue))
        self.metronomeValue.setCurrentIndex(metronomeValues.index(100))
        self.metronomeTempo = widgets.tempobutton.TempoButton()
        self.metronomeTempo.tempo.connect(self.setMetronomeValue)
        self.metronomeLabel.setBuddy(self.metronomeNote)
        self.metronomeRound = QCheckBox()

    
    def layoutMetronomeWidget(self, layout):
        grid = QGridLayout()
        grid.addWidget(self.metronomeLabel, 0, 0)

        box = QHBoxLayout(spacing=0)
        box.addWidget(self.metronomeNote)
        box.addWidget(self.metronomeEqualSign)
        box.addWidget(self.metronomeValue)
        box.addWidget(self.metronomeTempo)
        grid.addLayout(box, 0, 1)

        grid.addWidget(self.metronomeRound, 1, 1)
        layout.addLayout(grid)
        
    def tranlateMetronomeWidget(self):
        self.metronomeLabel.setText(_("Metronome mark:"))
        self.metronomeRound.setText(_("Round tap tempo value"))
        self.metronomeRound.setToolTip(_(
            "Round the entered tap tempo to a common value."
            ))
    
    def setMetronomeValue(self, bpm):
        """ Tap the tempo tap button """
        if  self.metronomeRound.isChecked():
            l = [abs(t - bpm) for t in metronomeValues]
            m = min(l)
            if m < 6:
                self.metronomeValue.setCurrentIndex(l.index(m))

        else:
            self.metronomeValue.setEditText(str(bpm))

    # Tempo indication
    def createTempoWidget(self):
        self.tempoLabel = QLabel()
        self.tempo = widgets.lineedit.LineEdit()
        completionmodel.complete(self.tempo, "scorewiz/completion/scoreproperties/tempo")
        self.tempo.completer().setCaseSensitivity(Qt.CaseInsensitive)
        self.tempoLabel.setBuddy(self.tempo)

    def layoutTempoWidget(self, layout):
        box = QHBoxLayout()
        box.addWidget(self.tempoLabel)
        box.addWidget(self.tempo)
        layout.addLayout(box)

    def translateTempoWidget(self):
        self.tempoLabel.setText(_("Tempo indication:"))

    def lyTempo(self, node, builder):
        """Returns an appropriate tempo indication."""
        text = self.tempo.text().strip()
        if builder.showMetronomeMark:
            dur = durations[self.metronomeNote.currentIndex()]
            val = self.metronomeValue.currentText() or '60'
        elif text:
            dur = None
            val = None
        else:
            return
        tempo = ly.dom.Tempo(dur, val, node)
        if text:
            ly.dom.QuotedString(text, tempo)

    def lyMidiTempo(self, node):
        """Sets the configured tempo in the tempoWholesPerMinute variable."""
        node['tempoWholesPerMinute'] = ly.dom.Scheme(self.schemeMidiTempo())
    
    def schemeMidiTempo(self):
        """Returns a string with the tempo like '(ly:make-moment 100 4)' from the settings."""
        base, mul = midiDurations[self.metronomeNote.currentIndex()]
        val = int(self.metronomeValue.currentText() or '60') * mul
        return "(ly:make-moment {0} {1})".format(val, base)
    
    def lySimpleMidiTempo(self, node):
        r"""Return a simple \tempo x=y node for the currently set tempo."""
        dur = durations[self.metronomeNote.currentIndex()]
        val = self.metronomeValue.currentText() or '60'
        return ly.dom.Tempo(dur, val, node)
Example #10
0
class NetworkArgs(QtHelper.EnhancedQDialog, Logger.ClassLogger):
    """
    Network arguments dialog
    """
    def __init__(self, dataArgs, parent=None):
        """
        Dialog to fill arguments for the network probe

        @param dataArgs: 
        @type dataArgs: 

        @param parent: 
        @type parent:
        """
        super(NetworkArgs, self).__init__(parent)
        self.dataArgs = dataArgs
        self.createDialog()
        self.createConnections()
        self.loadDefaultData()

    def createDialog (self):
        """
        Create qt dialog
        """
        mainLayout = QHBoxLayout()

        paramLayout = QHBoxLayout()
        paramLayout.addWidget( QLabel("Interface:") )
        self.intComboBox = QComboBox()
        self.intComboBox.setEditable(1)
        self.intComboBox.addItems( [ 'any', 'eth0', 'eth1', 'eth2', 'eth3', 'eth4', 'lo0' ] )
        paramLayout.addWidget( self.intComboBox )
        paramLayout.addWidget( QLabel("Filter:") )
        self.filterEdit = QLineEdit()
        paramLayout.addWidget( self.filterEdit )

        dataLayout = QVBoxLayout()
        self.labelHelp = QLabel("Network interface to dump:\nIf the interface name does not exist in the list\nplease to edit the combox list to change it.") 
        
        self.listBox = QTreeWidget(self)
        self.listBox.setIndentation(0)

        self.labels = [ self.tr("Interface"), self.tr("Filter") ]
        self.listBox.setHeaderLabels(self.labels)

        dataLayout.addWidget( self.labelHelp )
        dataLayout.addLayout( paramLayout )
        dataLayout.addWidget( self.listBox )

        buttonLayout = QVBoxLayout()
        self.addButton = QPushButton("Add", self)
        self.delButton = QPushButton("Remove", self)
        self.delButton.setEnabled(False)
        self.editButton = QPushButton("Edit", self)
        self.editButton.setEnabled(False)
        self.clearButton = QPushButton("Clear", self)
        self.okButton = QPushButton("Ok", self)
        self.cancelButton = QPushButton("Cancel", self)
        buttonLayout.addWidget( self.addButton )
        buttonLayout.addWidget( self.delButton )
        buttonLayout.addWidget( self.editButton )
        buttonLayout.addWidget( self.clearButton )
        buttonLayout.addWidget( self.okButton )
        buttonLayout.addWidget( self.cancelButton )

        mainLayout.addLayout( dataLayout ) 
        mainLayout.addLayout( buttonLayout ) 

        self.setLayout(mainLayout)

        self.setWindowTitle("Network Probe > Arguments")
        

    def createConnections (self):
        """
        Create qt connections
        """
        self.okButton.clicked.connect(self.accept)
        self.cancelButton.clicked.connect(self.reject)
        self.addButton.clicked.connect(self.addItem)
        self.delButton.clicked.connect(self.delItem)
        self.editButton.clicked.connect(self.editItem)
        self.clearButton.clicked.connect(self.clearList)
        self.listBox.itemClicked.connect(self.onItemSelected)

    def clearList(self):
        """
        Clear the list
        """
        self.listBox.clear()

    def onItemSelected(self, itm, row):
        """
        Called when an item is selected
        """
        self.delButton.setEnabled(True)
        self.editButton.setEnabled(True)

    def editItem(self):
        """
        Edit item
        """
        self.delButton.setEnabled(False)
        self.editButton.setEnabled(False)
        # retrieve value to put it in the line edit and then remove item 
        model = self.listBox.model()
        for selectedItem in self.listBox.selectedItems():
            qIndex = self.listBox.indexFromItem(selectedItem)
            eth = selectedItem.dataNet['interface']
            flt = selectedItem.dataNet['filter']
            self.filterEdit.setText( flt )
            self.intComboBox.setEditText( eth )
            model.removeRow(qIndex.row())

    def delItem(self):
        """
        Delete item
        """
        self.delButton.setEnabled(False)
        self.editButton.setEnabled(False)
        # remove item
        model = self.listBox.model()
        for selectedItem in self.listBox.selectedItems():
            qIndex = self.listBox.indexFromItem(selectedItem)
            model.removeRow(qIndex.row())

    def addItem(self):
        """
        Add item
        """
        eth = self.intComboBox.currentText()
        if eth != '':
            flt = self.filterEdit.text()
            tpl = {'interface': str(eth), 'filter': str(flt) }
            newParam = NetItem( data=tpl, parent=self.listBox)
            self.listBox.resizeColumnToContents(0)

    def loadDefaultData(self):
        """
        Load the default data
        """
        try:
            if len(self.dataArgs) ==0:
                return
            datObj = eval(str(self.dataArgs))
            if 'interfaces' in datObj:
                for eth in datObj['interfaces']:
                    newParam = NetItem( data=eth, parent=self.listBox)
        except Exception as e:
            self.error( "unable to load the default data: %s" % e )

    def getArgs(self):
        """
        Returns arguments
        Example list of files: {'interfaces': [ {'interface':'any', 'filter':''} ] }
        """
        listEth = []
        # iterate all items in a QListWidget
        root = self.listBox.invisibleRootItem()
        child_count = root.childCount()
        for i in xrange(child_count):
            itm = root.child(i)
            listEth.append( eval(str(itm.dataNet)) )
        ret = {'interfaces': listEth } 
        if len(listEth) == 0:
            ret = ''
        return str(ret)
Example #11
0
class ScoreProperties(object):
    """This is only the base class, it should be mixed in with a widget or a different way."""
    def createWidgets(self):
        """Creates all widgets."""
        self.createKeySignatureWidget()
        self.createTimeSignatureWidget()
        self.createPickupWidget()
        self.createMetronomeWidget()
        self.createTempoWidget()

    def layoutWidgets(self, layout):
        """Adds all widgets to a vertical layout."""
        self.layoutKeySignatureWidget(layout)
        self.layoutTimeSignatureWidget(layout)
        self.layoutPickupWidget(layout)
        self.layoutMetronomeWidget(layout)
        self.layoutTempoWidget(layout)

    def translateWidgets(self):
        self.translateKeySignatureWidget()
        self.translateTimeSignatureWidget()
        self.translatePickupWidget()
        self.tranlateMetronomeWidget()
        self.translateTempoWidget()

    def ly(self, node, builder):
        """Adds appropriate LilyPond command nodes to the parent node.
        
        Settings from the builder are used where that makes sense.
        All widgets must be present.
        
        """
        self.lyKeySignature(node, builder)
        self.lyTimeSignature(node, builder)
        self.lyPickup(node, builder)
        self.lyTempo(node, builder)

    def globalSection(self, builder):
        """Returns a sequential expression between { } containing the output of ly()."""
        seq = ly.dom.Seq()
        self.ly(seq, builder)
        return seq

    # Key signature
    def createKeySignatureWidget(self):
        self.keySignatureLabel = QLabel()
        self.keyNote = QComboBox()
        self.keyNote.setModel(
            listmodel.ListModel(keyNames['nederlands'], self.keyNote))
        self.keyMode = QComboBox()
        self.keyMode.setModel(
            listmodel.ListModel(modes,
                                self.keyMode,
                                display=listmodel.translate_index(1)))
        self.keySignatureLabel.setBuddy(self.keyNote)

    def translateKeySignatureWidget(self):
        self.keySignatureLabel.setText(_("Key signature:"))
        self.keyMode.model().update()

    def layoutKeySignatureWidget(self, layout):
        """Adds our widgets to a layout, assuming it is a QVBoxLayout."""
        box = QHBoxLayout()
        box.addWidget(self.keySignatureLabel)
        box.addWidget(self.keyNote)
        box.addWidget(self.keyMode)
        layout.addLayout(box)

    def setPitchLanguage(self, language='nederlands'):
        self.keyNote.model()._data = keyNames[language or 'nederlands']
        self.keyNote.model().update()

    def lyKeySignature(self, node, builder):
        """Adds the key signature to the ly.dom node parent."""
        note, alter = keys[self.keyNote.currentIndex()]
        alter = fractions.Fraction(alter, 2)
        mode = modes[self.keyMode.currentIndex()][0]
        ly.dom.KeySignature(note, alter, mode, node).after = 1

    # Time signature
    def createTimeSignatureWidget(self):
        self.timeSignatureLabel = QLabel()
        self.timeSignature = QComboBox(editable=True)
        icons = {
            '(4/4)': symbols.icon('time_c44'),
            '(2/2)': symbols.icon('time_c22'),
        }
        self.timeSignature.setModel(
            listmodel.ListModel(timeSignaturePresets,
                                self.timeSignature,
                                icon=icons.get))
        self.timeSignature.setCompleter(None)
        self.timeSignatureLabel.setBuddy(self.timeSignature)

    def translateTimeSignatureWidget(self):
        self.timeSignatureLabel.setText(_("Time signature:"))

    def layoutTimeSignatureWidget(self, layout):
        """Adds our widgets to a layout, assuming it is a QVBoxLayout."""
        box = QHBoxLayout()
        box.addWidget(self.timeSignatureLabel)
        box.addWidget(self.timeSignature)
        layout.addLayout(box)

    def lyTimeSignature(self, node, builder):
        """Adds the time signature to the ly.dom node parent."""
        sig = self.timeSignature.currentText().strip()
        if '+' in sig:
            pass  # TODO: implement support for \compoundMeter
        else:
            if sig == '(2/2)':
                ly.dom.TimeSignature(2, 2, node).after = 1
            elif sig == '(4/4)':
                ly.dom.TimeSignature(4, 4, node).after = 1
            else:
                match = re.search(r'(\d+).*?(\d+)', sig)
                if match:
                    if builder.lyVersion >= (2, 11, 44):
                        ly.dom.Line(r"\numericTimeSignature", node)
                    else:
                        ly.dom.Line(
                            r"\override Staff.TimeSignature #'style = #'()",
                            node)
                    num, beat = map(int, match.group(1, 2))
                    ly.dom.TimeSignature(num, beat, node).after = 1

    # Pickup bar
    def createPickupWidget(self):
        self.pickupLabel = QLabel()
        self.pickup = QComboBox()
        pickups = ['']
        pickups.extend(durations)
        self.pickup.setModel(
            listmodel.ListModel(pickups,
                                self.pickup,
                                display=lambda item: item or _("None"),
                                icon=lambda item: symbols.icon(
                                    'note_{0}'.format(item.replace('.', 'd')))
                                if item else None))
        self.pickup.view().setIconSize(QSize(22, 22))
        self.pickupLabel.setBuddy(self.pickup)

    def translatePickupWidget(self):
        self.pickupLabel.setText(_("Pickup measure:"))
        self.pickup.model().update()

    def layoutPickupWidget(self, layout):
        box = QHBoxLayout()
        box.addWidget(self.pickupLabel)
        box.addWidget(self.pickup)
        layout.addLayout(box)

    def lyPickup(self, node, builder):
        if self.pickup.currentIndex() > 0:
            dur, dots = partialDurations[self.pickup.currentIndex() - 1]
            ly.dom.Partial(dur, dots, parent=node)

    # Metronome value
    def createMetronomeWidget(self):
        self.metronomeLabel = QLabel()
        self.metronomeNote = QComboBox()
        self.metronomeNote.setModel(
            listmodel.ListModel(
                durations,
                display=None,
                icon=lambda item: symbols.icon('note_{0}'.format(
                    item.replace('.', 'd')))))
        self.metronomeNote.setCurrentIndex(durations.index('4'))
        self.metronomeNote.view().setIconSize(QSize(22, 22))
        self.metronomeEqualSign = QLabel('=')
        self.metronomeEqualSign.setFixedWidth(
            self.metronomeEqualSign.minimumSizeHint().width())
        self.metronomeValue = QComboBox(editable=True)
        self.metronomeValue.setModel(
            listmodel.ListModel(metronomeValues,
                                self.metronomeValue,
                                display=format))
        self.metronomeValue.setCompleter(None)
        self.metronomeValue.setValidator(
            QIntValidator(0, 999, self.metronomeValue))
        self.metronomeValue.setCurrentIndex(metronomeValues.index(100))
        self.metronomeTempo = widgets.tempobutton.TempoButton()
        self.metronomeTempo.tempo.connect(self.setMetronomeValue)
        self.metronomeLabel.setBuddy(self.metronomeNote)
        self.metronomeRound = QCheckBox()

    def layoutMetronomeWidget(self, layout):
        grid = QGridLayout()
        grid.addWidget(self.metronomeLabel, 0, 0)

        box = QHBoxLayout(spacing=0)
        box.addWidget(self.metronomeNote)
        box.addWidget(self.metronomeEqualSign)
        box.addWidget(self.metronomeValue)
        box.addWidget(self.metronomeTempo)
        grid.addLayout(box, 0, 1)

        grid.addWidget(self.metronomeRound, 1, 1)
        layout.addLayout(grid)

    def tranlateMetronomeWidget(self):
        self.metronomeLabel.setText(_("Metronome mark:"))
        self.metronomeRound.setText(_("Round tap tempo value"))
        self.metronomeRound.setToolTip(
            _("Round the entered tap tempo to a common value."))

    def setMetronomeValue(self, bpm):
        """ Tap the tempo tap button """
        if self.metronomeRound.isChecked():
            l = [abs(t - bpm) for t in metronomeValues]
            m = min(l)
            if m < 6:
                self.metronomeValue.setCurrentIndex(l.index(m))

        else:
            self.metronomeValue.setEditText(str(bpm))

    # Tempo indication
    def createTempoWidget(self):
        self.tempoLabel = QLabel()
        self.tempo = widgets.lineedit.LineEdit()
        completionmodel.complete(self.tempo,
                                 "scorewiz/completion/scoreproperties/tempo")
        self.tempo.completer().setCaseSensitivity(Qt.CaseInsensitive)
        self.tempoLabel.setBuddy(self.tempo)

    def layoutTempoWidget(self, layout):
        box = QHBoxLayout()
        box.addWidget(self.tempoLabel)
        box.addWidget(self.tempo)
        layout.addLayout(box)

    def translateTempoWidget(self):
        self.tempoLabel.setText(_("Tempo indication:"))

    def lyTempo(self, node, builder):
        """Returns an appropriate tempo indication."""
        text = self.tempo.text().strip()
        if builder.showMetronomeMark:
            dur = durations[self.metronomeNote.currentIndex()]
            val = self.metronomeValue.currentText() or '60'
        elif text:
            dur = None
            val = None
        else:
            return
        tempo = ly.dom.Tempo(dur, val, node)
        if text:
            ly.dom.QuotedString(text, tempo)

    def lyMidiTempo(self, node):
        """Sets the configured tempo in the tempoWholesPerMinute variable."""
        node['tempoWholesPerMinute'] = ly.dom.Scheme(self.schemeMidiTempo())

    def schemeMidiTempo(self):
        """Returns a string with the tempo like '(ly:make-moment 100 4)' from the settings."""
        base, mul = midiDurations[self.metronomeNote.currentIndex()]
        val = int(self.metronomeValue.currentText() or '60') * mul
        return "(ly:make-moment {0} {1})".format(val, base)

    def lySimpleMidiTempo(self, node):
        r"""Return a simple \tempo x=y node for the currently set tempo."""
        dur = durations[self.metronomeNote.currentIndex()]
        val = self.metronomeValue.currentText() or '60'
        return ly.dom.Tempo(dur, val, node)
Example #12
0
class Printing(preferences.Group):
    def __init__(self, page):
        super(Printing, self).__init__(page)

        layout = QGridLayout(spacing=1)
        self.setLayout(layout)

        self.messageLabel = QLabel(wordWrap=True)
        self.printCommandLabel = QLabel()
        self.printCommand = widgets.urlrequester.UrlRequester()
        self.printCommand.setFileMode(QFileDialog.ExistingFile)
        self.printCommand.changed.connect(page.changed)
        self.printDialogCheck = QCheckBox(toggled=page.changed)
        self.resolutionLabel = QLabel()
        self.resolution = QComboBox(editable=True,
                                    editTextChanged=page.changed)
        self.resolution.addItems("300 600 1200".split())
        self.resolution.lineEdit().setInputMask("9000")

        layout.addWidget(self.messageLabel, 0, 0, 1, 2)
        layout.addWidget(self.printCommandLabel, 1, 0)
        layout.addWidget(self.printCommand, 1, 1)
        layout.addWidget(self.printDialogCheck, 2, 0, 1, 2)
        layout.addWidget(self.resolutionLabel, 3, 0)
        layout.addWidget(self.resolution, 3, 1)

        app.translateUI(self)

    def translateUI(self):
        self.setTitle(_("Printing Music"))
        self.messageLabel.setText(
            _("Here you can enter a command to print a PDF or PostScript file. "
              "See the Help page for more information about printing music."))
        self.printCommandLabel.setText(_("Printing command:"))
        self.printCommand.setToolTip('<qt>' + _(
            "The printing command is used to print a PostScript or PDF file. "
            "On Linux you don't need this, but on Windows and Mac OS X you can "
            "provide a command to avoid that PDF documents are being printed "
            "using raster images, which is less optimal.\n"
            "<code>$pdf</code> gets replaced with the PDF filename, or alternatively, "
            "<code>$ps</code> is replaced with the PostScript filename. "
            "<code>$printer</code> is replaced with the printer's name to use."
        ))
        self.printDialogCheck.setText(_("Use Frescobaldi's print dialog"))
        self.printDialogCheck.setToolTip('<qt>' + _(
            "If enabled, Frescobaldi will show the print dialog and create a "
            "PDF or PostScript document containing only the selected pages "
            "to print. Otherwise, the command is called directly and is expected "
            "to show a print dialog itself."))
        self.resolutionLabel.setText(_("Resolution:"))
        self.resolution.setToolTip(
            _("Set the resolution if Frescobaldi prints using raster images."))

    def loadSettings(self):
        s = QSettings()
        s.beginGroup("helper_applications")
        self.printCommand.setPath(s.value("printcommand", "", type("")))
        self.printDialogCheck.setChecked(
            s.value("printcommand/dialog", False, bool))
        with qutil.signalsBlocked(self.resolution):
            self.resolution.setEditText(
                format(s.value("printcommand/dpi", 300, int)))

    def saveSettings(self):
        s = QSettings()
        s.beginGroup("helper_applications")
        s.setValue("printcommand", self.printCommand.path())
        s.setValue("printcommand/dialog", self.printDialogCheck.isChecked())
        s.setValue("printcommand/dpi", int(self.resolution.currentText()))
Example #13
0
class MidiPorts(preferences.Group):
    def __init__(self, page):
        super(MidiPorts, self).__init__(page)

        self._portsMessage = QLabel(wordWrap=True)
        self._playerLabel = QLabel()
        self._playerPort = QComboBox(editable=True, editTextChanged=self.changed, insertPolicy=QComboBox.NoInsert)
        self._inputLabel = QLabel()
        self._inputPort = QComboBox(editable=True, editTextChanged=self.changed, insertPolicy=QComboBox.NoInsert)

        self._reloadMidi = QPushButton(icon=icons.get("view-refresh"))
        self._reloadMidi.clicked.connect(self.refreshMidiPorts)

        grid = QGridLayout()
        self.setLayout(grid)
        grid.addWidget(self._portsMessage, 0, 0, 1, 3)
        grid.addWidget(self._playerLabel, 1, 0)
        grid.addWidget(self._playerPort, 1, 1, 1, 2)
        grid.addWidget(self._inputLabel, 2, 0)
        grid.addWidget(self._inputPort, 2, 1, 1, 2)
        grid.addWidget(self._reloadMidi, 3, 2)

        app.translateUI(self)
        self.loadMidiPorts()

    def translateUI(self):
        self.setTitle(_("MIDI Ports"))
        self._portsMessage.setText(
            _(
                "Note: There are no MIDI output ports available on your system. "
                "To use MIDI, please check if PortMIDI is installed on your system "
                "and that a MIDI synthesizer is available or connected."
            )
        )
        self._playerLabel.setText(_("Player output:"))
        self._playerPort.setToolTip(_("The MIDI port to play music to. " 'See "What\'s This" for more information.'))
        self._playerPort.setWhatsThis(
            _(
                "<p>"
                "This dropdown menu lists the available MIDI output ports on your system. "
                "You can select one, or just type part of a name. "
                "In that case, the first available port name that starts with the "
                "specified characters is used."
                "</p>\n<p>"
                "Click the button to refresh the list, e.g. when you connect a "
                "MIDI device or start a software synthesizer."
                "</p>"
            )
        )
        self._inputLabel.setText(_("Input port:"))
        self._inputPort.setToolTip(
            _("The MIDI port to get input from to write notes  " 'See "What\'s This" for more information.')
        )
        self._inputPort.setWhatsThis(
            _(
                "<p>"
                "This dropdown menu lists the available MIDI input ports on your system. "
                "You can select one, or just type part of a name. "
                "In that case, the first available port name that starts with the "
                "specified characters is used."
                "</p>\n<p>"
                "Click the button to refresh the list, e.g. when you connect a "
                "MIDI device or start a software synthesizer."
                "</p>"
            )
        )
        self._reloadMidi.setText(_("Refresh MIDI ports"))

    def loadMidiPorts(self):
        output_ports = midihub.output_ports()
        self._playerPort.setModel(listmodel.ListModel(output_ports))
        input_ports = midihub.input_ports()
        self._inputPort.setModel(listmodel.ListModel(input_ports))
        self._portsMessage.setVisible((not output_ports) and (not input_ports))

    def refreshMidiPorts(self):
        midihub.refresh_ports()
        with qutil.signalsBlocked(self):
            self.loadMidiPorts()
            self.loadSettings()

    def loadSettings(self):
        output_port = midihub.default_output()
        input_port = midihub.default_input()
        s = QSettings()
        s.beginGroup("midi")
        self._playerPort.setEditText(s.value("player/output_port", output_port, type("")))
        self._inputPort.setEditText(s.value("midi/input_port", input_port, type("")))

    def saveSettings(self):
        s = QSettings()
        s.beginGroup("midi")
        s.setValue("player/output_port", self._playerPort.currentText())
        s.setValue("midi/input_port", self._inputPort.currentText())
Example #14
0
class MidiPorts(preferences.Group):
    def __init__(self, page):
        super(MidiPorts, self).__init__(page)

        self._portsMessage = QLabel(wordWrap=True)
        self._playerLabel = QLabel()
        self._playerPort = QComboBox(editable=True,
                                     editTextChanged=self.changed,
                                     insertPolicy=QComboBox.NoInsert)
        self._inputLabel = QLabel()
        self._inputPort = QComboBox(editable=True,
                                    editTextChanged=self.changed,
                                    insertPolicy=QComboBox.NoInsert)

        self._reloadMidi = QPushButton(icon=icons.get('view-refresh'))
        self._reloadMidi.clicked.connect(self.refreshMidiPorts)

        grid = QGridLayout()
        self.setLayout(grid)
        grid.addWidget(self._portsMessage, 0, 0, 1, 3)
        grid.addWidget(self._playerLabel, 1, 0)
        grid.addWidget(self._playerPort, 1, 1, 1, 2)
        grid.addWidget(self._inputLabel, 2, 0)
        grid.addWidget(self._inputPort, 2, 1, 1, 2)
        grid.addWidget(self._reloadMidi, 3, 2)

        app.translateUI(self)
        self.loadMidiPorts()

    def translateUI(self):
        self.setTitle(_("MIDI Ports"))
        self._portsMessage.setText(
            _("Note: There are no MIDI output ports available on your system. "
              "To use MIDI, please check if PortMIDI is installed on your system "
              "and that a MIDI synthesizer is available or connected."))
        self._playerLabel.setText(_("Player output:"))
        self._playerPort.setToolTip(
            _("The MIDI port to play music to. "
              "See \"What's This\" for more information."))
        self._playerPort.setWhatsThis(
            _("<p>"
              "This dropdown menu lists the available MIDI output ports on your system. "
              "You can select one, or just type part of a name. "
              "In that case, the first available port name that starts with the "
              "specified characters is used."
              "</p>\n<p>"
              "Click the button to refresh the list, e.g. when you connect a "
              "MIDI device or start a software synthesizer."
              "</p>"))
        self._inputLabel.setText(_("Input port:"))
        self._inputPort.setToolTip(
            _("The MIDI port to get input from to write notes  "
              "See \"What's This\" for more information."))
        self._inputPort.setWhatsThis(
            _("<p>"
              "This dropdown menu lists the available MIDI input ports on your system. "
              "You can select one, or just type part of a name. "
              "In that case, the first available port name that starts with the "
              "specified characters is used."
              "</p>\n<p>"
              "Click the button to refresh the list, e.g. when you connect a "
              "MIDI device or start a software synthesizer."
              "</p>"))
        self._reloadMidi.setText(_("Refresh MIDI ports"))

    def loadMidiPorts(self):
        output_ports = midihub.output_ports()
        self._playerPort.setModel(listmodel.ListModel(output_ports))
        input_ports = midihub.input_ports()
        self._inputPort.setModel(listmodel.ListModel(input_ports))
        self._portsMessage.setVisible((not output_ports) and (not input_ports))

    def refreshMidiPorts(self):
        midihub.refresh_ports()
        with qutil.signalsBlocked(self):
            self.loadMidiPorts()
            self.loadSettings()

    def loadSettings(self):
        output_port = midihub.default_output()
        input_port = midihub.default_input()
        s = QSettings()
        s.beginGroup("midi")
        self._playerPort.setEditText(
            s.value("player/output_port", output_port, type("")))
        self._inputPort.setEditText(
            s.value("midi/input_port", input_port, type("")))

    def saveSettings(self):
        s = QSettings()
        s.beginGroup("midi")
        s.setValue("player/output_port", self._playerPort.currentText())
        s.setValue("midi/input_port", self._inputPort.currentText())
Example #15
0
class FindInFilesDialog( QDialog, object ):
    """ find in files dialog implementation """

    inProject = 0
    inDirectory = 1
    inOpenFiles = 2

    def __init__( self, where, what = "",
                  dirPath = "", filters = [],
                  parent = None ):

        QDialog.__init__( self, parent )

        mainWindow = GlobalData().mainWindow
        self.editorsManager = mainWindow.editorsManagerWidget.editorsManager

        self.__cancelRequest = False
        self.__inProgress = False
        self.searchRegexp = None
        self.searchResults = []

        # Avoid pylint complains
        self.findCombo = None
        self.caseCheckBox = None
        self.wordCheckBox = None
        self.regexpCheckBox = None
        self.projectRButton = None
        self.openFilesRButton = None
        self.dirRButton = None
        self.dirEditCombo = None
        self.dirSelectButton = None
        self.filterCombo = None
        self.fileLabel = None
        self.progressBar = None
        self.findButton = None

        self.__createLayout()
        self.setWindowTitle( "Find in files" )

        # Restore the combo box values
        project = GlobalData().project
        if project.fileName != "":
            self.findFilesWhat = project.findFilesWhat
            self.findFilesDirs = project.findFilesDirs
            self.findFilesMasks = project.findFilesMasks
        else:
            settings = Settings()
            self.findFilesWhat = settings.findFilesWhat
            self.findFilesDirs = settings.findFilesDirs
            self.findFilesMasks = settings.findFilesMasks
        self.findCombo.addItems( self.findFilesWhat )
        self.findCombo.setEditText( "" )
        self.dirEditCombo.addItems( self.findFilesDirs )
        self.dirEditCombo.setEditText( "" )
        self.filterCombo.addItems( self.findFilesMasks )
        self.filterCombo.setEditText( "" )

        if where == self.inProject:
            self.setSearchInProject( what, filters )
        elif where == self.inDirectory:
            self.setSearchInDirectory( what, dirPath, filters )
        else:
            self.setSearchInOpenFiles( what, filters )

        return

    def __createLayout( self ):
        """ Creates the dialog layout """

        self.resize( 600, 300 )
        self.setSizeGripEnabled( True )

        verticalLayout = QVBoxLayout( self )
        gridLayout = QGridLayout()

        # Combo box for the text to search
        findLabel = QLabel( self )
        findLabel.setText( "Find text:" )
        self.findCombo = QComboBox( self )
        self.__tuneCombo( self.findCombo )
        self.findCombo.lineEdit().setToolTip( "Regular expression to search for" )
        self.findCombo.editTextChanged.connect( self.__someTextChanged )

        gridLayout.addWidget( findLabel, 0, 0, 1, 1 )
        gridLayout.addWidget( self.findCombo, 0, 1, 1, 1 )
        verticalLayout.addLayout( gridLayout )

        # Check boxes
        horizontalCBLayout = QHBoxLayout()
        self.caseCheckBox = QCheckBox( self )
        self.caseCheckBox.setText( "Match &case" )
        horizontalCBLayout.addWidget( self.caseCheckBox )
        self.wordCheckBox = QCheckBox( self )
        self.wordCheckBox.setText( "Match whole &word" )
        horizontalCBLayout.addWidget( self.wordCheckBox )
        self.regexpCheckBox = QCheckBox( self )
        self.regexpCheckBox.setText( "Regular &expression" )
        horizontalCBLayout.addWidget( self.regexpCheckBox )

        verticalLayout.addLayout( horizontalCBLayout )

        # Files groupbox
        filesGroupbox = QGroupBox( self )
        filesGroupbox.setTitle( "Find in" )
        sizePolicy = QSizePolicy( QSizePolicy.Expanding, QSizePolicy.Preferred )
        sizePolicy.setHorizontalStretch( 0 )
        sizePolicy.setVerticalStretch( 0 )
        sizePolicy.setHeightForWidth(
                        filesGroupbox.sizePolicy().hasHeightForWidth() )
        filesGroupbox.setSizePolicy( sizePolicy )

        gridLayoutFG = QGridLayout( filesGroupbox )
        self.projectRButton = QRadioButton( filesGroupbox )
        self.projectRButton.setText( "&Project" )
        gridLayoutFG.addWidget( self.projectRButton, 0, 0 )
        self.projectRButton.clicked.connect( self.__projectClicked )

        self.openFilesRButton = QRadioButton( filesGroupbox )
        self.openFilesRButton.setText( "&Opened files only" )
        gridLayoutFG.addWidget( self.openFilesRButton, 1, 0 )
        self.openFilesRButton.clicked.connect( self.__openFilesOnlyClicked )

        self.dirRButton = QRadioButton( filesGroupbox )
        self.dirRButton.setText( "&Directory tree" )
        gridLayoutFG.addWidget( self.dirRButton, 2, 0 )
        self.dirRButton.clicked.connect( self.__dirClicked )

        self.dirEditCombo = QComboBox( filesGroupbox )
        self.__tuneCombo( self.dirEditCombo )
        self.dirEditCombo.lineEdit().setToolTip( "Directory to search in" )
        gridLayoutFG.addWidget( self.dirEditCombo, 2, 1 )
        self.dirEditCombo.editTextChanged.connect( self.__someTextChanged )

        self.dirSelectButton = QPushButton( filesGroupbox )
        self.dirSelectButton.setText( "..." )
        gridLayoutFG.addWidget( self.dirSelectButton, 2, 2 )
        self.dirSelectButton.clicked.connect( self.__selectDirClicked )

        filterLabel = QLabel( filesGroupbox )
        filterLabel.setText( "Files filter:" )
        gridLayoutFG.addWidget( filterLabel, 3, 0 )
        self.filterCombo = QComboBox( filesGroupbox )
        self.__tuneCombo( self.filterCombo )
        self.filterCombo.lineEdit().setToolTip( "File names regular expression" )
        gridLayoutFG.addWidget( self.filterCombo, 3, 1 )
        self.filterCombo.editTextChanged.connect( self.__someTextChanged )

        verticalLayout.addWidget( filesGroupbox )

        # File label
        self.fileLabel = FitPathLabel( self )
        self.fileLabel.setSizePolicy( QSizePolicy.Ignored, QSizePolicy.Fixed )
        verticalLayout.addWidget( self.fileLabel )

        # Progress bar
        self.progressBar = QProgressBar( self )
        self.progressBar.setValue( 0 )
        self.progressBar.setOrientation( Qt.Horizontal )
        verticalLayout.addWidget( self.progressBar )

        # Buttons at the bottom
        buttonBox = QDialogButtonBox( self )
        buttonBox.setOrientation( Qt.Horizontal )
        buttonBox.setStandardButtons( QDialogButtonBox.Cancel )
        self.findButton = buttonBox.addButton( "Find",
                                               QDialogButtonBox.AcceptRole )
        self.findButton.setDefault( True )
        self.findButton.clicked.connect( self.__process )
        verticalLayout.addWidget( buttonBox )

        buttonBox.rejected.connect( self.__onClose )
        return

    @staticmethod
    def __tuneCombo( comboBox ):
        " Sets the common settings for a combo box "
        sizePolicy = QSizePolicy( QSizePolicy.Expanding, QSizePolicy.Fixed )
        sizePolicy.setHorizontalStretch( 0 )
        sizePolicy.setVerticalStretch( 0 )
        sizePolicy.setHeightForWidth( \
                            comboBox.sizePolicy().hasHeightForWidth() )
        comboBox.setSizePolicy( sizePolicy )
        comboBox.setEditable( True )
        comboBox.setInsertPolicy( QComboBox.InsertAtTop )
        comboBox.setAutoCompletion( False )
        comboBox.setDuplicatesEnabled( False )
        return

    def __onClose( self ):
        " Triggered when the close button is clicked "

        self.__cancelRequest = True
        if not self.__inProgress:
            self.close()
        return

    def setSearchInProject( self, what = "", filters = [] ):
        " Set search ready for the whole project "

        if GlobalData().project.fileName == "":
            # No project loaded, fallback to opened files
            self.setSearchInOpenFiles( what, filters )
            return

        # Select the project radio button
        self.projectRButton.setEnabled( True )
        self.projectRButton.setChecked( True )
        self.dirEditCombo.setEnabled( False )
        self.dirSelectButton.setEnabled( False )

        openedFiles = self.editorsManager.getTextEditors()
        self.openFilesRButton.setEnabled( len( openedFiles ) != 0 )

        self.setFilters( filters )

        self.findCombo.setEditText( what )
        self.findCombo.lineEdit().selectAll()
        self.findCombo.setFocus()

        # Check searchability
        self.__testSearchability()
        return


    def setSearchInOpenFiles( self, what = "", filters = [] ):
        " Sets search ready for the opened files "

        openedFiles = self.editorsManager.getTextEditors()
        if len( openedFiles ) == 0:
            # No opened files, fallback to search in dir
            self.setSearchInDirectory( what, "", filters )
            return

        # Select the radio buttons
        self.projectRButton.setEnabled( GlobalData().project.fileName != "" )
        self.openFilesRButton.setEnabled( True )
        self.openFilesRButton.setChecked( True )
        self.dirEditCombo.setEnabled( False )
        self.dirSelectButton.setEnabled( False )

        self.setFilters( filters )

        self.findCombo.setEditText( what )
        self.findCombo.lineEdit().selectAll()
        self.findCombo.setFocus()

        # Check searchability
        self.__testSearchability()
        return


    def setSearchInDirectory( self, what = "", dirPath = "", filters = [] ):
        " Sets search ready for the given directory "

        # Select radio buttons
        self.projectRButton.setEnabled( GlobalData().project.fileName != "" )
        openedFiles = self.editorsManager.getTextEditors()
        self.openFilesRButton.setEnabled( len( openedFiles ) != 0 )
        self.dirRButton.setEnabled( True )
        self.dirRButton.setChecked( True )
        self.dirEditCombo.setEnabled( True )
        self.dirSelectButton.setEnabled( True )
        self.dirEditCombo.setEditText( dirPath )

        self.setFilters( filters )

        self.findCombo.setEditText( what )
        self.findCombo.lineEdit().selectAll()
        self.findCombo.setFocus()

        # Check searchability
        self.__testSearchability()
        return


    def setFilters( self, filters ):
        " Sets up the filters "

        # Set filters if provided
        if filters:
            self.filterCombo.setEditText( ";".join( filters ) )
        else:
            self.filterCombo.setEditText( "" )
        return

    def __testSearchability( self ):
        " Tests the searchability and sets the Find button status "

        startTime = time.time()
        if self.findCombo.currentText().strip() == "":
            self.findButton.setEnabled( False )
            self.findButton.setToolTip( "No text to search" )
            return

        if self.dirRButton.isChecked():
            dirname = self.dirEditCombo.currentText().strip()
            if dirname == "":
                self.findButton.setEnabled( False )
                self.findButton.setToolTip( "No directory path" )
                return
            if not os.path.isdir( dirname ):
                self.findButton.setEnabled( False )
                self.findButton.setToolTip( "Path is not a directory" )
                return

        # Now we need to match file names if there is a filter
        filtersText = self.filterCombo.currentText().strip()
        if filtersText == "":
            self.findButton.setEnabled( True )
            self.findButton.setToolTip( "Find in files" )
            return

        # Need to check the files match
        try:
            filterRe = re.compile( filtersText, re.IGNORECASE )
        except:
            self.findButton.setEnabled( False )
            self.findButton.setToolTip( "Incorrect files " \
                                        "filter regular expression" )
            return

        matched = False
        tooLong = False
        if self.projectRButton.isChecked():
            # Whole project
            for fname in GlobalData().project.filesList:
                if fname.endswith( sep ):
                    continue
                matched = filterRe.match( fname )
                if matched:
                    break
                # Check the time, it might took too long
                if time.time() - startTime > 0.1:
                    tooLong = True
                    break

        elif self.openFilesRButton.isChecked():
            # Opened files
            openedFiles = self.editorsManager.getTextEditors()
            for record in openedFiles:
                matched = filterRe.match( record[ 1 ] )
                if matched:
                    break
                # Check the time, it might took too long
                if time.time() - startTime > 0.1:
                    tooLong = True
                    break

        else:
            # Search in the dir
            if not dirname.endswith( sep ):
                dirname += sep
            matched, tooLong = self.__matchInDir( dirname, filterRe, startTime )

        if matched:
            self.findButton.setEnabled( True )
            self.findButton.setToolTip( "Find in files" )
        else:
            if tooLong:
                self.findButton.setEnabled( True )
                self.findButton.setToolTip( "Find in files" )
            else:
                self.findButton.setEnabled( False )
                self.findButton.setToolTip( "No files matched to search in" )
        return

    @staticmethod
    def __matchInDir( path, filterRe, startTime ):
        " Provides the 'match' and 'too long' statuses "
        matched = False
        tooLong = False
        for item in os.listdir( path ):
            if time.time() - startTime > 0.1:
                tooLong = True
                return matched, tooLong
            if os.path.isdir( path + item ):
                dname = path + item + sep
                matched, tooLong = FindInFilesDialog.__matchInDir( dname,
                                                                   filterRe,
                                                                   startTime )
                if matched or tooLong:
                    return matched, tooLong
                continue
            if filterRe.match( path + item ):
                matched = True
                return matched, tooLong
        return matched, tooLong

    def __projectClicked( self ):
        " project radio button clicked "
        self.dirEditCombo.setEnabled( False )
        self.dirSelectButton.setEnabled( False )
        self.__testSearchability()
        return

    def __openFilesOnlyClicked( self ):
        " open files only radio button clicked "
        self.dirEditCombo.setEnabled( False )
        self.dirSelectButton.setEnabled( False )
        self.__testSearchability()
        return

    def __dirClicked( self ):
        " dir radio button clicked "
        self.dirEditCombo.setEnabled( True )
        self.dirSelectButton.setEnabled( True )
        self.dirEditCombo.setFocus()
        self.__testSearchability()
        return

    def __someTextChanged( self, text ):
        " Text to search, filter or dir name has been changed "
        self.__testSearchability()
        return

    def __selectDirClicked( self ):
        " The user selects a directory "
        dirName = QFileDialog.getExistingDirectory( self,
                    "Select directory to search in",
                    self.dirEditCombo.currentText(),
                    QFileDialog.Options( QFileDialog.ShowDirsOnly ) )

        if dirName:
            self.dirEditCombo.setEditText( os.path.normpath( dirName ) )
        self.__testSearchability()
        return


    def __projectFiles( self, filterRe ):
        " Project files list respecting the mask "
        mainWindow = GlobalData().mainWindow
        files = []
        for fname in GlobalData().project.filesList:
            if fname.endswith( sep ):
                continue
            if filterRe is None or filterRe.match( fname ):
                widget = mainWindow.getWidgetForFileName( fname )
                if widget is None:
                    # Do not check for broken symlinks
                    if isFileSearchable( fname, False ):
                        files.append( ItemToSearchIn( fname, "" ) )
                else:
                    if widget.getType() in \
                                [ MainWindowTabWidgetBase.PlainTextEditor ]:
                        files.append( ItemToSearchIn( fname,
                                                      widget.getUUID() ) )
            QApplication.processEvents()
            if self.__cancelRequest:
                raise Exception( "Cancel request" )
        return files

    def __openedFiles( self, filterRe ):
        " Currently opened editor buffers "

        files = []
        openedFiles = self.editorsManager.getTextEditors()
        for record in openedFiles:
            uuid = record[ 0 ]
            fname = record[ 1 ]
            if filterRe is None or filterRe.match( fname ):
                files.append( ItemToSearchIn( fname, uuid ) )
            QApplication.processEvents()
            if self.__cancelRequest:
                raise Exception( "Cancel request" )
        return files

    def __dirFiles( self, path, filterRe, files ):
        " Files recursively for the dir "
        for item in os.listdir( path ):
            QApplication.processEvents()
            if self.__cancelRequest:
                raise Exception( "Cancel request" )
            if os.path.isdir( path + item ):
                if item in [ ".svn", ".cvs" ]:
                    # It does not make sense to search in revision control dirs
                    continue
                anotherDir, isLoop = resolveLink( path + item )
                if not isLoop:
                    self.__dirFiles( anotherDir + sep,
                                     filterRe, files )
                continue
            if not os.path.isfile( path + item ):
                continue
            realItem, isLoop = resolveLink( path + item )
            if isLoop:
                continue
            if filterRe is None or filterRe.match( realItem ):
                found = False
                for itm in files:
                    if itm.fileName == realItem:
                        found = True
                        break
                if not found:
                    mainWindow = GlobalData().mainWindow
                    widget = mainWindow.getWidgetForFileName( realItem )
                    if widget is None:
                        if isFileSearchable( realItem ):
                            files.append( ItemToSearchIn( realItem, "" ) )
                    else:
                        if widget.getType() in \
                                    [ MainWindowTabWidgetBase.PlainTextEditor ]:
                            files.append( ItemToSearchIn( realItem,
                                                          widget.getUUID() ) )
        return


    def __buildFilesList( self ):
        " Builds the list of files to search in "
        filtersText = self.filterCombo.currentText().strip()
        if filtersText != "":
            filterRe = re.compile( filtersText, re.IGNORECASE )
        else:
            filterRe = None

        if self.projectRButton.isChecked():
            return self.__projectFiles( filterRe )

        if self.openFilesRButton.isChecked():
            return self.__openedFiles( filterRe )

        dirname = os.path.realpath( self.dirEditCombo.currentText().strip() )
        files = []
        self.__dirFiles( dirname + sep, filterRe, files )
        return files


    def __process( self ):
        " Search process "

        # Add entries to the combo box if required
        regexpText = self.findCombo.currentText()
        if regexpText in self.findFilesWhat:
            self.findFilesWhat.remove( regexpText )
        self.findFilesWhat.insert( 0, regexpText )
        if len( self.findFilesWhat ) > 32:
            self.findFilesWhat = self.findFilesWhat[ : 32 ]
        self.findCombo.clear()
        self.findCombo.addItems( self.findFilesWhat )

        filtersText = self.filterCombo.currentText().strip()
        if filtersText in self.findFilesMasks:
            self.findFilesMasks.remove( filtersText )
        self.findFilesMasks.insert( 0, filtersText )
        if len( self.findFilesMasks ) > 32:
            self.findFilesMasks = self.findFilesMasks[ : 32 ]
        self.filterCombo.clear()
        self.filterCombo.addItems( self.findFilesMasks )

        if self.dirRButton.isChecked():
            dirText = self.dirEditCombo.currentText().strip()
            if dirText in self.findFilesDirs:
                self.findFilesDirs.remove( dirText )
            self.findFilesDirs.insert( 0, dirText )
            if len( self.findFilesDirs ) > 32:
                self.findFilesDirs = self.findFilesDirs[ : 32 ]
            self.dirEditCombo.clear()
            self.dirEditCombo.addItems( self.findFilesDirs )

        # Save the combo values for further usage
        if GlobalData().project.fileName != "":
            GlobalData().project.setFindInFilesHistory( self.findFilesWhat,
                                                        self.findFilesDirs,
                                                        self.findFilesMasks )
        else:
            Settings().findFilesWhat = self.findFilesWhat
            Settings().findFilesDirs = self.findFilesDirs
            Settings().findFilesMasks = self.findFilesMasks


        self.__inProgress = True
        numberOfMatches = 0
        self.searchResults = []
        self.searchRegexp = None

        # Form the regexp to search
        if not self.regexpCheckBox.isChecked():
            regexpText = re.escape( regexpText )
        if self.wordCheckBox.isChecked():
            regexpText = "\\b%s\\b" % regexpText
        flags = re.UNICODE | re.LOCALE
        if not self.caseCheckBox.isChecked():
            flags |= re.IGNORECASE

        try:
            self.searchRegexp = re.compile( regexpText, flags )
        except:
            logging.error( "Invalid search expression" )
            self.close()
            return


        QApplication.setOverrideCursor( QCursor( Qt.WaitCursor ) )
        self.fileLabel.setPath( 'Building list of files to search in...' )
        QApplication.processEvents()
        try:
            files = self.__buildFilesList()
        except Exception, exc:
            if "Cancel request" in str( exc ):
                QApplication.restoreOverrideCursor()
                self.close()
                return
            else:
                QApplication.restoreOverrideCursor()
                logging.error( str( exc ) )
                self.close()
                return
        QApplication.restoreOverrideCursor()
        QApplication.processEvents()

        if len( files ) == 0:
            self.fileLabel.setPath( 'No files to search in' )
            return

        self.progressBar.setRange( 0, len( files ) )

        index = 1
        for item in files:

            if self.__cancelRequest:
                self.__inProgress = False
                self.close()
                return

            self.fileLabel.setPath( 'Matches: ' + str( numberOfMatches ) + \
                                    ' Processing: ' + item.fileName )

            item.search( self.searchRegexp )
            found = len( item.matches )
            if found > 0:
                numberOfMatches += found
                self.searchResults.append( item )

            self.progressBar.setValue( index )
            index += 1

            QApplication.processEvents()

        if numberOfMatches == 0:
            if len( files ) == 1:
                self.fileLabel.setPath( "No matches in 1 file." )
            else:
                self.fileLabel.setPath( "No matches in " + \
                                        str( len( files ) ) + " files." )
            self.__inProgress = False
        else:
            self.close()
        return
Example #16
0
class Dialog(QDialog):
    def __init__(self, parent=None):
        super(Dialog, self).__init__(parent)
        self._filename = None
        self._page = None
        self._rect = None
        self.imageViewer = widgets.imageviewer.ImageViewer()
        self.dpiLabel = QLabel()
        self.dpiCombo = QComboBox(insertPolicy=QComboBox.NoInsert,
                                  editable=True)
        self.dpiCombo.lineEdit().setCompleter(None)
        self.dpiCombo.setValidator(
            QDoubleValidator(10.0, 1200.0, 4, self.dpiCombo))
        self.dpiCombo.addItems(
            [format(i) for i in (72, 100, 200, 300, 600, 1200)])

        self.colorButton = widgets.colorbutton.ColorButton()
        self.colorButton.setColor(QColor(Qt.white))
        self.crop = QCheckBox()
        self.antialias = QCheckBox(checked=True)
        self.dragfile = QPushButton(icons.get("image-x-generic"), None, None)
        self.fileDragger = FileDragger(self.dragfile)
        self.buttons = QDialogButtonBox(QDialogButtonBox.Close)
        self.copyButton = self.buttons.addButton('',
                                                 QDialogButtonBox.ApplyRole)
        self.copyButton.setIcon(icons.get('edit-copy'))
        self.saveButton = self.buttons.addButton('',
                                                 QDialogButtonBox.ApplyRole)
        self.saveButton.setIcon(icons.get('document-save'))

        layout = QVBoxLayout()
        self.setLayout(layout)

        layout.addWidget(self.imageViewer)

        controls = QHBoxLayout()
        layout.addLayout(controls)
        controls.addWidget(self.dpiLabel)
        controls.addWidget(self.dpiCombo)
        controls.addWidget(self.colorButton)
        controls.addWidget(self.crop)
        controls.addWidget(self.antialias)
        controls.addStretch()
        controls.addWidget(self.dragfile)
        layout.addWidget(widgets.Separator())
        layout.addWidget(self.buttons)

        app.translateUI(self)
        self.readSettings()
        self.finished.connect(self.writeSettings)
        self.dpiCombo.editTextChanged.connect(self.drawImage)
        self.colorButton.colorChanged.connect(self.drawImage)
        self.antialias.toggled.connect(self.drawImage)
        self.crop.toggled.connect(self.cropImage)
        self.buttons.rejected.connect(self.reject)
        self.copyButton.clicked.connect(self.copyToClipboard)
        self.saveButton.clicked.connect(self.saveAs)
        qutil.saveDialogSize(self, "copy_image/dialog/size", QSize(480, 320))

    def translateUI(self):
        self.setCaption()
        self.dpiLabel.setText(_("DPI:"))
        self.colorButton.setToolTip(_("Paper Color"))
        self.crop.setText(_("Auto-crop"))
        self.antialias.setText(_("Antialias"))
        self.dragfile.setText(_("Drag"))
        self.dragfile.setToolTip(_("Drag the image as a PNG file."))
        self.copyButton.setText(_("&Copy to Clipboard"))
        self.saveButton.setText(_("&Save As..."))
        self.imageViewer.setWhatsThis(
            _(
                #xgettext:no-python-format
                "<p>\n"
                "Clicking toggles the display between 100% size and window size. "
                "Drag to copy the image to another application. "
                "Drag with Ctrl (or {command}) to scroll a large image.\n"
                "</p>\n"
                "<p>\n"
                "You can also drag the small picture icon in the bottom right, "
                "which drags the actual file on disk, e.g. to an e-mail message.\n"
                "</p>").format(command="\u2318"))

    def readSettings(self):
        s = QSettings()
        s.beginGroup('copy_image')
        self.dpiCombo.setEditText(s.value("dpi", "100", type("")))
        self.colorButton.setColor(
            s.value("papercolor", QColor(Qt.white), QColor))
        self.crop.setChecked(s.value("autocrop", False, bool))
        self.antialias.setChecked(s.value("antialias", True, bool))

    def writeSettings(self):
        s = QSettings()
        s.beginGroup('copy_image')
        s.setValue("dpi", self.dpiCombo.currentText())
        s.setValue("papercolor", self.colorButton.color())
        s.setValue("autocrop", self.crop.isChecked())
        s.setValue("antialias", self.antialias.isChecked())

    def setCaption(self):
        if self._filename:
            filename = os.path.basename(self._filename)
        else:
            filename = _("<unknown>")
        title = _("Image from {filename}").format(filename=filename)
        self.setWindowTitle(app.caption(title))

    def setPage(self, page, rect):
        self._page = page
        self._rect = rect
        self._filename = documents.filename(page.document())
        self.fileDragger.basename = os.path.splitext(
            os.path.basename(self._filename))[0]
        self.setCaption()
        self.drawImage()

    def drawImage(self):
        dpi = float(self.dpiCombo.currentText() or '100')
        dpi = max(dpi, self.dpiCombo.validator().bottom())
        dpi = min(dpi, self.dpiCombo.validator().top())
        options = qpopplerview.RenderOptions()
        options.setPaperColor(self.colorButton.color())
        if self.antialias.isChecked():
            if popplerqt4:
                options.setRenderHint(
                    popplerqt4.Poppler.Document.Antialiasing
                    | popplerqt4.Poppler.Document.TextAntialiasing)
        else:
            options.setRenderHint(0)
        self._image = self._page.image(self._rect, dpi, dpi, options)
        self.cropImage()

    def cropImage(self):
        image = self._image
        if self.crop.isChecked():
            image = image.copy(autoCropRect(image))
        self.imageViewer.setImage(image)
        self.fileDragger.setImage(image)

    def copyToClipboard(self):
        QApplication.clipboard().setImage(self.imageViewer.image())

    def saveAs(self):
        if self._filename and not self.imageViewer.image().isNull():
            filename = os.path.splitext(self._filename)[0] + ".png"
        else:
            filename = 'image.png'
        filename = QFileDialog.getSaveFileName(self, _("Save Image As"),
                                               filename)
        if filename:
            if not self.imageViewer.image().save(filename):
                QMessageBox.critical(self, _("Error"),
                                     _("Could not save the image."))
            else:
                self.fileDragger.currentFile = filename