Пример #1
0
    def __init__(self):
        super(GeneralPreferences, self).__init__()
        grid = QGridLayout(self)
        grid.setSpacing(20)
        grid.setColumnStretch(1, 10)

        # directory auto completer
        completer = QCompleter(self)
        dirs = QDirModel(self)
        dirs.setFilter(QDir.AllDirs | QDir.NoDotAndDotDot)
        completer.setModel(dirs)
        completer.setCaseSensitivity(Qt.CaseInsensitive)
        completer.setCompletionMode(QCompleter.PopupCompletion)

        l = QLabel(
            u"<b>Ingresá el directorio donde descargar los videos...</b>")
        l.setTextFormat(Qt.RichText)
        grid.addWidget(l, 0, 0, 1, 2)

        grid.addWidget(QLabel(u"Descargar en:"), 1, 0, 2, 1)
        prv = config.get('downloaddir', '')
        self.downloaddir_entry = QLineEdit(prv)
        self.downloaddir_entry.setCompleter(completer)
        self.downloaddir_entry.setPlaceholderText(u'Ingresá un directorio')
        grid.addWidget(self.downloaddir_entry, 1, 1, 2, 2)

        self.downloaddir_buttn = QPushButton(u"Elegir un directorio")
        self.downloaddir_buttn.clicked.connect(self._choose_dir)
        grid.addWidget(self.downloaddir_buttn, 2, 1, 3, 2)

        self.autoreload_checkbox = QCheckBox(
            u"Recargar automáticamente la lista de episodios al iniciar")
        prv = config.get('autorefresh', False)
        self.autoreload_checkbox.setChecked(prv)
        grid.addWidget(self.autoreload_checkbox, 3, 0, 4, 2)

        self.shownotifs_checkbox = QCheckBox(
            u"Mostrar una notificación cuando termina cada descarga")
        prv = config.get('notification', True)
        self.shownotifs_checkbox.setChecked(prv)
        grid.addWidget(self.shownotifs_checkbox, 4, 0, 5, 2)
Пример #2
0
    def __init__(self):
        super(GeneralPreferences, self).__init__()
        grid = QGridLayout(self)
        grid.setSpacing(20)
        grid.setColumnStretch(1, 10)

        # directory auto completer
        completer = QCompleter(self)
        dirs = QDirModel(self)
        dirs.setFilter(QDir.AllDirs | QDir.NoDotAndDotDot)
        completer.setModel(dirs)
        completer.setCaseSensitivity(Qt.CaseInsensitive)
        completer.setCompletionMode(QCompleter.PopupCompletion)

        l = QLabel(
            u"<b>Ingresá el directorio donde descargar los videos...</b>")
        l.setTextFormat(Qt.RichText)
        grid.addWidget(l, 0, 0, 1, 2)

        grid.addWidget(QLabel(u"Descargar en:"), 1, 0, 2, 1)
        prv = config.get('downloaddir', '')
        self.downloaddir_entry = QLineEdit(prv)
        self.downloaddir_entry.setCompleter(completer)
        self.downloaddir_entry.setPlaceholderText(u'Ingresá un directorio')
        grid.addWidget(self.downloaddir_entry, 1, 1, 2, 2)

        self.downloaddir_buttn = QPushButton(u"Elegir un directorio")
        self.downloaddir_buttn.clicked.connect(self._choose_dir)
        grid.addWidget(self.downloaddir_buttn, 2, 1, 3, 2)

        self.autoreload_checkbox = QCheckBox(
            u"Recargar automáticamente la lista de episodios al iniciar")
        prv = config.get('autorefresh', False)
        self.autoreload_checkbox.setChecked(prv)
        grid.addWidget(self.autoreload_checkbox, 3, 0, 4, 2)

        self.shownotifs_checkbox = QCheckBox(
            u"Mostrar una notificación cuando termina cada descarga")
        prv = config.get('notification', True)
        self.shownotifs_checkbox.setChecked(prv)
        grid.addWidget(self.shownotifs_checkbox, 4, 0, 5, 2)
Пример #3
0
class DirCompleter(QCompleter):
    """ Completer for directory names """
    def __init__(self,
                 parent=None,
                 completionMode=QCompleter.PopupCompletion,
                 showHidden=False):

        QCompleter.__init__(self, parent)
        self.__model = QDirModel(self)

        if showHidden:
            filters = QDir.Filters(QDir.Drives | QDir.AllDirs | QDir.Hidden)
        else:
            filters = QDir.Filters(QDir.Drives | QDir.AllDirs)
        self.__model.setFilter(filters)

        self.setModel(self.__model)
        self.setCompletionMode(completionMode)

        if parent:
            parent.setCompleter(self)
        return
Пример #4
0
class DirCompleter( QCompleter ):
    """ Completer for directory names """

    def __init__( self, parent = None,
                  completionMode = QCompleter.PopupCompletion,
                  showHidden = False ):

        QCompleter.__init__( self, parent )
        self.__model = QDirModel( self )

        if showHidden:
            filters = QDir.Filters(QDir.Drives | QDir.AllDirs | QDir.Hidden)
        else:
            filters = QDir.Filters(QDir.Drives | QDir.AllDirs)
        self.__model.setFilter( filters )

        self.setModel( self.__model )
        self.setCompletionMode( completionMode )

        if parent:
            parent.setCompleter( self )
        return
Пример #5
0
class SearchWidget(QFrame):
    """Widget, appeared, when Ctrl+F pressed.
    Has different forms for different search modes
    """

    Normal = "normal"
    Good = "good"
    Bad = "bad"
    Incorrect = "incorrect"

    visibilityChanged = pyqtSignal(bool)
    """
    visibilityChanged(visible)
    
    **Signal** emitted, when widget has been shown or hidden
    """  # pylint: disable=W0105

    searchInDirectoryStartPressed = pyqtSignal(type(re.compile("")), list, unicode)
    """
    searchInDirectoryStartPressed(regEx, mask, path)
    
    **Signal** emitted, when 'search in directory' button had been pressed
    """  # pylint: disable=W0105

    searchInDirectoryStopPressed = pyqtSignal()
    """
    searchInDirectoryStopPressed()
    
    **Signal** emitted, when 'stop search in directory' button had been pressed
    """  # pylint: disable=W0105

    replaceCheckedStartPressed = pyqtSignal(unicode)
    """
    replaceCheckedStartPressed(replText)
    
    **Signal** emitted, when 'replace checked' button had been pressed
    """  # pylint: disable=W0105

    replaceCheckedStopPressed = pyqtSignal()
    """
    replaceCheckedStartPressed()
    
    **Signal** emitted, when 'stop replacing checked' button had been pressed
    """  # pylint: disable=W0105

    searchRegExpChanged = pyqtSignal(type(re.compile("")))
    """
    searchRegExpValidStateChanged(regEx)
    
    **Signal** emitted, when search regexp has been changed.
    If reg exp is invalid - regEx object contains empty pattern
    """  # pylint: disable=W0105

    searchNext = pyqtSignal()
    """
    searchNext()
    
    **Signal** emitted, when 'Search Next' had been pressed
    """  # pylint: disable=W0105

    searchPrevious = pyqtSignal()
    """
    searchPrevious()
    
    **Signal** emitted, when 'Search Previous' had been pressed
    """  # pylint: disable=W0105

    replaceFileOne = pyqtSignal(unicode)
    """
    replaceFileOne(replText)
    
    **Signal** emitted, when 'Replace' had been pressed
    """  # pylint: disable=W0105

    replaceFileAll = pyqtSignal(unicode)
    """
    replaceFileAll(replText)
    
    **Signal** emitted, when 'Replace All' had been pressed
    """  # pylint: disable=W0105

    def __init__(self, plugin):
        QFrame.__init__(self, core.workspace())
        self._mode = None
        self.plugin = plugin
        from PyQt4 import uic  # lazy import for better startup performance

        uic.loadUi(os.path.join(os.path.dirname(__file__), "SearchWidget.ui"), self)

        self.cbSearch.setCompleter(None)
        self.cbReplace.setCompleter(None)
        self.cbMask.setCompleter(None)

        self.fsModel = QDirModel(self.cbPath.lineEdit())
        self.fsModel.setFilter(QDir.AllDirs | QDir.NoDotAndDotDot)
        self.cbPath.lineEdit().setCompleter(QCompleter(self.fsModel, self.cbPath.lineEdit()))
        # TODO QDirModel is deprecated but QCompleter does not yet handle
        # QFileSystemodel - please update when possible."""
        self.cbSearch.setCompleter(None)
        self.pbSearchStop.setVisible(False)
        self.pbReplaceCheckedStop.setVisible(False)

        self._progress = QProgressBar(self)
        self._progress.setAlignment(Qt.AlignCenter)
        self._progress.setToolTip(self.tr("Search in progress..."))
        self._progress.setMaximumSize(QSize(80, 16))
        core.mainWindow().statusBar().insertPermanentWidget(1, self._progress)
        self._progress.setVisible(False)

        # cd up action
        self.tbCdUp = QToolButton(self.cbPath.lineEdit())
        self.tbCdUp.setIcon(QIcon(":/enkiicons/go-up.png"))
        self.tbCdUp.setCursor(Qt.ArrowCursor)
        self.tbCdUp.installEventFilter(self)  # for drawing button

        self.cbSearch.installEventFilter(self)  # for catching Tab and Shift+Tab
        self.cbReplace.installEventFilter(self)  # for catching Tab and Shift+Tab
        self.cbPath.installEventFilter(self)  # for catching Tab and Shift+Tab
        self.cbMask.installEventFilter(self)  # for catching Tab and Shift+Tab

        self._closeShortcut = QShortcut(QKeySequence("Esc"), self)
        self._closeShortcut.setContext(Qt.WidgetWithChildrenShortcut)
        self._closeShortcut.activated.connect(self.hide)

        # connections
        self.cbSearch.lineEdit().textChanged.connect(self._onSearchRegExpChanged)

        self.cbSearch.lineEdit().returnPressed.connect(self._onReturnPressed)
        self.cbReplace.lineEdit().returnPressed.connect(self._onReturnPressed)
        self.cbPath.lineEdit().returnPressed.connect(self._onReturnPressed)
        self.cbMask.lineEdit().returnPressed.connect(self._onReturnPressed)

        self.cbRegularExpression.stateChanged.connect(self._onSearchRegExpChanged)
        self.cbCaseSensitive.stateChanged.connect(self._onSearchRegExpChanged)

        self.tbCdUp.clicked.connect(self._onCdUpPressed)

        core.mainWindow().hideAllWindows.connect(self.hide)
        core.workspace().currentDocumentChanged.connect(
            lambda old, new: self.setVisible(self.isVisible() and new is not None)
        )

    def show(self):
        """Reimplemented function. Sends signal
        """
        super(SearchWidget, self).show()
        self.visibilityChanged.emit(self.isVisible())

    def hide(self):
        """Reimplemented function.
        Sends signal, returns focus to workspace
        """
        super(SearchWidget, self).hide()
        core.workspace().focusCurrentDocument()
        self.visibilityChanged.emit(self.isVisible())

    def setVisible(self, visible):
        """Reimplemented function. Sends signal
        """
        super(SearchWidget, self).setVisible(visible)
        self.visibilityChanged.emit(self.isVisible())

    def _regExEscape(self, text):
        """Improved version of re.escape()
        Doesn't escape space, comma, underscore.
        Escapes \n and \t
        """
        text = re.escape(text)
        # re.escape escapes space, comma, underscore, but, it is not necessary and makes text not readable
        for symbol in " ,_='\"/:@#%&":
            text = text.replace("\\" + symbol, symbol)

        text = text.replace("\\\n", "\\n")
        text = text.replace("\\\t", "\\t")

        return text

    def _makeEscapeSeqsVisible(self, text):
        """Replace invisible \n and \t with escape sequences
        """
        text = text.replace("\t", "\\t")
        text = text.replace("\n", "\\n")
        return text

    def setMode(self, mode):
        """Change search mode.
        i.e. from "Search file" to "Replace directory"
        """
        if self._mode == mode and self.isVisible():
            if core.workspace().currentDocument() is not None and not core.workspace().currentDocument().hasFocus():
                self.cbSearch.lineEdit().selectAll()
                self.cbSearch.setFocus()

        self._mode = mode

        # Set Search and Replace text
        if (
            core.workspace().currentDocument() is not None
            and core.workspace().currentDocument().hasFocus()
            and core.workspace().currentDocument().selectedText()
        ):
            searchText = core.workspace().currentDocument().selectedText()

            self.cbReplace.setEditText(self._makeEscapeSeqsVisible(searchText))

            if self.cbRegularExpression.checkState() == Qt.Checked:
                searchText = self._regExEscape(searchText)
            self.cbSearch.setEditText(searchText)

        if (
            not self.cbReplace.lineEdit().text()
            and self.cbSearch.lineEdit().text()
            and not self.cbRegularExpression.checkState() == Qt.Checked
        ):
            self.cbReplace.setEditText(self.cbSearch.lineEdit().text())

        # Move focus to Search edit
        self.cbSearch.setFocus()
        self.cbSearch.lineEdit().selectAll()

        # Set search path
        if mode & ModeFlagDirectory and not (self.isVisible() and self.cbPath.isVisible()):
            try:
                searchPath = os.path.abspath(unicode(os.path.curdir))
                self.cbPath.setEditText(searchPath)
            except OSError:  # current directory might have been deleted
                pass

        # Set widgets visibility flag according to state
        widgets = (
            self.wSearch,
            self.pbPrevious,
            self.pbNext,
            self.pbSearch,
            self.wReplace,
            self.wPath,
            self.pbReplace,
            self.pbReplaceAll,
            self.pbReplaceChecked,
            self.wOptions,
            self.wMask,
        )
        #                         wSear  pbPrev pbNext pbSear wRepl  wPath  pbRep  pbRAll pbRCHK wOpti wMask
        visible = {
            ModeSearch: (1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0),
            ModeReplace: (1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0),
            ModeSearchDirectory: (1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1),
            ModeReplaceDirectory: (1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1),
            ModeSearchOpenedFiles: (1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1),
            ModeReplaceOpenedFiles: (1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1),
        }

        for i, widget in enumerate(widgets):
            widget.setVisible(visible[mode][i])

        # Search next button text
        if mode == ModeReplace:
            self.pbNext.setText("Next")
        else:
            self.pbNext.setText(u"Next↵")

        # Finaly show all with valid size
        self.show()  # show before updating widgets and labels
        self._updateLabels()
        self._updateWidgets()

    def eventFilter(self, object_, event):
        """ Event filter for mode switch tool button
        Draws icons in the search and path lineEdits
        """
        if event.type() == QEvent.Paint and object_ is self.tbCdUp:  # draw CdUp button in search path QLineEdit
            toolButton = object_
            lineEdit = self.cbPath.lineEdit()
            lineEdit.setContentsMargins(lineEdit.height(), 0, 0, 0)

            height = lineEdit.height()
            availableRect = QRect(0, 0, height, height)

            if toolButton.rect() != availableRect:
                toolButton.setGeometry(availableRect)

            painter = QPainter(toolButton)
            toolButton.icon().paint(painter, availableRect)

            return True

        elif event.type() == QEvent.KeyPress:  # Tab and Shift+Tab in QLineEdits

            if event.key() == Qt.Key_Tab:
                self._moveFocus(1)
                return True
            elif event.key() == Qt.Key_Backtab:
                self._moveFocus(-1)
                return True

        return QFrame.eventFilter(self, object_, event)

    def _onReturnPressed(self):
        """Return or Enter pressed on widget.
        Search next or Replace next
        """
        if self.pbReplace.isVisible():
            self.pbReplace.click()
        elif self.pbNext.isVisible():
            self.pbNext.click()
        elif self.pbSearch.isVisible():
            self.pbSearch.click()
        elif self.pbSearchStop.isVisible():
            self.pbSearchStop.click()

    def _moveFocus(self, step):
        """Move focus forward or backward according to step.
        Standard Qt Keyboard focus algorithm doesn't allow circular navigation
        """
        allFocusableWidgets = (self.cbSearch, self.cbReplace, self.cbPath, self.cbMask)
        visibleWidgets = [widget for widget in allFocusableWidgets if widget.isVisible()]

        try:
            focusedIndex = visibleWidgets.index(QApplication.focusWidget())
        except ValueError:
            print >>sys.stderr, "Invalid focused widget in Search Widget"
            return

        nextFocusedIndex = (focusedIndex + step) % len(visibleWidgets)

        visibleWidgets[nextFocusedIndex].setFocus()
        visibleWidgets[nextFocusedIndex].lineEdit().selectAll()

    def _updateLabels(self):
        """Update 'Search' 'Replace' 'Path' labels geometry
        """
        width = 0

        if self.lSearch.isVisible():
            width = max(width, self.lSearch.minimumSizeHint().width())

        if self.lReplace.isVisible():
            width = max(width, self.lReplace.minimumSizeHint().width())

        if self.lPath.isVisible():
            width = max(width, self.lPath.minimumSizeHint().width())

        self.lSearch.setMinimumWidth(width)
        self.lReplace.setMinimumWidth(width)
        self.lPath.setMinimumWidth(width)

    def _updateWidgets(self):
        """Update geometry of widgets with buttons
        """
        width = 0

        if self.wSearchRight.isVisible():
            width = max(width, self.wSearchRight.minimumSizeHint().width())

        if self.wReplaceRight.isVisible():
            width = max(width, self.wReplaceRight.minimumSizeHint().width())

        if self.wPathRight.isVisible():
            width = max(width, self.wPathRight.minimumSizeHint().width())

        self.wSearchRight.setMinimumWidth(width)
        self.wReplaceRight.setMinimumWidth(width)
        self.wPathRight.setMinimumWidth(width)

    def _updateComboBoxes(self):
        """Update comboboxes with last used texts
        """
        searchText = self.cbSearch.currentText()
        replaceText = self.cbReplace.currentText()
        maskText = self.cbMask.currentText()

        # search
        if searchText:
            index = self.cbSearch.findText(searchText)

            if index == -1:
                self.cbSearch.addItem(searchText)

        # replace
        if replaceText:
            index = self.cbReplace.findText(replaceText)

            if index == -1:
                self.cbReplace.addItem(replaceText)

        # mask
        if maskText:
            index = self.cbMask.findText(maskText)

            if index == -1:
                self.cbMask.addItem(maskText)

    def _searchPatternTextAndFlags(self):
        """Get search pattern and flags
        """
        pattern = self.cbSearch.currentText()
        if not self.cbRegularExpression.checkState() == Qt.Checked:
            pattern = re.escape(pattern)
        flags = 0
        if not self.cbCaseSensitive.checkState() == Qt.Checked:
            flags = re.IGNORECASE
        return pattern, flags

    def getRegExp(self):
        """Read search parameters from controls and present it as a regular expression
        """
        pattern, flags = self._searchPatternTextAndFlags()
        return re.compile(pattern, flags)

    def isSearchRegExpValid(self):
        """Try to compile search pattern to check if it is valid
        Returns bool result and text error
        """
        pattern, flags = self._searchPatternTextAndFlags()
        try:
            re.compile(pattern, flags)
        except re.error, ex:
            return False, unicode(ex)

        return True, None
Пример #6
0
class DiffGUI(object):
    ' diff gui class '
    def __init__(self):
        ' make a diff method with GUI '
        self.dialog = QDialog()
        self.diff_path = None

        # directory auto completer
        self.completer = QCompleter(self.dialog)
        self.dirs = QDirModel(self.dialog)
        self.dirs.setFilter(QDir.AllEntries | QDir.NoDotAndDotDot)
        self.completer.setModel(self.dirs)
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.setCompletionMode(QCompleter.PopupCompletion)
        #self.completer.setCompletionMode(QCompleter.InlineCompletion)

        self.group1 = QGroupBox()
        self.group1.setTitle('Diff')
        self.frmt = QComboBox(self.group1)
        self.frmt.addItems(['Unified', 'Normal', 'Context'])
        self.file1 = QLineEdit()
        self.file1.setPlaceholderText('/full/path/to/one_file.py')
        self.file1.setCompleter(self.completer)
        self.file2 = QLineEdit()
        self.file2.setPlaceholderText('/full/path/to/another_file.py')
        self.file2.setCompleter(self.completer)
        self.fout = QLineEdit()
        self.fout.setText(''.join((path.join(gettempdir(),
                     datetime.now().strftime('%d-%b-%Y_%H:%M:%S.diff')))))
        self.fout.setPlaceholderText('/full/path/to/output_file.diff')
        self.fout.setCompleter(self.completer)
        self.regex = QLineEdit()
        self.regex.setPlaceholderText('DONT use unless you know what are doing')
        self.regex.setToolTip('Do NOT use unless you know what you are doing !')
        self.borig = QPushButton(QIcon.fromTheme("folder-open"), 'Open')
        self.borig.clicked.connect(lambda: self.file1.setText(str(
            QFileDialog.getOpenFileName(self.dialog, 'Open file to compare',
                                           path.expanduser("~"), ';;(*.*)'))))

        self.bmodi = QPushButton(QIcon.fromTheme("folder-open"), 'Open')
        self.bmodi.clicked.connect(lambda: self.file2.setText(str(
            QFileDialog.getOpenFileName(self.dialog, 'Open file to compare',
                                           path.expanduser("~"), ';;(*.*)'))))
        self.bout = QPushButton(QIcon.fromTheme("folder-open"), 'Open')
        self.bout.clicked.connect(lambda: self.fout.setText(str(
            QFileDialog.getSaveFileName(self.dialog, 'Save a Diff file',
                                        path.expanduser("~"), ';;(*.diff)'))))
        vboxg1 = QVBoxLayout(self.group1)
        for each_widget in (QLabel('Original file full path'),
                            self.file1, self.borig,
                            QLabel('Modified file full path'),
                            self.file2, self.bmodi,
                            QLabel('Output file full Path'),
                            self.fout, self.bout,
                            QLabel('Diff Output Format'), self.frmt,
                            QLabel('Diff REGEX to Ignore (ADVANCED)'),
                            self.regex):
            vboxg1.addWidget(each_widget)

        self.group2 = QGroupBox()
        self.group2.setTitle('Options')
        self.nwfl = QCheckBox('Treat new files as Empty')
        self.smll = QCheckBox('Look for smaller changes')
        self.lrgf = QCheckBox('Optimize for large files')
        self.case = QCheckBox('Ignore case changes on content')
        self.cnvt = QCheckBox('Convert Tabs to Spaces')
        self.blnk = QCheckBox('Ignore added or removed Blank lines')
        self.spac = QCheckBox('Ignore changes in amount of Spaces')
        self.whit = QCheckBox('Ignore ALL white Spaces')
        self.tabz = QCheckBox('Ignore changes by Tab expansions')
        self.sprs = QCheckBox('Remove Space or Tab before empty lines')
        self.filn = QCheckBox('Ignore case when comparing file names')
        self.tbs = QComboBox(self.group2)
        self.tbs.addItems(['4', '6', '8', '10', '2'])
        self.nice = QComboBox(self.group2)
        self.nice.addItems(['20', '15', '10', '5', '0'])
        vboxg2 = QVBoxLayout(self.group2)
        for each_widget in (self.nwfl, self.smll, self.lrgf, self.case,
                            self.cnvt, self.blnk, self.spac, self.whit,
                            self.tabz, self.sprs, self.filn,
                            QLabel('Diff Tabs-to-Spaces Size'), self.tbs,
                            QLabel('Diff Backend CPU Priority'), self.nice):
            vboxg2.addWidget(each_widget)
            try:
                each_widget.setToolTip(each_widget.text())
            except:
                each_widget.setToolTip(each_widget.currentText())
            each_widget.setCursor(QCursor(Qt.PointingHandCursor))

        group3 = QGroupBox()
        group3.setTitle('Even More Options')
        self.plai = QCheckBox('Force treat all files as plain text')
        self.nocr = QCheckBox('Force strip trailing carriage return')
        self.ridt = QCheckBox('Report when two files are identical')
        self.nocm = QCheckBox('Do not output common lines')
        self.rdif = QCheckBox('Report only when files differ')
        self.clip = QCheckBox('Copy Diff to Clipboard when done')
        self.noti = QCheckBox('Use system Notification when done')
        self.pret = QCheckBox('Align all Tabs by prepending a Tab')
        self.lolz = QCheckBox('Output Diff in two equal columns')
        self.odif = QCheckBox('Open Diff with Ninja-IDE when done')
        self.plac = QCheckBox('Make an Awesome Diff view when done')
        self.wdth = QComboBox(group3)
        self.wdth.addItems(['80', '100', '120', '130', '250', '500', '999999'])
        self.bcknd = QComboBox(group3)
        self.bcknd.addItems(['diff', 'diff.py'])
        self.bcknd.setDisabled(True)  #TODO this feature needs work
        vboxg3 = QVBoxLayout(group3)
        for each_widget in (self.plai, self.nocr, self.ridt, self.nocm,
                            self.rdif, self.pret, self.clip, self.noti,
                            self.lolz, self.odif, self.plac,
                            QLabel('Diff Maximum Total Width'), self.wdth,
                            QLabel('Diff Backend (EXPERIMENTAL)'), self.bcknd):
            vboxg3.addWidget(each_widget)
            try:
                each_widget.setToolTip(each_widget.text())
            except:
                each_widget.setToolTip(each_widget.currentText())
            each_widget.setCursor(QCursor(Qt.PointingHandCursor))

        for widget_should_be_checked in (self.nwfl, self.smll, self.lrgf,
                                   self.clip, self.cnvt, self.plai, self.noti):
            widget_should_be_checked.setChecked(True)

        container = QWidget()
        hbox = QHBoxLayout(container)
        for each_widget in (self.group2, self.group1, group3):
            hbox.addWidget(each_widget)

        buttons = QDialogButtonBox()
        buttons.resize(self.dialog.size().width(), buttons.size().height() * 2)
        buttons.setOrientation(Qt.Horizontal)
        buttons.setStandardButtons(
            QDialogButtonBox.Ok |
            QDialogButtonBox.Cancel |
            QDialogButtonBox.Close |
            QDialogButtonBox.Help)
        buttons.setCenterButtons(False)
        buttons.helpRequested.connect(lambda: QMessageBox.about(
            self.dialog, __doc__,
            ''.join((__doc__, ' GUI and Visualizer Plugin,', linesep,
            'version ', __version__, ', (', __license__, '), by ', linesep,
            __author__, ', ( ', __email__, ' ).', linesep))))
        buttons.rejected.connect(self.dialog.close)
        buttons.accepted.connect(self.make_diff)

        info = QLabel(''.join(('<b> Current Backend Diff Engine: </b>',
                      getoutput('diff --version').split(linesep)[0])))

        vbox = QVBoxLayout(self.dialog)
        for each_widget in (
                QLabel('<center><h2> Ninja IDE Diff and Patch </h2></center>'),
                container, info, buttons):
            vbox.addWidget(each_widget)

        self.dialog.resize(1024, self.dialog.size().height())
        self.dialog.exec_()

    def make_diff(self):
        ' make the diff '
        diff_command = ''.join((
        'nice --adjustment=', str(self.nice.currentText()).strip(), ' ',
        str(self.bcknd.currentText()).strip(), ' --',
        str(self.frmt.currentText()).strip().lower(),

        ' --new-file ' if self.nwfl.isChecked() is True else '',
        ' --minimal ' if self.smll.isChecked() is True else '',
        ' --speed-large-files ' if self.lrgf.isChecked() is True else '',
        ' --ignore-self.case ' if self.case.isChecked() is True else '',
        ' --expand-tabs ' if self.cnvt.isChecked() is True else '',
        ' --ignore-blank-lines ' if self.blnk.isChecked() is True else '',
        ' --ignore-space-change ' if self.spac.isChecked() is True else '',
        ' --ignore-all-space ' if self.whit.isChecked() is True else '',
        ' --ignore-tab-expansion ' if self.tabz.isChecked() is True else '',
        ' --suppress-blank-empty ' if self.sprs.isChecked() is True else '',
        ' --ignore-file-name-case ' if self.filn.isChecked() is True else '',
        ' --text ' if self.plai.isChecked() is True else '',
        ' --strip-trailing-cr ' if self.nocr.isChecked() is True else '',
        ' --suppress-common-lines ' if self.nocm.isChecked() is True else '',
        ' --initial-tab ' if self.pret.isChecked() is True else '',
        ' --side-by-side ' if self.lolz.isChecked() is True else '',

        ' --tabsize=', str(self.tbs.currentText()).strip(),
        ' --width=', str(self.wdth.currentText()).strip(),

        str(' --ignore-matching-lines=' + str(self.regex.text()).strip())
                           if str(self.regex.text()).strip() is not '' else '',
        ' ',
        path.abspath(str(self.file1.text()))
                    if str(self.file1.text()).strip() is not '' else __file__,
        ' ',
        path.abspath(str(self.file2.text()))
                    if str(self.file2.text()).strip() is not '' else __file__
        ))

        print(diff_command)
        diff_output = getoutput(diff_command)
        try:
            print(' INFO: OK, Saving new Diff to disk...')
            output_file = file(path.abspath(str(self.fout.text())), 'w')
            output_file.write(diff_output)
            output_file.close()
        except:
            print(' ERROR: FAIL, Can not save Diff to disk!')
        if self.clip.isChecked() is True:
            print(' INFO: OK, Diff Copied to Clipboard...')
            QApplication.clipboard().setText(diff_output)
        if self.noti.isChecked() is True:
            call('notify-send [Ninja-IDE] ¡Diff_is_Ready!', shell=True)
        if self.odif.isChecked() is True:
            print(' INFO: OK, Opening Diff with Ninja-IDE')
            call('ninja-ide ' + path.abspath(str(self.fout.text())), shell=True)

        self.diff_path = path.abspath(str(self.fout.text()))
        return self.diff_path
Пример #7
0
class ComboBox(QComboBox):
    """File browser combo box.
    Widget and functionality
    """
    def __init__(self, fileBrowser):
        QComboBox.__init__(self, fileBrowser)

        self._fileBrowser = fileBrowser

        self.setAttribute(Qt.WA_MacShowFocusRect, False)
        self.setAttribute(Qt.WA_MacSmallSize)
        self.setEditable(True)
        self.setMinimumContentsLength(1)
        self.setSizeAdjustPolicy(
            QComboBox.AdjustToMinimumContentsLengthWithIcon)
        self.lineEdit().setReadOnly(False)
        self._completionModel = QDirModel(self.lineEdit())
        self._completionModel.setFilter(QDir.AllDirs | QDir.NoDotAndDotDot)
        self.lineEdit().setCompleter(
            QCompleter(self._completionModel, self.lineEdit()))
        #TODO QDirModel is deprecated but QCompleter does not yet handle
        #QFileSystemModel - please update when possible.
        self._count = 0

        # Show popup action
        self._showPopupAction = QAction(QIcon(':enkiicons/filtered.png'),
                                        "File browser history", self)
        self._showPopupAction.setShortcut('Ctrl+H')
        core.actionManager().addAction("mNavigation/mFileBrowser/aMenuShow",
                                       self._showPopupAction)
        self._showPopupAction.triggered.connect(self._onShowPopup)

        # reconnected in self.updateComboItems()
        self.currentIndexChanged[int].connect(self._onItemSelected)

    def del_(self):
        """Explicitly called destructor
        """
        core.actionManager().removeAction(self._showPopupAction)

    def _onShowPopup(self, triggered):
        """Handler for self._showPopupAction
        """
        self.showPopup()

    @pyqtSlot(int)
    def _onItemSelected(self, index):
        """Handler of item selection in the combo box
        """
        if self.count() > self._count:  # It is user input
            path = self.itemText(index)
            if os.path.isdir(path):
                self._fileBrowser.setCurrentPath(path)
        else:
            path = self.itemData(index).toString()
            self._fileBrowser.setCurrentPath(path)

    def updateItems(self, items):
        """Update items in the combo box according to current history
        """
        self.currentIndexChanged[int].disconnect()
        self.clear()
        # Current text
        self.addItem(self._fileBrowser.currentPath())
        self.setItemData(0, self._fileBrowser.currentPath())
        self.insertSeparator(self.count())

        for index, path in enumerate(items):
            self.addItem(path)
            self.setItemData(index + 2, path)
        self._count = self.count()
        self.currentIndexChanged[int].connect(self._onItemSelected)
Пример #8
0
class MyMainWindow(QMainWindow):
    " Main Window "

    def __init__(self, parent=None):
        " Initialize QWidget inside MyMainWindow "
        super(MyMainWindow, self).__init__(parent)
        QWidget.__init__(self)
        self.statusBar().showMessage("               " + __doc__)
        self.setStyleSheet("QStatusBar{color:grey;}")
        self.setWindowTitle(__doc__)
        self.setWindowIcon(QIcon.fromTheme("face-monkey"))
        self.setFont(QFont("Ubuntu Light", 10))
        self.setMaximumSize(QDesktopWidget().screenGeometry().width(), QDesktopWidget().screenGeometry().height())

        # directory auto completer
        self.completer = QCompleter(self)
        self.dirs = QDirModel(self)
        self.dirs.setFilter(QDir.AllEntries | QDir.NoDotAndDotDot)
        self.completer.setModel(self.dirs)
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.setCompletionMode(QCompleter.PopupCompletion)

        # process
        self.process = QProcess(self)
        # self.process.finished.connect(self.on_process_finished)
        # self.process.error.connect(self.on_process_error)

        # Proxy support, by reading http_proxy os env variable
        proxy_url = QUrl(environ.get("http_proxy", ""))
        QNetworkProxy.setApplicationProxy(
            QNetworkProxy(
                QNetworkProxy.HttpProxy if str(proxy_url.scheme()).startswith("http") else QNetworkProxy.Socks5Proxy,
                proxy_url.host(),
                proxy_url.port(),
                proxy_url.userName(),
                proxy_url.password(),
            )
        ) if "http_proxy" in environ else None
        print((" INFO: Proxy Auto-Config as " + str(proxy_url)))

        # basic widgets layouts and set up
        self.mainwidget = QTabWidget()
        self.mainwidget.setToolTip(__doc__)
        self.mainwidget.setMovable(True)
        self.mainwidget.setTabShape(QTabWidget.Triangular)
        self.mainwidget.setTabsClosable(True)
        self.mainwidget.setContextMenuPolicy(Qt.CustomContextMenu)
        self.mainwidget.tabCloseRequested.connect(
            lambda: self.mainwidget.setTabPosition(1)
            if self.mainwidget.tabPosition() == 0
            else self.mainwidget.setTabPosition(0)
        )
        self.setCentralWidget(self.mainwidget)
        self.dock1 = QDockWidget()
        self.dock2 = QDockWidget()
        self.dock3 = QDockWidget()
        for a in (self.dock1, self.dock2, self.dock3):
            a.setWindowModality(Qt.NonModal)
            a.setWindowOpacity(0.9)
            a.setWindowTitle(__doc__ if a.windowTitle() == "" else a.windowTitle())
            a.setStyleSheet(" QDockWidget::title{text-align:center;}")
            a.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable)
            self.mainwidget.addTab(a, QIcon.fromTheme("face-cool"), str(a.windowTitle()).strip().lower())

        # Paleta de colores para pintar transparente
        self.palette().setBrush(QPalette.Base, Qt.transparent)
        self.setPalette(self.palette())
        self.setAttribute(Qt.WA_OpaquePaintEvent, False)

        # toolbar and basic actions
        self.toolbar = QToolBar(self)
        self.toolbar.setIconSize(QSize(24, 24))
        # spacer widget for left
        self.left_spacer = QWidget(self)
        self.left_spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        # spacer widget for right
        self.right_spacer = QWidget(self)
        self.right_spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        qaqq = QAction(QIcon.fromTheme("application-exit"), "Quit", self)
        qaqq.setShortcut("Ctrl+Q")
        qaqq.triggered.connect(exit)
        qamin = QAction(QIcon.fromTheme("go-down"), "Minimize", self)
        qamin.triggered.connect(lambda: self.showMinimized())
        qamax = QAction(QIcon.fromTheme("go-up"), "Maximize", self)
        qanor = QAction(QIcon.fromTheme("go-up"), "AutoCenter AutoResize", self)
        qanor.triggered.connect(self.center)
        qatim = QAction(QIcon.fromTheme("go-up"), "View Date and Time", self)
        qatim.triggered.connect(self.timedate)
        qabug = QAction(QIcon.fromTheme("help-about"), "Report a Problem", self)
        qabug.triggered.connect(
            lambda: qabug.setDisabled(True)
            if not call("xdg-open mailto:" + "*****@*****.**".decode("rot13"), shell=True)
            else " ERROR "
        )
        qamax.triggered.connect(lambda: self.showMaximized())
        qaqt = QAction(QIcon.fromTheme("help-about"), "About Qt", self)
        qaqt.triggered.connect(lambda: QMessageBox.aboutQt(self))
        qaslf = QAction(QIcon.fromTheme("help-about"), "About Self", self)
        qaslf.triggered.connect(
            lambda: QMessageBox.about(
                self.mainwidget,
                __doc__,
                "".join(
                    (
                        __doc__,
                        linesep,
                        "version ",
                        __version__,
                        ", (",
                        __license__,
                        "), by ",
                        __author__,
                        ", ( ",
                        __email__,
                        " )",
                        linesep,
                    )
                ),
            )
        )
        qasrc = QAction(QIcon.fromTheme("applications-development"), "View Source Code", self)
        qasrc.triggered.connect(lambda: call("xdg-open " + __file__, shell=1))
        qakb = QAction(QIcon.fromTheme("input-keyboard"), "Keyboard Shortcuts", self)
        qakb.triggered.connect(
            lambda: QMessageBox.information(self.mainwidget, "Keyboard Shortcuts", " Ctrl+Q = Quit ")
        )
        qapic = QAction(QIcon.fromTheme("camera-photo"), "Take a Screenshot", self)
        qapic.triggered.connect(
            lambda: QPixmap.grabWindow(QApplication.desktop().winId()).save(
                QFileDialog.getSaveFileName(
                    self.mainwidget, " Save Screenshot As ...", path.expanduser("~"), ";;(*.png) PNG", "png"
                )
            )
        )
        qatb = QAction(QIcon.fromTheme("help-browser"), "Toggle ToolBar", self)
        qatb.triggered.connect(lambda: self.toolbar.hide() if self.toolbar.isVisible() is True else self.toolbar.show())
        qati = QAction(QIcon.fromTheme("help-browser"), "Switch ToolBar Icon Size", self)
        qati.triggered.connect(
            lambda: self.toolbar.setIconSize(self.toolbar.iconSize() * 4)
            if self.toolbar.iconSize().width() * 4 == 24
            else self.toolbar.setIconSize(self.toolbar.iconSize() / 4)
        )
        qasb = QAction(QIcon.fromTheme("help-browser"), "Toggle Tabs Bar", self)
        qasb.triggered.connect(
            lambda: self.mainwidget.tabBar().hide()
            if self.mainwidget.tabBar().isVisible() is True
            else self.mainwidget.tabBar().show()
        )
        qadoc = QAction(QIcon.fromTheme("help-browser"), "On-line Docs", self)
        qadoc.triggered.connect(lambda: open_new_tab(__url__))
        qapy = QAction(QIcon.fromTheme("help-browser"), "About Python", self)
        qapy.triggered.connect(lambda: open_new_tab("http://python.org/about"))
        qali = QAction(QIcon.fromTheme("help-browser"), "Read Licence", self)
        qali.triggered.connect(lambda: open_new_tab(__full_licence__))
        qacol = QAction(QIcon.fromTheme("preferences-system"), "Set GUI Colors", self)
        qacol.triggered.connect(
            lambda: self.setStyleSheet(
                """ * {
                background-color: %s } """
                % QColorDialog.getColor().name()
            )
        )
        qatit = QAction(QIcon.fromTheme("preferences-system"), "Set the App Window Title", self)
        qatit.triggered.connect(self.seTitle)
        qafnt = QAction(QIcon.fromTheme("help-about"), "Set GUI Font", self)
        if KDE:
            font = QFont()
            qafnt.triggered.connect(
                lambda: self.setStyleSheet("*{font-family: %s}" % font.toString())
                if KFontDialog.getFont(font)[0] == QDialog.Accepted
                else ""
            )
        else:
            qafnt.triggered.connect(
                lambda: self.setStyleSheet("*{font-family: %s}" % QFontDialog.getFont()[0].toString())
            )
        self.toolbar.addWidget(self.left_spacer)
        self.toolbar.addSeparator()
        for b in (
            qaqq,
            qamin,
            qanor,
            qamax,
            qasrc,
            qakb,
            qacol,
            qatim,
            qatb,
            qati,
            qasb,
            qatit,
            qafnt,
            qapic,
            qadoc,
            qali,
            qaslf,
            qaqt,
            qapy,
            qabug,
        ):
            self.toolbar.addAction(b)
        self.addToolBar(Qt.TopToolBarArea, self.toolbar)
        self.toolbar.addSeparator()
        self.toolbar.addWidget(self.right_spacer)

        def contextMenuRequested(point):
            " quick and dirty custom context menu "
            menu = QMenu()
            menu.addActions(
                (
                    qaqq,
                    qamin,
                    qanor,
                    qamax,
                    qasrc,
                    qakb,
                    qacol,
                    qati,
                    qasb,
                    qatb,
                    qatim,
                    qatit,
                    qafnt,
                    qapic,
                    qadoc,
                    qali,
                    qaslf,
                    qaqt,
                    qapy,
                    qabug,
                )
            )
            menu.exec_(self.mapToGlobal(point))

        self.mainwidget.customContextMenuRequested.connect(contextMenuRequested)

        def must_be_checked(widget_list):
            " widget tuple passed as argument should be checked as ON "
            for each_widget in widget_list:
                try:
                    each_widget.setChecked(True)
                except:
                    pass

        def must_have_tooltip(widget_list):
            " widget tuple passed as argument should have tooltips "
            for each_widget in widget_list:
                try:
                    each_widget.setToolTip(each_widget.text())
                except:
                    each_widget.setToolTip(each_widget.currentText())
                finally:
                    each_widget.setCursor(QCursor(Qt.PointingHandCursor))

        def must_autofillbackground(widget_list):
            " widget tuple passed as argument should have filled background "
            for each_widget in widget_list:
                try:
                    each_widget.setAutoFillBackground(True)
                except:
                    pass

        #######################################################################

        self.group1 = QGroupBox()
        self.group1.setTitle(" Blender ")
        self.arch = QLabel("<center><b>" + architecture()[0])
        self.ost = QLabel("<center><b>" + sys.platform)
        self.downf = QLineEdit(path.join(path.expanduser("~"), "blender"))
        self.downf.setCompleter(self.completer)
        self.borig = QPushButton(QIcon.fromTheme("folder-open"), "Open")
        self.borig.clicked.connect(
            lambda: self.downf.setText(
                path.join(
                    str(QFileDialog.getExistingDirectory(self.mainwidget, "Open a Folder", path.expanduser("~"))),
                    "blender",
                )
            )
        )
        self.bugs = QPushButton(QIcon.fromTheme("help-faq"), "Report Bugs!")
        self.bugs.clicked.connect(lambda: open_new_tab("http://www.blender.org/development/report-a-bug"))
        self.go = QPushButton(QIcon.fromTheme("emblem-favorite"), "Run Blender")
        self.go.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.go.clicked.connect(self.run)
        vboxg1 = QVBoxLayout(self.group1)
        for each_widget in (
            self.go,
            QLabel(""),
            QLabel('<h3 style="color:white;"> Download Folder Path: </h3>'),
            self.downf,
            self.borig,
            QLabel('<h3 style="color:white;"> Bugs: </h3>'),
            self.bugs,
            QLabel('<h3 style="color:white;"> OS: </h3>'),
            self.ost,
            QLabel('<h3 style="color:white;"> Architexture: </h3>'),
            self.arch,
            QLabel(
                """<i style="color:white;"> Warning:
        this builds arent as stable as releases, use at your own risk</i>"""
            ),
        ):
            vboxg1.addWidget(each_widget)

        self.group2 = QGroupBox()
        self.group2.setTitle("Options")
        self.nwfl = QCheckBox("Force opening with borders")
        self.smll = QCheckBox("Auto Center and Auto Resize the Window")
        self.lrgf = QCheckBox("Start with the console window open")
        self.case = QCheckBox("BGE: Run on 50 hertz without dropping frames")
        self.cnvt = QCheckBox("BGE: Use Vertex Arrays for rendering")
        self.blnk = QCheckBox("BGE: No Texture Mipmapping")
        self.spac = QCheckBox("BGE: Linear Texture Mipmap instead of Nearest")
        self.whit = QCheckBox("Turn Debugging ON")
        self.tabz = QCheckBox("Enable floating point exceptions")
        self.sprs = QCheckBox("Disable the crash handler")
        self.filn = QCheckBox("Enable debug messages from FFmpeg library")

        self.plac = QCheckBox("Enable debug messages for python")
        self.plac = QCheckBox("Enable debug messages for the event system")
        self.plac = QCheckBox("Enable debug messages for event handling")
        self.plac = QCheckBox("Enable debug messages for the window manager")

        self.tbs = QComboBox(self.group2)
        self.tbs.addItems(["0", "1", "2", "3"])
        self.nice = QComboBox(self.group2)
        self.nice.addItems(["0", "1", "2", "3"])
        vboxg2 = QVBoxLayout(self.group2)
        for each_widget in (
            self.nwfl,
            self.smll,
            self.lrgf,
            self.case,
            self.cnvt,
            self.blnk,
            self.spac,
            self.whit,
            self.tabz,
            self.sprs,
            self.filn,
            QLabel("BLAH BLAH BLAH"),
            self.tbs,
            QLabel("BLAH BLAH BLAH"),
            self.nice,
        ):
            vboxg2.addWidget(each_widget)

        group3 = QGroupBox()
        group3.setTitle("Even More Options")
        self.plai = QCheckBox("Enable debug messages from libmv library")
        self.nocr = QCheckBox("Skip reading the startup.blend in the home dir")
        self.ridt = QCheckBox("Set BLENDER_SYSTEM_DATAFILES environment var")
        self.nocm = QCheckBox("Set BLENDER_SYSTEM_SCRIPTS environment var")
        self.rdif = QCheckBox("Set BLENDER_SYSTEM_PYTHON environment var")
        self.clip = QCheckBox("Disable joystick support")
        self.noti = QCheckBox("Disable GLSL shading")
        self.pret = QCheckBox("Force sound system to None")
        self.lolz = QCheckBox("Disable automatic python script execution")
        self.odif = QCheckBox("Run blender with an interactive console")

        self.plac = QCheckBox("Enable all debug messages, excludes libmv")
        self.plac = QCheckBox("Enable time profiling for background jobs")
        self.plac = QCheckBox("Do not use native pixel size for high res")

        self.wdth = QComboBox(group3)
        self.wdth.addItems(["OPENAL", "NULL", "SDL", "JACK"])
        self.bcknd = QComboBox(group3)
        self.bcknd.addItems(["0", "5", "10", "15", "20"])
        vboxg3 = QVBoxLayout(group3)
        for each_widget in (
            self.plai,
            self.nocr,
            self.ridt,
            self.nocm,
            self.rdif,
            self.pret,
            self.clip,
            self.noti,
            self.lolz,
            self.odif,
            self.plac,
            QLabel('<b style="color:white">Force sound system to specific device'),
            self.wdth,
            QLabel('<b style="color:white">CPU Priority'),
            self.bcknd,
        ):
            vboxg3.addWidget(each_widget)

        # dock 2 the waterfall
        scrollable = QScrollArea()
        scrollable.setWidget(QLabel("".join((urlopen("http://builder.blender.org/waterfall").readlines()[23:]))))
        self.dock2.setWidget(scrollable)

        # dock 3 the build status
        stats = QLabel(
            "<center>"
            + "".join((urlopen("http://builder.blender.org/one_line_per_build").readlines()[23:])).strip()
            + "</center>"
        )
        self.dock3.setWidget(stats)

        # configure some widget settings
        must_be_checked((self.nwfl, self.smll, self.lrgf, self.clip, self.cnvt, self.plai, self.noti))
        must_have_tooltip(
            (
                self.plai,
                self.nocr,
                self.ridt,
                self.nocm,
                self.rdif,
                self.pret,
                self.clip,
                self.noti,
                self.lolz,
                self.odif,
                self.plac,
                self.wdth,
                self.bcknd,
                self.nwfl,
                self.smll,
                self.lrgf,
                self.case,
                self.cnvt,
                self.blnk,
                self.spac,
                self.whit,
                self.tabz,
                self.sprs,
                self.filn,
                self.tbs,
                self.nice,
                self.arch,
                self.ost,
            )
        )
        must_autofillbackground(
            (
                self.plai,
                self.nocr,
                self.ridt,
                self.nocm,
                self.rdif,
                self.pret,
                self.clip,
                self.noti,
                self.lolz,
                self.odif,
                self.plac,
                self.wdth,
                self.bcknd,
                self.nwfl,
                self.smll,
                self.lrgf,
                self.case,
                self.cnvt,
                self.blnk,
                self.spac,
                self.whit,
                self.tabz,
                self.sprs,
                self.filn,
                self.tbs,
                self.nice,
                scrollable,
                stats,
                self.arch,
                self.ost,
            )
        )

        container = QWidget()
        hbox = QHBoxLayout(container)
        for each_widget in (self.group2, self.group1, group3):
            hbox.addWidget(each_widget)

        self.dock1.setWidget(container)

    def run(self):
        " run the actual conversion "
        print((" INFO: Working at " + str(datetime.now())))
        print(" INFO: Loading Blender awesomeness . . . ")
        self.go.setDisabled(True)
        # create the output directory
        try:
            mkdir(str(self.downf.text()))
            print((" INFO: Preparing Directory " + str(self.downf.text())))
        except:
            print((" INFO: Preparing Directory " + str(self.downf.text())))
        # parse local system architecture
        architecturez = "x86_64" if "64bit" in architecture()[0] else "i686"
        print((" INFO: System Architecture is " + architecturez))
        # parse remote blender filename
        blenderfile = [
            a.strip().lower().replace('<td><a href="', "").replace("</a></td>", "").split('">')[0]
            for a in urlopen("http://builder.blender.org/download/").readlines()[40:80]
            if '<td><a href="blender-' in a and sub("[^a-z]", "", str(sys.platform).lower()) in a and architecturez in a
        ][0]
        print((" INFO: System OS is " + sys.platform))
        print((" INFO: Blender Remote Filename is " + blenderfile))
        if path.isfile(path.join(str(self.downf.text()), blenderfile)):
            print((" INFO: Blender Local Filename is " + blenderfile))
            print(" INFO: Local and Remote Files are similar, Skiping Download")
        else:
            print(" INFO: Local and Remote Files differ, Requesting Download")
            print((" INFO: URL is builder.blender.org/download/" + blenderfile))
            # get the file
            downloader = Downloader(
                self.mainwidget, "http://builder.blender.org/download/" + blenderfile, str(self.downf.text())
            )
            downloader.show()

    ###########################################################################

    def paintEvent(self, event):
        "Paint semi-transparent background, animated pattern, background text"
        # because we are on 2012 !, its time to showcase how Qt we are !
        QWidget.paintEvent(self, event)
        # make a painter
        p = QPainter(self)
        p.setRenderHint(QPainter.TextAntialiasing)
        p.setRenderHint(QPainter.HighQualityAntialiasing)
        # fill a rectangle with transparent painting
        p.fillRect(event.rect(), Qt.transparent)
        # animated random dots background pattern
        for i in range(8192):
            x = randint(9, self.size().width() - 9)
            y = randint(9, self.size().height() - 9)
            p.setPen(QPen(QColor(randint(9, 255), randint(9, 255), 255), 1))
            p.drawPoint(x, y)
        # set pen to use white color
        p.setPen(QPen(QColor(randint(9, 255), randint(9, 255), 255), 1))
        # Rotate painter 45 Degree
        p.rotate(30)
        # Set painter Font for text
        p.setFont(QFont("Ubuntu", 200))
        # draw the background text, with antialiasing
        p.drawText(99, 99, "Blender")
        # Rotate -45 the QPen back !
        p.rotate(-30)
        # set the pen to no pen
        p.setPen(Qt.NoPen)
        # Background Color
        p.setBrush(QColor(0, 0, 0))
        # Background Opacity
        p.setOpacity(0.75)
        # Background Rounded Borders
        p.drawRoundedRect(self.rect(), 50, 50)
        # finalize the painter
        p.end()

    def seTitle(self):
        " set the title of the main window "
        dialog = QDialog(self)
        textEditInput = QLineEdit(" Type Title Here ")
        ok = QPushButton(" O K ")
        ok.clicked.connect(lambda: self.setWindowTitle(textEditInput.text()))
        ly = QVBoxLayout()
        [ly.addWidget(wdgt) for wdgt in (QLabel("Title:"), textEditInput, ok)]
        dialog.setLayout(ly)
        dialog.exec_()

    def timedate(self):
        " get the time and date "
        dialog = QDialog(self)
        clock = QLCDNumber()
        clock.setNumDigits(24)
        timer = QTimer()
        timer.timeout.connect(lambda: clock.display(datetime.now().strftime("%d-%m-%Y %H:%M:%S %p")))
        timer.start(1000)
        clock.setToolTip(datetime.now().strftime("%c %x"))
        ok = QPushButton(" O K ")
        ok.clicked.connect(dialog.close)
        ly = QVBoxLayout()
        [ly.addWidget(wdgt) for wdgt in (QCalendarWidget(), clock, ok)]
        dialog.setLayout(ly)
        dialog.exec_()

    def closeEvent(self, event):
        " Ask to Quit "
        if (
            QMessageBox.question(self, " Close ", " Quit ? ", QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
            == QMessageBox.Yes
        ):
            event.accept()
        else:
            event.ignore()

    def center(self):
        " Center and resize the window "
        self.resize(
            QDesktopWidget().screenGeometry().width() // 1.25, QDesktopWidget().screenGeometry().height() // 1.25
        )
        qr = self.frameGeometry()
        qr.moveCenter(QDesktopWidget().availableGeometry().center())
        self.move(qr.topLeft())
Пример #9
0
class SearchWidget(QFrame):
    """Widget, appeared, when Ctrl+F pressed.
    Has different forms for different search modes
    """

    Normal = 'normal'
    Good = 'good'
    Bad = 'bad'
    Incorrect = 'incorrect'

    visibilityChanged = pyqtSignal(bool)
    """
    visibilityChanged(visible)
    
    **Signal** emitted, when widget has been shown or hidden
    """  # pylint: disable=W0105

    searchInDirectoryStartPressed = pyqtSignal(type(re.compile('')), list,
                                               unicode)
    """
    searchInDirectoryStartPressed(regEx, mask, path)
    
    **Signal** emitted, when 'search in directory' button had been pressed
    """  # pylint: disable=W0105

    searchInDirectoryStopPressed = pyqtSignal()
    """
    searchInDirectoryStopPressed()
    
    **Signal** emitted, when 'stop search in directory' button had been pressed
    """  # pylint: disable=W0105

    replaceCheckedStartPressed = pyqtSignal(unicode)
    """
    replaceCheckedStartPressed(replText)
    
    **Signal** emitted, when 'replace checked' button had been pressed
    """  # pylint: disable=W0105

    replaceCheckedStopPressed = pyqtSignal()
    """
    replaceCheckedStartPressed()
    
    **Signal** emitted, when 'stop replacing checked' button had been pressed
    """  # pylint: disable=W0105

    searchRegExpChanged = pyqtSignal(type(re.compile('')))
    """
    searchRegExpValidStateChanged(regEx)
    
    **Signal** emitted, when search regexp has been changed.
    If reg exp is invalid - regEx object contains empty pattern
    """  # pylint: disable=W0105

    searchNext = pyqtSignal()
    """
    searchNext()
    
    **Signal** emitted, when 'Search Next' had been pressed
    """  # pylint: disable=W0105

    searchPrevious = pyqtSignal()
    """
    searchPrevious()
    
    **Signal** emitted, when 'Search Previous' had been pressed
    """  # pylint: disable=W0105

    replaceFileOne = pyqtSignal(unicode)
    """
    replaceFileOne(replText)
    
    **Signal** emitted, when 'Replace' had been pressed
    """  # pylint: disable=W0105

    replaceFileAll = pyqtSignal(unicode)
    """
    replaceFileAll(replText)
    
    **Signal** emitted, when 'Replace All' had been pressed
    """  # pylint: disable=W0105

    def __init__(self, plugin):
        QFrame.__init__(self, core.workspace())
        self._mode = None
        self.plugin = plugin
        from PyQt4 import uic  # lazy import for better startup performance
        uic.loadUi(os.path.join(os.path.dirname(__file__), 'SearchWidget.ui'),
                   self)

        self.cbSearch.setCompleter(None)
        self.cbReplace.setCompleter(None)
        self.cbMask.setCompleter(None)

        self.fsModel = QDirModel(self.cbPath.lineEdit())
        self.fsModel.setFilter(QDir.AllDirs | QDir.NoDotAndDotDot)
        self.cbPath.lineEdit().setCompleter(
            QCompleter(self.fsModel, self.cbPath.lineEdit()))
        # TODO QDirModel is deprecated but QCompleter does not yet handle
        # QFileSystemodel - please update when possible."""
        self.cbSearch.setCompleter(None)
        self.pbSearchStop.setVisible(False)
        self.pbReplaceCheckedStop.setVisible(False)

        self._progress = QProgressBar(self)
        self._progress.setAlignment(Qt.AlignCenter)
        self._progress.setToolTip(self.tr("Search in progress..."))
        self._progress.setMaximumSize(QSize(80, 16))
        core.mainWindow().statusBar().insertPermanentWidget(1, self._progress)
        self._progress.setVisible(False)

        # cd up action
        self.tbCdUp = QToolButton(self.cbPath.lineEdit())
        self.tbCdUp.setIcon(QIcon(":/enkiicons/go-up.png"))
        self.tbCdUp.setCursor(Qt.ArrowCursor)
        self.tbCdUp.installEventFilter(self)  # for drawing button

        self.cbSearch.installEventFilter(
            self)  # for catching Tab and Shift+Tab
        self.cbReplace.installEventFilter(
            self)  # for catching Tab and Shift+Tab
        self.cbPath.installEventFilter(self)  # for catching Tab and Shift+Tab
        self.cbMask.installEventFilter(self)  # for catching Tab and Shift+Tab

        self._closeShortcut = QShortcut(QKeySequence("Esc"), self)
        self._closeShortcut.setContext(Qt.WidgetWithChildrenShortcut)
        self._closeShortcut.activated.connect(self.hide)

        # connections
        self.cbSearch.lineEdit().textChanged.connect(
            self._onSearchRegExpChanged)

        self.cbSearch.lineEdit().returnPressed.connect(self._onReturnPressed)
        self.cbReplace.lineEdit().returnPressed.connect(self._onReturnPressed)
        self.cbPath.lineEdit().returnPressed.connect(self._onReturnPressed)
        self.cbMask.lineEdit().returnPressed.connect(self._onReturnPressed)

        self.cbRegularExpression.stateChanged.connect(
            self._onSearchRegExpChanged)
        self.cbCaseSensitive.stateChanged.connect(self._onSearchRegExpChanged)
        self.cbWholeWord.stateChanged.connect(self._onSearchRegExpChanged)

        self.tbCdUp.clicked.connect(self._onCdUpPressed)

        self.pbNext.pressed.connect(self.searchNext)
        self.pbPrevious.pressed.connect(self.searchPrevious)
        self.pbSearchStop.pressed.connect(self.searchInDirectoryStopPressed)
        self.pbReplaceCheckedStop.pressed.connect(
            self.replaceCheckedStopPressed)

        core.mainWindow().hideAllWindows.connect(self.hide)
        core.workspace().escPressed.connect(self.hide)

        core.workspace().currentDocumentChanged.connect( \
                    lambda old, new: self.setVisible(self.isVisible() and new is not None))

    def show(self):
        """Reimplemented function. Sends signal
        """
        super(SearchWidget, self).show()
        self.visibilityChanged.emit(self.isVisible())

    def hide(self):
        """Reimplemented function.
        Sends signal, returns focus to workspace
        """
        super(SearchWidget, self).hide()
        core.workspace().focusCurrentDocument()
        self.visibilityChanged.emit(self.isVisible())

    def setVisible(self, visible):
        """Reimplemented function. Sends signal
        """
        super(SearchWidget, self).setVisible(visible)
        self.visibilityChanged.emit(self.isVisible())

    def _regExEscape(self, text):
        """Improved version of re.escape()
        Doesn't escape space, comma, underscore.
        Escapes \n and \t
        """
        text = re.escape(text)
        # re.escape escapes space, comma, underscore, but, it is not necessary and makes text not readable
        for symbol in (' ,_=\'"/:@#%&'):
            text = text.replace('\\' + symbol, symbol)

        text = text.replace('\\\n', '\\n')
        text = text.replace('\\\t', '\\t')

        return text

    def _makeEscapeSeqsVisible(self, text):
        """Replace invisible \n and \t with escape sequences
        """
        text = text.replace('\\', '\\\\')
        text = text.replace('\t', '\\t')
        text = text.replace('\n', '\\n')
        return text

    def setMode(self, mode):
        """Change search mode.
        i.e. from "Search file" to "Replace directory"
        """
        if self._mode == mode and self.isVisible():
            if core.workspace().currentDocument() is not None and \
               not core.workspace().currentDocument().hasFocus():
                self.cbSearch.lineEdit().selectAll()
                self.cbSearch.setFocus()

        self._mode = mode

        # Set Search and Replace text
        document = core.workspace().currentDocument()
        if document is not None and \
           document.hasFocus() and \
           document.qutepart.selectedText:
            searchText = document.qutepart.selectedText

            self.cbReplace.setEditText(self._makeEscapeSeqsVisible(searchText))

            if self.cbRegularExpression.checkState() == Qt.Checked:
                searchText = self._regExEscape(searchText)
            self.cbSearch.setEditText(searchText)

        if not self.cbReplace.lineEdit().text() and \
            self.cbSearch.lineEdit().text() and \
            not self.cbRegularExpression.checkState() == Qt.Checked:
            replaceText = self.cbSearch.lineEdit().text().replace('\\', '\\\\')
            self.cbReplace.setEditText(replaceText)

        # Move focus to Search edit
        self.cbSearch.setFocus()
        self.cbSearch.lineEdit().selectAll()

        # Set search path
        if mode & MODE_FLAG_DIRECTORY and \
           not (self.isVisible() and self.cbPath.isVisible()):
            try:
                searchPath = os.path.abspath(unicode(os.path.curdir))
                self.cbPath.setEditText(searchPath)
            except OSError:  # current directory might have been deleted
                pass

        # Set widgets visibility flag according to state
        widgets = (self.wSearch, self.pbPrevious, self.pbNext, self.pbSearch, self.wReplace, self.wPath, \
                   self.pbReplace, self.pbReplaceAll, self.pbReplaceChecked, self.wOptions, self.wMask)
        #                         wSear  pbPrev pbNext pbSear wRepl  wPath  pbRep  pbRAll pbRCHK wOpti wMask
        visible = \
        {MODE_SEARCH :               (1,     1,     1,     0,     0,     0,     0,     1,     1,    1,    0,),
         MODE_REPLACE:               (1,     1,     1,     0,     1,     0,     1,     1,     0,    1,    0,),
         MODE_SEARCH_DIRECTORY:      (1,     0,     0,     1,     0,     1,     0,     0,     0,    1,    1,),
         MODE_REPLACE_DIRECTORY:     (1,     0,     0,     1,     1,     1,     0,     0,     1,    1,    1,),
         MODE_SEARCH_OPENED_FILES:   (1,     0,     0,     1,     0,     0,     0,     0,     0,    1,    1,),
         MODE_REPLACE_OPENED_FILES:  (1,     0,     0,     1,     1,     0,     0,     0,     1,    1,    1,)}

        for i, widget in enumerate(widgets):
            widget.setVisible(visible[mode][i])

        # Search next button text
        if mode == MODE_REPLACE:
            self.pbNext.setText('Next')
        else:
            self.pbNext.setText(u'Next↵')

        # Finaly show all with valid size
        self.show()  # show before updating widgets and labels
        self._updateLabels()
        self._updateWidgets()

    def eventFilter(self, object_, event):
        """ Event filter for mode switch tool button
        Draws icons in the search and path lineEdits
        """
        if event.type(
        ) == QEvent.Paint and object_ is self.tbCdUp:  # draw CdUp button in search path QLineEdit
            toolButton = object_
            lineEdit = self.cbPath.lineEdit()
            lineEdit.setContentsMargins(lineEdit.height(), 0, 0, 0)

            height = lineEdit.height()
            availableRect = QRect(0, 0, height, height)

            if toolButton.rect() != availableRect:
                toolButton.setGeometry(availableRect)

            painter = QPainter(toolButton)
            toolButton.icon().paint(painter, availableRect)

            return True

        elif event.type(
        ) == QEvent.KeyPress:  # Tab and Shift+Tab in QLineEdits

            if event.key() == Qt.Key_Tab:
                self._moveFocus(1)
                return True
            elif event.key() == Qt.Key_Backtab:
                self._moveFocus(-1)
                return True

        return QFrame.eventFilter(self, object_, event)

    def _onReturnPressed(self):
        """Return or Enter pressed on widget.
        Search next or Replace next
        """
        if self.pbReplace.isVisible():
            self.pbReplace.click()
        elif self.pbNext.isVisible():
            self.pbNext.click()
        elif self.pbSearch.isVisible():
            self.pbSearch.click()
        elif self.pbSearchStop.isVisible():
            self.pbSearchStop.click()

    def _moveFocus(self, step):
        """Move focus forward or backward according to step.
        Standard Qt Keyboard focus algorithm doesn't allow circular navigation
        """
        allFocusableWidgets = (self.cbSearch, self.cbReplace, self.cbPath,
                               self.cbMask)
        visibleWidgets = [widget for widget in allFocusableWidgets \
                                    if widget.isVisible()]

        try:
            focusedIndex = visibleWidgets.index(QApplication.focusWidget())
        except ValueError:
            print >> sys.stderr, 'Invalid focused widget in Search Widget'
            return

        nextFocusedIndex = (focusedIndex + step) % len(visibleWidgets)

        visibleWidgets[nextFocusedIndex].setFocus()
        visibleWidgets[nextFocusedIndex].lineEdit().selectAll()

    def _updateLabels(self):
        """Update 'Search' 'Replace' 'Path' labels geometry
        """
        width = 0

        if self.lSearch.isVisible():
            width = max(width, self.lSearch.minimumSizeHint().width())

        if self.lReplace.isVisible():
            width = max(width, self.lReplace.minimumSizeHint().width())

        if self.lPath.isVisible():
            width = max(width, self.lPath.minimumSizeHint().width())

        self.lSearch.setMinimumWidth(width)
        self.lReplace.setMinimumWidth(width)
        self.lPath.setMinimumWidth(width)

    def _updateWidgets(self):
        """Update geometry of widgets with buttons
        """
        width = 0

        if self.wSearchRight.isVisible():
            width = max(width, self.wSearchRight.minimumSizeHint().width())

        if self.wReplaceRight.isVisible():
            width = max(width, self.wReplaceRight.minimumSizeHint().width())

        if self.wPathRight.isVisible():
            width = max(width, self.wPathRight.minimumSizeHint().width())

        self.wSearchRight.setMinimumWidth(width)
        self.wReplaceRight.setMinimumWidth(width)
        self.wPathRight.setMinimumWidth(width)

    def updateComboBoxes(self):
        """Update comboboxes with last used texts
        """
        searchText = self.cbSearch.currentText()
        replaceText = self.cbReplace.currentText()
        maskText = self.cbMask.currentText()

        # search
        if searchText:
            index = self.cbSearch.findText(searchText)

            if index == -1:
                self.cbSearch.addItem(searchText)

        # replace
        if replaceText:
            index = self.cbReplace.findText(replaceText)

            if index == -1:
                self.cbReplace.addItem(replaceText)

        # mask
        if maskText:
            index = self.cbMask.findText(maskText)

            if index == -1:
                self.cbMask.addItem(maskText)

    def _searchPatternTextAndFlags(self):
        """Get search pattern and flags
        """
        pattern = self.cbSearch.currentText()

        pattern = pattern.replace(
            u'\u2029',
            '\n')  # replace unicode paragraph separator with habitual \n

        if not self.cbRegularExpression.checkState() == Qt.Checked:
            pattern = re.escape(pattern)

        if self.cbWholeWord.checkState() == Qt.Checked:
            pattern = r'\b' + pattern + r'\b'

        flags = 0
        if not self.cbCaseSensitive.checkState() == Qt.Checked:
            flags = re.IGNORECASE
        return pattern, flags

    def getRegExp(self):
        """Read search parameters from controls and present it as a regular expression
        """
        pattern, flags = self._searchPatternTextAndFlags()
        return re.compile(pattern, flags)

    def isSearchRegExpValid(self):
        """Try to compile search pattern to check if it is valid
        Returns bool result and text error
        """
        pattern, flags = self._searchPatternTextAndFlags()
        try:
            re.compile(pattern, flags)
        except re.error, ex:
            return False, unicode(ex)

        return True, None
Пример #10
0
class DiffGUI(object):
    ' diff gui class '
    def __init__(self):
        ' make a diff method with GUI '
        self.dialog = QDialog()
        self.diff_path = None

        # directory auto completer
        self.completer = QCompleter(self.dialog)
        self.dirs = QDirModel(self.dialog)
        self.dirs.setFilter(QDir.AllEntries | QDir.NoDotAndDotDot)
        self.completer.setModel(self.dirs)
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.setCompletionMode(QCompleter.PopupCompletion)

        self.group1 = QGroupBox()
        self.group1.setTitle('Diff')
        self.frmt = QComboBox(self.group1)
        self.frmt.addItems(['Unified', 'Normal', 'Context'])
        self.file1 = QLineEdit()
        self.file1.setPlaceholderText('/full/path/to/one_file.py')
        self.file1.setCompleter(self.completer)
        self.file2 = QLineEdit()
        self.file2.setPlaceholderText('/full/path/to/another_file.py')
        self.file2.setCompleter(self.completer)
        self.fout = QLineEdit()
        self.fout.setText(''.join((path.join(gettempdir(),
                     datetime.now().strftime('%d-%b-%Y_%H:%M:%S.diff')))))
        self.fout.setPlaceholderText('/full/path/to/output_file.diff')
        self.fout.setCompleter(self.completer)
        self.regex = QLineEdit()
        self.regex.setPlaceholderText('DONT use unless you know what are doing')
        self.regex.setToolTip('Do NOT use unless you know what you are doing !')
        self.borig = QPushButton(QIcon.fromTheme("folder-open"), 'Open')
        self.borig.clicked.connect(lambda: self.file1.setText(str(
            QFileDialog.getOpenFileName(self.dialog, 'Open file to compare',
                                           path.expanduser("~"), ';;(*.*)'))))

        self.bmodi = QPushButton(QIcon.fromTheme("folder-open"), 'Open')
        self.bmodi.clicked.connect(lambda: self.file2.setText(str(
            QFileDialog.getOpenFileName(self.dialog, 'Open file to compare',
                                           path.expanduser("~"), ';;(*.*)'))))
        self.bout = QPushButton(QIcon.fromTheme("folder-open"), 'Open')
        self.bout.clicked.connect(lambda: self.fout.setText(str(
            QFileDialog.getSaveFileName(self.dialog, 'Save a Diff file',
                                        path.expanduser("~"), ';;(*.diff)'))))
        vboxg1 = QVBoxLayout(self.group1)
        for each_widget in (QLabel('Original file full path'),
                            self.file1, self.borig,
                            QLabel('Modified file full path'),
                            self.file2, self.bmodi,
                            QLabel('Output file full Path'),
                            self.fout, self.bout,
                            QLabel('Diff Output Format'), self.frmt,
                            QLabel('Diff REGEX to Ignore (ADVANCED)'),
                            self.regex):
            vboxg1.addWidget(each_widget)

        self.group2 = QGroupBox()
        self.group2.setTitle('Options')
        self.nwfl = QCheckBox('Treat new files as Empty')
        self.smll = QCheckBox('Look for smaller changes')
        self.lrgf = QCheckBox('Optimize for large files')
        self.case = QCheckBox('Ignore case changes on content')
        self.cnvt = QCheckBox('Convert Tabs to Spaces')
        self.blnk = QCheckBox('Ignore added or removed Blank lines')
        self.spac = QCheckBox('Ignore changes in amount of Spaces')
        self.whit = QCheckBox('Ignore ALL white Spaces')
        self.tabz = QCheckBox('Ignore changes by Tab expansions')
        self.sprs = QCheckBox('Remove Space or Tab before empty lines')
        self.filn = QCheckBox('Ignore case when comparing file names')
        self.tbs = QComboBox(self.group2)
        self.tbs.addItems(['4', '6', '8', '10', '2'])
        self.nice = QComboBox(self.group2)
        self.nice.addItems(['20', '15', '10', '5', '0'])
        vboxg2 = QVBoxLayout(self.group2)
        for each_widget in (self.nwfl, self.smll, self.lrgf, self.case,
                            self.cnvt, self.blnk, self.spac, self.whit,
                            self.tabz, self.sprs, self.filn,
                            QLabel('Diff Tabs-to-Spaces Size'), self.tbs,
                            QLabel('Diff Backend CPU Priority'), self.nice):
            vboxg2.addWidget(each_widget)
            try:
                each_widget.setToolTip(each_widget.text())
            except:
                each_widget.setToolTip(each_widget.currentText())
            each_widget.setCursor(QCursor(Qt.PointingHandCursor))

        group3 = QGroupBox()
        group3.setTitle('Even More Options')
        self.plai = QCheckBox('Force treat all files as plain text')
        self.nocr = QCheckBox('Force strip trailing carriage return')
        self.ridt = QCheckBox('Report when two files are identical')
        self.nocm = QCheckBox('Do not output common lines')
        self.rdif = QCheckBox('Report only when files differ')
        self.clip = QCheckBox('Copy Diff to Clipboard when done')
        self.noti = QCheckBox('Use system Notification when done')
        self.pret = QCheckBox('Align all Tabs by prepending a Tab')
        self.lolz = QCheckBox('Output Diff in two equal columns')
        self.odif = QCheckBox('Open Diff with Ninja-IDE when done')
        self.plac = QCheckBox('Make an Awesome Diff view when done')
        self.wdth = QComboBox(group3)
        self.wdth.addItems(['80', '100', '120', '130', '250', '500', '9999999'])
        self.bcknd = QComboBox(group3)
        self.bcknd.addItems(['diff', 'diff.py'])
        self.bcknd.setDisabled(True)  # TODO this feature needs work
        vboxg3 = QVBoxLayout(group3)
        for each_widget in (self.plai, self.nocr, self.ridt, self.nocm,
                            self.rdif, self.pret, self.clip, self.noti,
                            self.lolz, self.odif, self.plac,
                            QLabel('Diff Maximum Total Width'), self.wdth,
                            QLabel('Diff Backend (EXPERIMENTAL)'), self.bcknd):
            vboxg3.addWidget(each_widget)
            try:
                each_widget.setToolTip(each_widget.text())
            except:
                each_widget.setToolTip(each_widget.currentText())
            each_widget.setCursor(QCursor(Qt.PointingHandCursor))

        for widget_should_be_checked in (self.nwfl, self.smll, self.lrgf,
                                   self.clip, self.cnvt, self.plai, self.noti):
            widget_should_be_checked.setChecked(True)

        container = QWidget()
        hbox = QHBoxLayout(container)
        for each_widget in (self.group2, self.group1, group3):
            hbox.addWidget(each_widget)

        buttons = QDialogButtonBox()
        buttons.resize(self.dialog.size().width(), buttons.size().height() * 2)
        buttons.setOrientation(Qt.Horizontal)
        buttons.setStandardButtons(
            QDialogButtonBox.Ok |
            QDialogButtonBox.Cancel |
            QDialogButtonBox.Close |
            QDialogButtonBox.Help)
        buttons.setCenterButtons(False)
        buttons.helpRequested.connect(lambda: QMessageBox.about(
            self.dialog, __doc__,
            ''.join((__doc__, ' GUI and Visualizer Plugin,', linesep,
            'version ', __version__, ', (', __license__, '), by ', linesep,
            __author__, ', ( ', __email__, ' ).', linesep))))
        buttons.rejected.connect(self.dialog.close)
        buttons.accepted.connect(self.make_diff)

        info = QLabel(''.join(('<b> Current Backend Diff Engine: </b>',
                      getoutput('diff --version').split(linesep)[0])))

        vbox = QVBoxLayout(self.dialog)
        for each_widget in (
                QLabel('<center><h2> Ninja IDE Diff and Patch </h2></center>'),
                container, info, buttons):
            vbox.addWidget(each_widget)

        self.dialog.resize(1024, self.dialog.size().height())
        self.dialog.exec_()

    def make_diff(self):
        ' make the diff '
        diff_command = ''.join((
        'nice --adjustment=', str(self.nice.currentText()).strip(), ' ',
        str(self.bcknd.currentText()).strip(), ' --',
        str(self.frmt.currentText()).strip().lower(),

        ' --new-file ' if self.nwfl.isChecked() is True else '',
        ' --minimal ' if self.smll.isChecked() is True else '',
        ' --speed-large-files ' if self.lrgf.isChecked() is True else '',
        ' --ignore-self.case ' if self.case.isChecked() is True else '',
        ' --expand-tabs ' if self.cnvt.isChecked() is True else '',
        ' --ignore-blank-lines ' if self.blnk.isChecked() is True else '',
        ' --ignore-space-change ' if self.spac.isChecked() is True else '',
        ' --ignore-all-space ' if self.whit.isChecked() is True else '',
        ' --ignore-tab-expansion ' if self.tabz.isChecked() is True else '',
        ' --suppress-blank-empty ' if self.sprs.isChecked() is True else '',
        ' --ignore-file-name-case ' if self.filn.isChecked() is True else '',
        ' --text ' if self.plai.isChecked() is True else '',
        ' --strip-trailing-cr ' if self.nocr.isChecked() is True else '',
        ' --suppress-common-lines ' if self.nocm.isChecked() is True else '',
        ' --initial-tab ' if self.pret.isChecked() is True else '',
        ' --side-by-side ' if self.lolz.isChecked() is True else '',

        ' --tabsize=', str(self.tbs.currentText()).strip(),
        ' --width=', str(self.wdth.currentText()).strip(),

        str(' --ignore-matching-lines=' + str(self.regex.text()).strip())
                           if str(self.regex.text()).strip() is not '' else '',
        ' ',
        path.abspath(str(self.file1.text()))
                    if str(self.file1.text()).strip() is not '' else __file__,
        ' ',
        path.abspath(str(self.file2.text()))
                    if str(self.file2.text()).strip() is not '' else __file__
        ))

        print(diff_command)
        diff_output = getoutput(diff_command)
        try:
            print(' INFO: OK, Saving new Diff to disk...')
            output_file = file(path.abspath(str(self.fout.text())), 'w')
            output_file.write(diff_output)
            output_file.close()
        except:
            print(' ERROR: FAIL, Can not save Diff to disk!')
        if self.clip.isChecked() is True:
            print(' INFO: OK, Diff Copied to Clipboard...')
            QApplication.clipboard().setText(diff_output)
        if self.noti.isChecked() is True:
            call('notify-send [Ninja-IDE] ¡Diff_is_Ready!', shell=True)
        if self.odif.isChecked() is True:
            print(' INFO: OK, Opening Diff with Ninja-IDE')
            call('ninja-ide ' + path.abspath(str(self.fout.text())), shell=True)

        self.diff_path = path.abspath(str(self.fout.text()))
        return self.diff_path
Пример #11
0
class ComboBox(QComboBox):
    """File browser combo box.
    Widget and functionality
    """
    def __init__(self, fileBrowser):
        QComboBox.__init__(self, fileBrowser)

        self._fileBrowser = fileBrowser

        self.setAttribute( Qt.WA_MacShowFocusRect, False )
        self.setAttribute( Qt.WA_MacSmallSize )
        self.setEditable(True)
        self.setMinimumContentsLength(1)
        self.setSizeAdjustPolicy(QComboBox.AdjustToMinimumContentsLengthWithIcon)
        self.lineEdit().setReadOnly( False )
        self._completionModel = QDirModel(self.lineEdit())
        self._completionModel.setFilter( QDir.AllDirs | QDir.NoDotAndDotDot )
        self.lineEdit().setCompleter(QCompleter(self._completionModel,
                                               self.lineEdit()))
        #TODO QDirModel is deprecated but QCompleter does not yet handle
        #QFileSystemModel - please update when possible.
        self._count = 0

        # Show popup action
        self._showPopupAction = QAction(QIcon(':enkiicons/filtered.png'), "File browser history", self)
        self._showPopupAction.setShortcut('Ctrl+H')
        core.actionManager().addAction("mNavigation/mFileBrowser/aMenuShow", self._showPopupAction)
        self._showPopupAction.triggered.connect(self._onShowPopup)

        # reconnected in self.updateComboItems()
        self.currentIndexChanged[int].connect(self._onItemSelected)

    def del_(self):
        """Explicitly called destructor
        """
        core.actionManager().removeAction(self._showPopupAction)

    def _onShowPopup(self, triggered):
        """Handler for self._showPopupAction
        """
        self.showPopup()

    @pyqtSlot(int)
    def _onItemSelected(self, index):
        """Handler of item selection in the combo box
        """
        if self.count() > self._count:  # It is user input
            path = self.itemText(index)
            if os.path.isdir(path):
                self._fileBrowser.setCurrentPath(path)
        else:
            path = self.itemData(index)
            self._fileBrowser.setCurrentPath(path)

    def updateItems(self, items):
        """Update items in the combo box according to current history
        """
        self.currentIndexChanged[int].disconnect()
        self.clear()
        # Current text
        self.addItem(self._fileBrowser.currentPath())
        self.setItemData(0, self._fileBrowser.currentPath())
        self.insertSeparator(self.count())

        for index, path in enumerate(items):
            self.addItem(path)
            self.setItemData(index + 2, path)
        self._count = self.count()
        self.currentIndexChanged[int].connect(self._onItemSelected)
class MyMainWindow(QMainWindow):
    " Main Window "

    def __init__(self, parent=None):
        " Initialize QWidget inside MyMainWindow "
        super(MyMainWindow, self).__init__(parent)
        QWidget.__init__(self)
        self.statusBar().showMessage("               {}".format(__doc__))
        self.setStyleSheet("QStatusBar{color:grey;}")
        self.setWindowTitle(__doc__)
        self.setWindowIcon(QIcon.fromTheme("face-monkey"))
        self.setFont(QFont("Ubuntu Light", 10))
        self.setMaximumSize(QDesktopWidget().screenGeometry().width(), QDesktopWidget().screenGeometry().height())

        # directory auto completer
        self.completer = QCompleter(self)
        self.dirs = QDirModel(self)
        self.dirs.setFilter(QDir.AllEntries | QDir.NoDotAndDotDot)
        self.completer.setModel(self.dirs)
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.setCompletionMode(QCompleter.PopupCompletion)

        # Proxy support, by reading http_proxy os env variable
        proxy_url = QUrl(environ.get("http_proxy", ""))
        QNetworkProxy.setApplicationProxy(
            QNetworkProxy(
                QNetworkProxy.HttpProxy if str(proxy_url.scheme()).startswith("http") else QNetworkProxy.Socks5Proxy,
                proxy_url.host(),
                proxy_url.port(),
                proxy_url.userName(),
                proxy_url.password(),
            )
        ) if "http_proxy" in environ else None
        print((" INFO: Proxy Auto-Config as " + str(proxy_url)))

        # basic widgets layouts and set up
        self.mainwidget = QTabWidget()
        self.mainwidget.setToolTip(__doc__)
        self.mainwidget.setContextMenuPolicy(Qt.CustomContextMenu)
        self.mainwidget.tabCloseRequested.connect(lambda: self.mainwidget.setTabPosition(randint(0, 3)))
        # if self.mainwidget.tabPosition() == 0
        # else self.mainwidget.setTabPosition(0))
        self.mainwidget.setStyleSheet("QTabBar{color:white;font-weight:bold;}")
        self.mainwidget.setTabBar(TabBar(self))
        self.mainwidget.setMovable(True)
        self.mainwidget.setTabsClosable(True)
        self.mainwidget.setTabShape(QTabWidget.Triangular)
        self.setCentralWidget(self.mainwidget)
        self.dock1 = QDockWidget()
        self.dock2 = QDockWidget()
        self.dock3 = QDockWidget()
        for a in (self.dock1, self.dock2, self.dock3):
            a.setWindowModality(Qt.NonModal)
            a.setWindowOpacity(0.9)
            a.setWindowTitle(__doc__ if a.windowTitle() == "" else a.windowTitle())
            a.setStyleSheet(" QDockWidget::title{text-align:center;}")
            self.mainwidget.addTab(a, QIcon.fromTheme("face-smile"), "Double Click Me")

        # Paleta de colores para pintar transparente
        self.palette().setBrush(QPalette.Base, Qt.transparent)
        self.setPalette(self.palette())
        self.setAttribute(Qt.WA_OpaquePaintEvent, False)

        # toolbar and basic actions
        self.toolbar = QToolBar(self)
        self.toolbar.setIconSize(QSize(24, 24))
        # spacer widget for left
        self.left_spacer = QWidget(self)
        self.left_spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        # spacer widget for right
        self.right_spacer = QWidget(self)
        self.right_spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        qaqq = QAction(QIcon.fromTheme("application-exit"), "Quit", self)
        qaqq.setShortcut("Ctrl+Q")
        qaqq.triggered.connect(exit)
        qamin = QAction(QIcon.fromTheme("go-down"), "Minimize", self)
        qamin.triggered.connect(lambda: self.showMinimized())
        qamax = QAction(QIcon.fromTheme("go-up"), "Maximize", self)
        qanor = QAction(QIcon.fromTheme("view-fullscreen"), "AutoCenter AutoResize", self)
        qanor.triggered.connect(self.center)
        qatim = QAction(QIcon.fromTheme("mail-signed-verified"), "View Date and Time", self)
        qatim.triggered.connect(self.timedate)
        qabug = QAction(QIcon.fromTheme("help-about"), "Report a Problem", self)
        qabug.triggered.connect(
            lambda: qabug.setDisabled(True)
            if not call("xdg-open mailto:" + "*****@*****.**".decode("rot13"), shell=True)
            else " ERROR "
        )
        qamax.triggered.connect(lambda: self.showMaximized())
        qaqt = QAction(QIcon.fromTheme("help-about"), "About Qt", self)
        qaqt.triggered.connect(lambda: QMessageBox.aboutQt(self))
        qakde = QAction(QIcon.fromTheme("help-about"), "About KDE", self)
        if KDE:
            qakde.triggered.connect(KHelpMenu(self, "", False).aboutKDE)
        qaslf = QAction(QIcon.fromTheme("help-about"), "About Self", self)
        if KDE:
            qaslf.triggered.connect(KAboutApplicationDialog(aboutData, self).exec_)
        else:
            qaslf.triggered.connect(
                lambda: QMessageBox.about(
                    self.mainwidget,
                    __doc__,
                    "".join(
                        (
                            __doc__,
                            linesep,
                            "version ",
                            __version__,
                            ", (",
                            __license__,
                            "), by ",
                            __author__,
                            ", ( ",
                            __email__,
                            " )",
                            linesep,
                        )
                    ),
                )
            )
        qafnt = QAction(QIcon.fromTheme("tools-check-spelling"), "Set GUI Font", self)
        if KDE:
            font = QFont()
            qafnt.triggered.connect(
                lambda: self.setStyleSheet(
                    "".join(("*{font-family:", str(font.toString()), "}"))
                    if KFontDialog.getFont(font)[0] == QDialog.Accepted
                    else ""
                )
            )
        else:
            qafnt.triggered.connect(
                lambda: self.setStyleSheet("".join(("*{font-family:", str(QFontDialog.getFont()[0].toString()), "}")))
            )
        qasrc = QAction(QIcon.fromTheme("applications-development"), "View Source Code", self)
        qasrc.triggered.connect(lambda: call("xdg-open {}".format(__file__), 1))
        qakb = QAction(QIcon.fromTheme("input-keyboard"), "Keyboard Shortcuts", self)
        qakb.triggered.connect(
            lambda: QMessageBox.information(self.mainwidget, "Keyboard Shortcuts", " Ctrl+Q = Quit ")
        )
        qapic = QAction(QIcon.fromTheme("camera-photo"), "Take a Screenshot", self)
        qapic.triggered.connect(
            lambda: QPixmap.grabWindow(QApplication.desktop().winId()).save(
                QFileDialog.getSaveFileName(
                    self.mainwidget, " Save Screenshot As ...", path.expanduser("~"), ";;(*.png) PNG", "png"
                )
            )
        )
        qatb = QAction(QIcon.fromTheme("go-top"), "Toggle ToolBar", self)
        qatb.triggered.connect(lambda: self.toolbar.hide() if self.toolbar.isVisible() is True else self.toolbar.show())
        qati = QAction(QIcon.fromTheme("help-browser"), "Switch ToolBar Icon Size", self)
        qati.triggered.connect(
            lambda: self.toolbar.setIconSize(self.toolbar.iconSize() * 4)
            if self.toolbar.iconSize().width() * 4 == 24
            else self.toolbar.setIconSize(self.toolbar.iconSize() / 4)
        )
        qasb = QAction(QIcon.fromTheme("zoom-in"), "Toggle Tabs Bar", self)
        qasb.triggered.connect(
            lambda: self.mainwidget.tabBar().hide()
            if self.mainwidget.tabBar().isVisible() is True
            else self.mainwidget.tabBar().show()
        )
        qadoc = QAction(QIcon.fromTheme("help-browser"), "On-line Docs", self)
        qadoc.triggered.connect(lambda: open_new_tab(__url__))
        qapy = QAction(QIcon.fromTheme("help-about"), "About Python", self)
        qapy.triggered.connect(lambda: open_new_tab("http://python.org/about"))
        qali = QAction(QIcon.fromTheme("help-browser"), "Read Licence", self)
        qali.triggered.connect(lambda: open_new_tab(__full_licence__))
        qacol = QAction(QIcon.fromTheme("preferences-system"), "Set GUI Colors", self)
        if KDE:
            color = QColor()
            qacol.triggered.connect(
                lambda: self.setStyleSheet("".join(("* { background-color: ", str(color.name()), "}")))
                if KColorDialog.getColor(color, self)
                else ""
            )
        else:
            qacol.triggered.connect(
                lambda: self.setStyleSheet(
                    "".join((" * { background-color: ", str(QColorDialog.getColor().name()), " } "))
                )
            )
        qatit = QAction(QIcon.fromTheme("preferences-system"), "Set the App Window Title", self)
        qatit.triggered.connect(self.seTitle)
        self.toolbar.addWidget(self.left_spacer)
        self.toolbar.addSeparator()
        for b in (
            qaqq,
            qamin,
            qanor,
            qamax,
            qasrc,
            qakb,
            qacol,
            qatim,
            qatb,
            qafnt,
            qati,
            qasb,
            qatit,
            qapic,
            qadoc,
            qali,
            qaslf,
            qaqt,
            qakde,
            qapy,
            qabug,
        ):
            self.toolbar.addAction(b)
        self.addToolBar(Qt.TopToolBarArea, self.toolbar)
        self.toolbar.addSeparator()
        self.toolbar.addWidget(self.right_spacer)
        # define the menu
        menu = self.menuBar()
        # File menu items
        menu.addMenu("&File").addActions((qaqq,))
        menu.addMenu("&Window").addActions((qamax, qanor, qamin))
        # Settings menu
        menu.addMenu("&Settings").addActions((qasrc, qacol, qafnt, qatim, qatb, qati, qasb, qapic))
        # Help menu items
        menu.addMenu("&Help").addActions((qadoc, qakb, qabug, qali, qaqt, qakde, qapy, qaslf))
        # Tray Icon
        tray = QSystemTrayIcon(QIcon.fromTheme("face-devilish"), self)
        tray.setToolTip(__doc__)
        traymenu = QMenu()
        traymenu.addActions((qamax, qanor, qamin, qaqq))
        tray.setContextMenu(traymenu)
        tray.show()

        def contextMenuRequested(point):
            " quick and dirty custom context menu "
            menu = QMenu()
            menu.addActions(
                (
                    qaqq,
                    qamin,
                    qanor,
                    qamax,
                    qasrc,
                    qakb,
                    qacol,
                    qafnt,
                    qati,
                    qasb,
                    qatb,
                    qatim,
                    qatit,
                    qapic,
                    qadoc,
                    qali,
                    qaslf,
                    qaqt,
                    qakde,
                    qapy,
                    qabug,
                )
            )
            menu.exec_(self.mapToGlobal(point))

        self.mainwidget.customContextMenuRequested.connect(contextMenuRequested)

        def must_be_checked(widget_list):
            " widget tuple passed as argument should be checked as ON "
            for each_widget in widget_list:
                try:
                    each_widget.setChecked(True)
                except:
                    pass

        def must_have_tooltip(widget_list):
            " widget tuple passed as argument should have tooltips "
            for each_widget in widget_list:
                try:
                    each_widget.setToolTip(each_widget.text())
                except:
                    each_widget.setToolTip(each_widget.currentText())
                finally:
                    each_widget.setCursor(QCursor(Qt.PointingHandCursor))

        def must_autofillbackground(widget_list):
            " widget tuple passed as argument should have filled background "
            for each_widget in widget_list:
                try:
                    each_widget.setAutoFillBackground(True)
                except:
                    pass

        def must_glow(widget_list):
            " apply an glow effect to the widget "
            for glow, each_widget in enumerate(widget_list):
                try:
                    if each_widget.graphicsEffect() is None:
                        glow = QGraphicsDropShadowEffect(self)
                        glow.setOffset(0)
                        glow.setBlurRadius(99)
                        glow.setColor(QColor(99, 255, 255))
                        each_widget.setGraphicsEffect(glow)
                        # glow.setEnabled(False)
                        try:
                            each_widget.clicked.connect(
                                lambda: each_widget.graphicsEffect().setEnabled(True)
                                if each_widget.graphicsEffect().isEnabled() is False
                                else each_widget.graphicsEffect().setEnabled(False)
                            )
                        except:
                            each_widget.sliderPressed.connect(
                                lambda: each_widget.graphicsEffect().setEnabled(True)
                                if each_widget.graphicsEffect().isEnabled() is False
                                else each_widget.graphicsEffect().setEnabled(False)
                            )
                except:
                    pass

        #######################################################################

        self.group1 = QGroupBox()
        self.group1.setTitle(__doc__)
        self.frmt = QComboBox(self.group1)
        self.frmt.addItems(["blah ", "blah blah", "blah blah blah"])
        self.file1 = QLineEdit()
        self.file1.setPlaceholderText("/full/path/to/one_file.py")
        self.file1.setCompleter(self.completer)
        self.borig = QPushButton(QIcon.fromTheme("folder-open"), "Open")
        vboxg1 = QVBoxLayout(self.group1)
        for each_widget in (
            QLabel('<b style="color:white;">some comment'),
            self.file1,
            self.borig,
            QLabel('<b style="color:white;">Lorem Impsum'),
            self.frmt,
        ):
            vboxg1.addWidget(each_widget)

        self.group2 = QGroupBox()
        self.group2.setTitle(__doc__)
        self.nwfl = QCheckBox("Be Awesome")
        self.smll = QCheckBox("Solve the Squaring of the Circle")
        self.lrgf = QCheckBox("Im just a QCheckBox")
        self.case = QCheckBox("Use Quantum Processing")
        vboxg2 = QVBoxLayout(self.group2)
        for each_widget in (self.nwfl, self.smll, self.lrgf, self.case):
            vboxg2.addWidget(each_widget)

        group3 = QGroupBox()
        group3.setTitle(__doc__)
        self.plai = QCheckBox("May the Force be with You")
        self.nocr = QCheckBox("Im just a Place Holder")
        self.ridt = QCheckBox("Lorem Impsum")
        self.nocm = QCheckBox("Divide by Zero")
        vboxg3 = QVBoxLayout(group3)
        for each_widget in (self.plai, self.nocr, self.ridt, self.nocm):
            vboxg3.addWidget(each_widget)
        container = QWidget()
        hbox = QHBoxLayout(container)
        for each_widget in (self.group2, self.group1, group3):
            hbox.addWidget(each_widget)
        self.dock1.setWidget(container)

        # dock 2
        self.dock2.setWidget(QPlainTextEdit())

        # dock 3
        self.dock3.setWidget(QCalendarWidget())

        # configure some widget settings
        must_be_checked((self.nwfl, self.smll, self.lrgf, self.plai))
        must_have_tooltip((self.plai, self.nocr, self.ridt, self.nocm, self.nwfl, self.smll, self.lrgf, self.case))
        must_autofillbackground(
            (self.plai, self.nocr, self.ridt, self.nocm, self.nwfl, self.smll, self.lrgf, self.case)
        )
        must_glow((self.plai, self.nocr, self.ridt, self.nocm, self.nwfl))

    def run(self):
        " run forest run "
        print((" INFO: Working at {}".format(str(datetime.datetime.now()))))

    ###########################################################################

    def paintEvent(self, event):
        "Paint semi-transparent background, animated pattern, background text"
        # because we are on 2012 !, its time to showcase how Qt we are !
        QWidget.paintEvent(self, event)
        # make a painter
        p = QPainter(self)
        p.setRenderHint(QPainter.TextAntialiasing)
        p.setRenderHint(QPainter.HighQualityAntialiasing)
        # fill a rectangle with transparent painting
        p.fillRect(event.rect(), Qt.transparent)
        # animated random dots background pattern
        for i in range(4096):
            x = randint(9, self.size().width() - 9)
            y = randint(9, self.size().height() - 9)
            p.setPen(QPen(QColor(randint(9, 255), randint(9, 255), 255), 1))
            p.drawPoint(x, y)
        # set pen to use white color
        p.setPen(QPen(QColor(randint(9, 255), randint(9, 255), 255), 1))
        # Rotate painter 45 Degree
        p.rotate(30)
        # Set painter Font for text
        p.setFont(QFont("Ubuntu", 200))
        # draw the background text, with antialiasing
        if KDE:
            p.drawText(99, 99, "PyKDE")
        else:
            p.drawText(99, 99, "PyQt")
        # Rotate -45 the QPen back !
        p.rotate(-30)
        # set the pen to no pen
        p.setPen(Qt.NoPen)
        # Background Color
        p.setBrush(QColor(0, 0, 0))
        # Background Opacity
        p.setOpacity(0.75)
        # Background Rounded Borders
        p.drawRoundedRect(self.rect(), 50, 50)
        # finalize the painter
        p.end()

    def seTitle(self):
        " set the title of the main window "
        dialog = QDialog(self)
        textEditInput = QLineEdit(" Type Title Here ")
        ok = QPushButton(" O K ")
        ok.clicked.connect(lambda: self.setWindowTitle(textEditInput.text()))
        ly = QVBoxLayout()
        [ly.addWidget(wdgt) for wdgt in (QLabel("Title:"), textEditInput, ok)]
        dialog.setLayout(ly)
        dialog.exec_()

    def timedate(self):
        " get the time and date "
        dialog = QDialog(self)
        clock = QLCDNumber()
        clock.setNumDigits(24)
        timer = QTimer()
        timer.timeout.connect(lambda: clock.display(datetime.now().strftime("%d-%m-%Y %H:%M:%S %p")))
        timer.start(1000)
        clock.setToolTip(datetime.now().strftime("%c %x"))
        ok = QPushButton(" O K ")
        ok.clicked.connect(dialog.close)
        ly = QVBoxLayout()
        [ly.addWidget(wdgt) for wdgt in (QCalendarWidget(), clock, ok)]
        dialog.setLayout(ly)
        dialog.exec_()

    def closeEvent(self, event):
        " Ask to Quit "
        if (
            QMessageBox.question(self, " Close ", " Quit ? ", QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
            == QMessageBox.Yes
        ):
            event.accept()
        else:
            event.ignore()

    def center(self):
        " Center and resize the window "
        self.showNormal()
        self.resize(
            QDesktopWidget().screenGeometry().width() // 1.25, QDesktopWidget().screenGeometry().height() // 1.25
        )
        qr = self.frameGeometry()
        qr.moveCenter(QDesktopWidget().availableGeometry().center())
        self.move(qr.topLeft())

    def nepomuk_set(self, file_tag=None, __tag="", _label="", _description=""):
        " Quick and Easy Nepomuk Taggify for Files "
        print(
            (
                """ INFO: Semantic Desktop Experience is Tagging Files :
              {}, {}, {}, {})""".format(
                    file_tag, __tag, _label, _description
                )
            )
        )
        if Nepomuk.ResourceManager.instance().init() is 0:
            fle = Nepomuk.Resource(KUrl(QFileInfo(file_tag).absoluteFilePath()))
            _tag = Nepomuk.Tag(__tag)
            _tag.setLabel(_label)
            fle.addTag(_tag)
            fle.setDescription(_description)
            print(([str(a.label()) for a in fle.tags()], fle.description()))
            return ([str(a.label()) for a in fle.tags()], fle.description())
        else:
            print(" ERROR: FAIL: Nepomuk is not running ! ")
            return

    def nepomuk_get(self, query_to_search):
        " Quick and Easy Nepomuk Query for Files "
        print(
            (
                """ INFO: Semantic Desktop Experience is Quering Files :
              {} """.format(
                    query_to_search
                )
            )
        )
        results = []
        nepo = Nepomuk.Query.QueryServiceClient()
        nepo.desktopQuery("hasTag:{}".format(query_to_search))

        def _query(data):
            """ ('filename.ext', 'file description', ['list', 'of', 'tags']) """
            results.append(
                (
                    [str(a.resource().genericLabel()) for a in data][0],
                    [str(a.resource().description()) for a in data][0],
                    [str(a.label()) for a in iter([a.resource().tags() for a in data][0])],
                )
            )

        nepo.newEntries.connect(_query)

        def _end():
            """
            [  ('filename.ext', 'file description', ['list', 'of', 'tags']),
               ('filename.ext', 'file description', ['list', 'of', 'tags']),
               ('filename.ext', 'file description', ['list', 'of', 'tags'])  ]
            """
            nepo.newEntries.disconnect
            print(results)
            return results

        nepo.finishedListing.connect(_end)

    def kio_get(self, url_string):
        " multi-threaded, multi-protocol, resumable, error-checked download "
        downloader_thread = KIO.storedGet(KUrl(str(url_string).strip()))

        def kio_job_data_or_error(job):
            " retrieve job data or job error "
            print((job.data() if not job.error() else job.error()))
            return job.data() if not job.error() else job.error()

        downloader_thread.result.connect(kio_job_data_or_error)
class MyMainWindow(QMainWindow):
    ' Main Window '
    def __init__(self, AUTO):
        ' Initialize QWidget inside MyMainWindow '
        super(MyMainWindow, self).__init__()
        QWidget.__init__(self)
        self.auto = AUTO
        self.statusBar().showMessage('               {}'.format(__doc__))
        self.setStyleSheet('QStatusBar{color:grey;}')
        self.setWindowTitle(__doc__)
        self.setWindowIcon(QIcon.fromTheme("face-monkey"))
        self.setFont(QFont('Ubuntu Light', 10))
        self.setMaximumSize(QDesktopWidget().screenGeometry().width(),
                            QDesktopWidget().screenGeometry().height())

        self.base = path.abspath(path.join(getcwd(), str(datetime.now().year)))

        # directory auto completer
        self.completer = QCompleter(self)
        self.dirs = QDirModel(self)
        self.dirs.setFilter(QDir.AllEntries | QDir.NoDotAndDotDot)
        self.completer.setModel(self.dirs)
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.setCompletionMode(QCompleter.PopupCompletion)

        # process
        self.process1 = None
        self.process2 = None
        self.cmd1 = 'nice -n {n} arecord{v} -f {f} -c {c} -r {b} -t raw'
        self.cmd2 = 'oggenc - -r -C {c} -R {b} -q {q} {d}{t}{a} -o {o}'
        self.process3 = QProcess(self)
        #self.process3.finished.connect(self.on_process3_finished)
        #self.process3.error.connect(self.on_process3_error)

        self.cmd3 = ('nice -n 20 ' +
          'sox "{o}" -n spectrogram -x {x} -y {y} -z 99 -t "{o}" -o "{o}.png"')
        self.actual_file = ''

        # re starting timers, one stops, one starts
        self.timerFirst = QTimer(self)
        self.timerFirst.timeout.connect(self.end)
        self.timerSecond = QTimer(self)
        self.timerSecond.timeout.connect(self.run)

        # Proxy support, by reading http_proxy os env variable
        proxy_url = QUrl(environ.get('http_proxy', ''))
        QNetworkProxy.setApplicationProxy(QNetworkProxy(QNetworkProxy.HttpProxy
            if str(proxy_url.scheme()).startswith('http')
            else QNetworkProxy.Socks5Proxy, proxy_url.host(), proxy_url.port(),
                 proxy_url.userName(), proxy_url.password())) \
            if 'http_proxy' in environ else None
        print((' INFO: Proxy Auto-Config as ' + str(proxy_url)))

        # basic widgets layouts and set up
        self.mainwidget = QTabWidget()
        self.mainwidget.setToolTip(__doc__)
        self.mainwidget.setMovable(True)
        self.mainwidget.setTabShape(QTabWidget.Triangular)
        self.mainwidget.setContextMenuPolicy(Qt.CustomContextMenu)
        self.mainwidget.setStyleSheet('QTabBar{color:white;font-weight:bold;}')
        self.mainwidget.setTabBar(TabBar(self))
        self.mainwidget.setTabsClosable(False)
        self.setCentralWidget(self.mainwidget)
        self.dock1 = QDockWidget()
        self.dock2 = QDockWidget()
        self.dock3 = QDockWidget()
        self.dock4 = QDockWidget()
        self.dock5 = QDockWidget()
        for a in (self.dock1, self.dock2, self.dock3, self.dock4, self.dock5):
            a.setWindowModality(Qt.NonModal)
            # a.setWindowOpacity(0.9)
            a.setWindowTitle(__doc__
                             if a.windowTitle() == '' else a.windowTitle())
            a.setStyleSheet('QDockWidget::title{text-align:center;}')
            self.mainwidget.addTab(a, QIcon.fromTheme("face-smile"),
                                   'Double Click Me')

        # Paleta de colores para pintar transparente
        self.palette().setBrush(QPalette.Base, Qt.transparent)
        self.setPalette(self.palette())
        self.setAttribute(Qt.WA_OpaquePaintEvent, False)

        # toolbar and basic actions
        self.toolbar = QToolBar(self)
        self.toolbar.setIconSize(QSize(24, 24))
        # spacer widget for left
        self.left_spacer = QWidget(self)
        self.left_spacer.setSizePolicy(QSizePolicy.Expanding,
                                       QSizePolicy.Expanding)
        # spacer widget for right
        self.right_spacer = QWidget(self)
        self.right_spacer.setSizePolicy(QSizePolicy.Expanding,
                                        QSizePolicy.Expanding)
        qaqq = QAction(QIcon.fromTheme("application-exit"), 'Quit', self)
        qaqq.setShortcut('Ctrl+Q')
        qaqq.triggered.connect(exit)
        qamin = QAction(QIcon.fromTheme("go-down"), 'Minimize', self)
        qamin.triggered.connect(lambda: self.showMinimized())
        qamax = QAction(QIcon.fromTheme("go-up"), 'Maximize', self)
        qanor = QAction(QIcon.fromTheme("view-fullscreen"),
                        'AutoCenter AutoResize', self)
        qanor.triggered.connect(self.center)
        qatim = QAction(QIcon.fromTheme("mail-signed-verified"),
                        'View Date and Time', self)
        qatim.triggered.connect(self.timedate)
        qabug = QAction(QIcon.fromTheme("help-about"), 'Report a Problem', self)
        qabug.triggered.connect(lambda: qabug.setDisabled(True) if not call(
            'xdg-open mailto:' + '*****@*****.**'.decode('rot13'),
            shell=True) else ' ERROR ')
        qamax.triggered.connect(lambda: self.showMaximized())
        qaqt = QAction(QIcon.fromTheme("help-about"), 'About Qt', self)
        qaqt.triggered.connect(lambda: QMessageBox.aboutQt(self))
        qakde = QAction(QIcon.fromTheme("help-about"), 'About KDE', self)
        if KDE:
            qakde.triggered.connect(KHelpMenu(self, "", False).aboutKDE)
        qaslf = QAction(QIcon.fromTheme("help-about"), 'About Self', self)
        if KDE:
            qaslf.triggered.connect(
                                KAboutApplicationDialog(aboutData, self).exec_)
        else:
            qaslf.triggered.connect(lambda: QMessageBox.about(self.mainwidget,
            __doc__, ''.join((__doc__, linesep, 'version ', __version__, ', (',
            __license__, '), by ', __author__, ', ( ', __email__, ' )', linesep
            ))))
        qafnt = QAction(QIcon.fromTheme("tools-check-spelling"),
                        'Set GUI Font', self)
        if KDE:
            font = QFont()
            qafnt.triggered.connect(lambda:
            self.setStyleSheet(''.join((
                '*{font-family:', str(font.toString()), '}'))
                if KFontDialog.getFont(font)[0] == QDialog.Accepted else ''))
        else:
            qafnt.triggered.connect(lambda:
                self.setStyleSheet(''.join(('*{font-family:',
                            str(QFontDialog.getFont()[0].toString()), '}'))))
        qasrc = QAction(QIcon.fromTheme("applications-development"),
                        'View Source Code', self)
        qasrc.triggered.connect(lambda:
                            call('xdg-open {}'.format(__file__), shell=True))
        qakb = QAction(QIcon.fromTheme("input-keyboard"),
                       'Keyboard Shortcuts', self)
        qakb.triggered.connect(lambda: QMessageBox.information(self.mainwidget,
                               'Keyboard Shortcuts', ' Ctrl+Q = Quit '))
        qapic = QAction(QIcon.fromTheme("camera-photo"),
                        'Take a Screenshot', self)
        qapic.triggered.connect(lambda: QPixmap.grabWindow(
            QApplication.desktop().winId()).save(QFileDialog.getSaveFileName(
            self.mainwidget, " Save Screenshot As ...", path.expanduser("~"),
            ';;(*.png) PNG', 'png')))
        qatb = QAction(QIcon.fromTheme("go-top"), 'Toggle ToolBar', self)
        qatb.triggered.connect(lambda: self.toolbar.hide()
                if self.toolbar.isVisible() is True else self.toolbar.show())
        qati = QAction(QIcon.fromTheme("zoom-in"),
                       'Switch ToolBar Icon Size', self)
        qati.triggered.connect(lambda:
            self.toolbar.setIconSize(self.toolbar.iconSize() * 4)
            if self.toolbar.iconSize().width() * 4 == 24
            else self.toolbar.setIconSize(self.toolbar.iconSize() / 4))
        qasb = QAction(QIcon.fromTheme("preferences-other"),
                       'Toggle Tabs Bar', self)
        qasb.triggered.connect(lambda: self.mainwidget.tabBar().hide()
                               if self.mainwidget.tabBar().isVisible() is True
                               else self.mainwidget.tabBar().show())
        qadoc = QAction(QIcon.fromTheme("help-browser"), 'On-line Docs', self)
        qadoc.triggered.connect(lambda: open_new_tab(str(__url__).strip()))
        qapy = QAction(QIcon.fromTheme("help-about"), 'About Python', self)
        qapy.triggered.connect(lambda: open_new_tab('http://python.org/about'))
        qali = QAction(QIcon.fromTheme("help-browser"), 'Read Licence', self)
        qali.triggered.connect(lambda: open_new_tab(__full_licence__))
        qacol = QAction(QIcon.fromTheme("preferences-system"), 'Set GUI Colors',
                        self)
        if KDE:
            color = QColor()
            qacol.triggered.connect(lambda:
                self.setStyleSheet(''.join(('* { background-color: ',
                                            str(color.name()), '}')))
                if KColorDialog.getColor(color, self) else '')
        else:
            qacol.triggered.connect(lambda: self.setStyleSheet(''.join((
                ' * { background-color: ', str(QColorDialog.getColor().name()),
                ' } '))))
        qatit = QAction(QIcon.fromTheme("preferences-system"),
                        'Set the App Window Title', self)
        qatit.triggered.connect(self.seTitle)
        self.toolbar.addWidget(self.left_spacer)
        self.toolbar.addSeparator()
        self.toolbar.addActions((qaqq, qamin, qanor, qamax, qasrc, qakb, qacol,
            qatim, qatb, qafnt, qati, qasb, qatit, qapic, qadoc, qali, qaslf,
            qaqt, qakde, qapy, qabug))
        self.addToolBar(Qt.TopToolBarArea, self.toolbar)
        self.toolbar.addSeparator()
        self.toolbar.addWidget(self.right_spacer)
        # define the menu
        menu = self.menuBar()
        # File menu items
        menu.addMenu('&File').addActions((qaqq, ))
        menu.addMenu('&Window').addActions((qamax, qanor, qamin))
        # Settings menu
        menu.addMenu('&Settings').addActions((qasrc, qacol, qafnt, qatim,
                                              qatb, qati, qasb, qapic))
        # Help menu items
        menu.addMenu('&Help').addActions((qadoc, qakb, qabug, qali,
                                          qaqt, qakde, qapy, qaslf))
        # Tray Icon
        tray = QSystemTrayIcon(QIcon.fromTheme("face-devilish"), self)
        tray.setToolTip(__doc__)
        traymenu = QMenu()
        traymenu.addActions((qamax, qanor, qamin, qaqq))
        tray.setContextMenu(traymenu)
        tray.show()

        def contextMenuRequested(point):
            ' quick and dirty custom context menu '
            menu = QMenu()
            menu.addActions((qaqq, qamin, qanor, qamax, qasrc, qakb, qacol,
                qafnt, qati, qasb, qatb, qatim, qatit, qapic, qadoc, qali,
                qaslf, qaqt, qakde, qapy, qabug))
            menu.exec_(self.mapToGlobal(point))
        self.mainwidget.customContextMenuRequested.connect(contextMenuRequested)

        def must_be_checked(widget_list):
            ' widget tuple passed as argument should be checked as ON '
            for each_widget in widget_list:
                try:
                    each_widget.setChecked(True)
                except:
                    pass

        def must_have_tooltip(widget_list):
            ' widget tuple passed as argument should have tooltips '
            for each_widget in widget_list:
                try:
                    each_widget.setToolTip(each_widget.text())
                except:
                    each_widget.setToolTip(each_widget.currentText())
                finally:
                    each_widget.setCursor(QCursor(Qt.PointingHandCursor))

        def must_autofillbackground(widget_list):
            ' widget tuple passed as argument should have filled background '
            for each_widget in widget_list:
                try:
                    each_widget.setAutoFillBackground(True)
                except:
                    pass

        def must_glow(widget_list):
            ' apply an glow effect to the widget '
            for glow, each_widget in enumerate(widget_list):
                try:
                    if each_widget.graphicsEffect() is None:
                        glow = QGraphicsDropShadowEffect(self)
                        glow.setOffset(0)
                        glow.setBlurRadius(99)
                        glow.setColor(QColor(99, 255, 255))
                        each_widget.setGraphicsEffect(glow)
                        # glow.setEnabled(False)
                        try:
                            each_widget.clicked.connect(lambda:
                            each_widget.graphicsEffect().setEnabled(True)
                            if each_widget.graphicsEffect().isEnabled() is False
                            else each_widget.graphicsEffect().setEnabled(False))
                        except:
                            each_widget.sliderPressed.connect(lambda:
                            each_widget.graphicsEffect().setEnabled(True)
                            if each_widget.graphicsEffect().isEnabled() is False
                            else each_widget.graphicsEffect().setEnabled(False))
                except:
                    pass

        #######################################################################

        # dock 1
        QLabel('<h1 style="color:white;"> Record !</h1>', self.dock1).resize(
               self.dock3.size().width() / 4, 25)
        self.group1 = QGroupBox()
        self.group1.setTitle(__doc__)

        self.spec = QPushButton(self)
        self.spec.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.spec.setMinimumSize(self.spec.size().width(), 250)
        self.spec.setFlat(True)
        self.spec.clicked.connect(self.spectro)

        self.clock = QLCDNumber()
        self.clock.setSegmentStyle(QLCDNumber.Flat)
        self.clock.setMinimumSize(self.clock.size().width(), 50)
        self.clock.setNumDigits(25)
        self.timer1 = QTimer(self)
        self.timer1.timeout.connect(lambda: self.clock.display(
            datetime.now().strftime("%d-%m-%Y %H:%M:%S %p")))
        self.timer1.start(1000)
        self.clock.setToolTip(datetime.now().strftime("%c %x"))
        self.clock.setCursor(QCursor(Qt.CrossCursor))

        self.diskBar = QProgressBar()
        self.diskBar.setMinimum(0)
        self.diskBar.setMaximum(statvfs(HOME).f_blocks *
            statvfs(HOME).f_frsize / 1024 / 1024 / 1024)
        self.diskBar.setValue(statvfs(HOME).f_bfree *
            statvfs(HOME).f_frsize / 1024 / 1024 / 1024)
        self.diskBar.setToolTip(str(statvfs(HOME).f_bfree *
            statvfs(HOME).f_frsize / 1024 / 1024 / 1024) + ' Gigabytes free')

        self.feedback = QPlainTextEdit(''.join(('<center><h3>', __doc__,
            ', version', __version__, __license__, ' <br> by ', __author__,
            ' <i>(Dev)</i>, Radio Comunitaria FM Reconquista <i>(Q.A.)</i><br>',
            'FMReconquista.org.ar & GitHub.com/JuanCarlosPaco/Cinta-Testigo')))

        self.rec = QPushButton(QIcon.fromTheme("media-record"), 'Record')
        self.rec.setMinimumSize(self.rec.size().width(), 50)
        self.rec.clicked.connect(self.go)  # self.run

        self.stop = QPushButton(QIcon.fromTheme("media-playback-stop"), 'Stop')
        self.stop.clicked.connect(self.end)

        self.kill = QPushButton(QIcon.fromTheme("process-stop"), 'Kill')
        self.kill.clicked.connect(self.killer)

        vboxg1 = QVBoxLayout(self.group1)
        for each_widget in (
            QLabel('<b style="color:white;"> Spectro'), self.spec,
            QLabel('<b style="color:white;"> Time '), self.clock,
            QLabel('<b style="color:white;"> Disk '), self.diskBar,
            QLabel('<b style="color:white;"> STDOUT + STDIN '), self.feedback,
            QLabel('<b style="color:white;"> Record '), self.rec, self.stop,
            self.kill):
            vboxg1.addWidget(each_widget)

        self.group2 = QGroupBox()
        self.group2.setTitle(__doc__)

        self.slider = QSlider(self)
        self.slid_l = QLabel(self.slider)
        self.slider.setCursor(QCursor(Qt.OpenHandCursor))
        self.slider.sliderPressed.connect(lambda:
                            self.slider.setCursor(QCursor(Qt.ClosedHandCursor)))
        self.slider.sliderReleased.connect(lambda:
                            self.slider.setCursor(QCursor(Qt.OpenHandCursor)))
        self.slider.valueChanged.connect(lambda:
                            self.slider.setToolTip(str(self.slider.value())))
        self.slider.valueChanged.connect(lambda: self.slid_l.setText(
                    '<h2 style="color:white;">{}'.format(self.slider.value())))
        self.slider.setMinimum(10)
        self.slider.setMaximum(99)
        self.slider.setValue(30)
        self.slider.setOrientation(Qt.Vertical)
        self.slider.setTickPosition(QSlider.TicksBothSides)
        self.slider.setTickInterval(2)
        self.slider.setSingleStep(10)
        self.slider.setPageStep(10)

        vboxg2 = QVBoxLayout(self.group2)
        for each_widget in (
            QLabel('<b style="color:white;">MINUTES of recording'), self.slider,
            QLabel('<b style="color:white;"> Default: 30 Min')):
            vboxg2.addWidget(each_widget)

        group3 = QGroupBox()
        group3.setTitle(__doc__)
        try:
            self.label2 = QLabel(getoutput('sox --version', shell=True))
            self.label4 = QLabel(getoutput('arecord --version', shell=1)[:25])
            self.label6 = QLabel(str(getoutput('oggenc --version', shell=True)))
        except:
            print(''' ERROR: No SOX, OGGenc avaliable !
                  ( sudo apt-get install vorbis-tools sox alsa-utils ) ''')
            exit()

        self.button5 = QPushButton(QIcon.fromTheme("audio-x-generic"),
                                   'OGG --> ZIP')
        self.button5.clicked.connect(lambda: make_archive(
            str(QFileDialog.getSaveFileName(self, "Save OGG to ZIP file As...",
            getcwd(), ';;(*.zip)', 'zip')).replace('.zip', ''), "zip",
            path.abspath(path.join(getcwd(), str(datetime.now().year)))))

        self.button1 = QPushButton(QIcon.fromTheme("folder-open"), 'Files')
        self.button1.clicked.connect(lambda:
                                     call('xdg-open ' + getcwd(), shell=True))

        self.button0 = QPushButton(
            QIcon.fromTheme("preferences-desktop-screensaver"), 'LCD OFF')
        self.button0.clicked.connect(lambda:
            call('sleep 3 ; xset dpms force off', shell=True))

        vboxg3 = QVBoxLayout(group3)
        for each_widget in (
            QLabel('<b style="color:white;"> OGG Output Codec '), self.label6,
            QLabel('<b style="color:white;"> Raw Record Backend '), self.label4,
            QLabel('<b style="color:white;"> Helper Libs '), self.label2,
            QLabel('<b style="color:white;"> OGG ZIP '), self.button5,
            QLabel('<b style="color:white;"> Files '), self.button1,
            QLabel('<b style="color:white;"> LCD '), self.button0):
            vboxg3.addWidget(each_widget)
        container = QWidget()
        hbox = QHBoxLayout(container)
        for each_widget in (self.group2, self.group1, group3):
            hbox.addWidget(each_widget)
        self.dock1.setWidget(container)

        # dock 2
        QLabel('<h1 style="color:white;"> Hardware !</h1>', self.dock2).resize(
               self.dock2.size().width() / 4, 25)
        try:
            audioDriverStr = {Solid.AudioInterface.Alsa: "ALSA",
                Solid.AudioInterface.OpenSoundSystem: "Open Sound",
                Solid.AudioInterface.UnknownAudioDriver: "Unknown?"}
            audioInterfaceTypeStr = {
                Solid.AudioInterface.AudioControl: "Control",
                Solid.AudioInterface.UnknownAudioInterfaceType: "Unknown?",
                Solid.AudioInterface.AudioInput: "In",
                Solid.AudioInterface.AudioOutput: "Out"}
            soundcardTypeStr = {
                Solid.AudioInterface.InternalSoundcard: "Internal",
                Solid.AudioInterface.UsbSoundcard: "USB3",
                Solid.AudioInterface.FirewireSoundcard: "FireWire",
                Solid.AudioInterface.Headset: "Headsets",
                Solid.AudioInterface.Modem: "Modem"}
            display = QTreeWidget()
            display.setAlternatingRowColors(True)
            display.setHeaderLabels(["Items", "ID", "Drivers", "I / O", "Type"])
            display.setColumnWidth(0, 350)
            display.setColumnWidth(1, 350)
            display.setColumnWidth(3, 75)
            # retrieve a list of Solid.Device for this machine
            deviceList = Solid.Device.allDevices()
            # filter the list of all devices and display matching results
            # note that we never create a Solid.AudioInterface object, but
            # receive one from the 'asDeviceInterface' call
            for device in deviceList:
                if device.isDeviceInterface(
                                         Solid.DeviceInterface.AudioInterface):
                    audio = device.asDeviceInterface(
                            Solid.DeviceInterface.AudioInterface)
                    devtype = audio.deviceType()
                    devstr = []
                    for key in audioInterfaceTypeStr:
                        flag = key & devtype
                        if flag:
                            devstr.append(audioInterfaceTypeStr[key])
                    QTreeWidgetItem(display, [device.product(), audio.name(),
                        audioDriverStr[audio.driver()], "/".join(devstr),
                        soundcardTypeStr[audio.soundcardType()]])
            self.dock2.setWidget(display)
        except:
            self.dock2.setWidget(QLabel(""" <center style='color:white;'>
            <h1>:(<br>ERROR: Please, install PyKDE !</h1><br>
            <br><i> (Sorry, can not use non-Qt Libs). Thanks </i><center>"""))

        ## dock 3
        QLabel('<h1 style="color:white;"> Previews !</h1>', self.dock3).resize(
               self.dock3.size().width() / 4, 25)
        self.fileView = QColumnView()
        self.fileView.updatePreviewWidget.connect(self.play)
        self.fileView.setToolTip(' Browse and Preview Files ')
        self.media = None
        self.model = QDirModel()
        self.fileView.setModel(self.model)
        self.dock3.setWidget(self.fileView)

        # dock4
        QLabel('<h1 style="color:white;"> Setup !</h1>', self.dock4).resize(
               self.dock4.size().width() / 4, 25)
        self.group4 = QGroupBox()
        self.group4.setTitle(__doc__)

        self.combo0 = QComboBox()
        self.combo0.addItems(['S16_LE', 'S32_LE', 'S16_BE', 'U16_LE', 'U16_BE',
          'S24_LE', 'S24_BE', 'U24_LE', 'U24_BE', 'S32_BE', 'U32_LE', 'U32_BE'])

        self.combo1 = QComboBox()
        self.combo1.addItems(['1', '-1', '0', '2', '3', '4',
                              '5', '6', '7', '8', '9', '10'])

        self.combo2 = QComboBox()
        self.combo2.addItems(['128', '256', '512', '1024', '64', '32', '16'])

        self.combo3 = QComboBox(self)
        self.combo3.addItems(['MONO', 'STEREO', 'Surround'])

        self.combo4 = QComboBox()
        self.combo4.addItems(['44100', '96000', '48000', '32000',
                              '22050', '16000', '11025', '8000'])

        self.combo5 = QComboBox(self)
        self.combo5.addItems(['20', '19', '18', '17', '16', '15', '14', '13',
            '12', '10', '9', '8', '7', '6', '5', '4', '3', '2', '1', '0'])

        self.nepochoose = QCheckBox('Auto-Tag Files using Nepomuk Semantic')

        self.chckbx0 = QCheckBox('Disable Software based Volume Control')

        self.chckbx1 = QCheckBox('Output Sound Stereo-to-Mono Downmix')

        self.chckbx2 = QCheckBox('Add Date and Time MetaData to Sound files')

        self.chckbx3 = QCheckBox('Add Yourself as the Author Artist of Sound')

        vboxg4 = QVBoxLayout(self.group4)
        for each_widget in (
            QLabel('<b style="color:white;"> Sound OGG Quality'), self.combo1,
            QLabel('<b style="color:white;"> Sound Record Format'), self.combo0,
            QLabel('<b style="color:white;"> Sound KBps '), self.combo2,
            QLabel('<b style="color:white;"> Sound Channels '), self.combo3,
            QLabel('<b style="color:white;"> Sound Sample Rate '), self.combo4,
            QLabel('<b style="color:white;"> Sound Volume'), self.chckbx0,
            QLabel('<b style="color:white;"> Sound Mix'), self.chckbx1,
            QLabel('<b style="color:white;"> Sound Meta'), self.chckbx2,
            QLabel('<b style="color:white;"> Sound Authorship'), self.chckbx3,
            QLabel('<b style="color:white;"> CPUs Priority'), self.combo5,
            QLabel('<b style="color:white;">Nepomuk Semantic User Experience'),
            self.nepochoose):
            vboxg4.addWidget(each_widget)
        self.dock4.setWidget(self.group4)

        # dock 5
        QLabel('<h1 style="color:white;"> Voice Changer ! </h1>', self.dock5
               ).resize(self.dock5.size().width() / 3, 25)
        self.group5 = QGroupBox()
        self.group5.setTitle(__doc__)

        self.dial = QDial()
        self.dial.setCursor(QCursor(Qt.OpenHandCursor))
        self.di_l = QLabel(self.dial)
        self.di_l.resize(self.dial.size() / 8)
        self.dial.sliderPressed.connect(lambda:
                            self.dial.setCursor(QCursor(Qt.ClosedHandCursor)))
        self.dial.sliderReleased.connect(lambda:
                            self.dial.setCursor(QCursor(Qt.OpenHandCursor)))
        self.dial.valueChanged.connect(lambda:
                            self.dial.setToolTip(str(self.dial.value())))
        self.dial.valueChanged.connect(lambda: self.di_l.setText(
                    '<h1 style="color:white;">{}'.format(self.dial.value())))
        self.dial.setValue(0)
        self.dial.setMinimum(-999)
        self.dial.setMaximum(999)
        self.dial.setSingleStep(100)
        self.dial.setPageStep(100)
        self.dial.setWrapping(False)
        self.dial.setNotchesVisible(True)

        self.defo = QPushButton(QIcon.fromTheme("media-playback-start"), 'Run')
        self.defo.setMinimumSize(self.defo.size().width(), 50)
        self.defo.clicked.connect(lambda: self.process3.start(
            'play -q -V0 "|rec -q -V0 -n -d -R riaa pitch {} "'
            .format(self.dial.value()) if int(self.dial.value()) != 0 else
            'play -q -V0 "|rec -q -V0 --multi-threaded -n -d -R bend {} "'
            .format(' 3,2500,3 3,-2500,3 ' * 999)))

        self.qq = QPushButton(QIcon.fromTheme("media-playback-stop"), 'Stop')
        self.qq.clicked.connect(self.process3.kill)

        self.die = QPushButton(QIcon.fromTheme("process-stop"), 'Kill')
        self.die.clicked.connect(lambda: call('killall rec', shell=True))

        vboxg5 = QVBoxLayout(self.group5)
        for each_widget in (self.dial, self.defo, self.qq, self.die):
            vboxg5.addWidget(each_widget)
        self.dock5.setWidget(self.group5)

        # configure some widget settings
        must_be_checked((self.nepochoose, self.chckbx1,
                         self.chckbx2, self.chckbx3))
        must_have_tooltip((self.label2, self.label4, self.label6, self.combo0,
            self.nepochoose, self.combo1, self.combo2, self.combo3, self.combo4,
            self.combo5, self.chckbx0, self.chckbx1, self.chckbx2, self.chckbx3,
            self.rec, self.stop, self.defo, self.qq, self.die, self.kill,
            self.button0, self.button1, self.button5))
        must_autofillbackground((self.clock, self.label2, self.label4,
            self.label6, self.nepochoose, self.chckbx0, self.chckbx1,
            self.chckbx2, self.chckbx3))
        must_glow((self.rec, self.dial, self.combo1))
        self.nepomuk_get('testigo')
        if self.auto is True:
            self.go()

    def play(self, index):
        ' play with delay '
        if not self.media:
            self.media = Phonon.MediaObject(self)
            audioOutput = Phonon.AudioOutput(Phonon.MusicCategory, self)
            Phonon.createPath(self.media, audioOutput)
        self.media.setCurrentSource(Phonon.MediaSource(
            self.model.filePath(index)))
        self.media.play()

    def end(self):
        ' kill it with fire '
        print((' INFO: Stoping Processes at {}'.format(str(datetime.now()))))
        self.process1.terminate()
        self.process2.terminate()
        self.feedback.setText('''
            <h5>Errors for RECORDER QProcess 1:</h5>{}<hr>
            <h5>Errors for ENCODER QProcess 2:</h5>{}<hr>
            <h5>Output for RECORDER QProcess 1:</h5>{}<hr>
            <h5>Output for ENCODER QProcess 2:</h5>{}<hr>
            '''.format(self.process1.readAllStandardError(),
                       self.process2.readAllStandardError(),
                       self.process1.readAllStandardOutput(),
                       self.process2.readAllStandardOutput(),
        ))

    def killer(self):
        ' kill -9 '
        QMessageBox.information(self.mainwidget, __doc__,
            ' KILL -9 was sent to the multi-process backend ! ')
        self.process1.kill()
        self.process2.kill()

    def go(self):
        ' run timeout re-starting timers '
        self.timerFirst.start(int(self.slider.value()) * 60 * 1000 + 2000)
        self.timerSecond.start(int(self.slider.value()) * 60 * 1000 + 2010)
        self.run()

    def run(self):
        ' run forest run '
        print((' INFO: Working at {}'.format(str(datetime.now()))))

        chnl = 1 if self.combo3.currentText() == 'MONO' else 2
        print((' INFO: Using {} Channels . . . '.format(chnl)))

        btrt = int(self.combo4.currentText())
        print((' INFO: Using {} Hz per Second . . . '.format(btrt)))

        threshold = int(self.dial.value())
        print((' INFO: Using Thresold of {} . . . '.format(threshold)))

        print((' INFO: Using Recording time of {}'.format(self.slider.value())))

        frmt = str(self.combo0.currentText()).strip()
        print((' INFO: Using Recording quality of {} ...'.format(frmt)))

        qlt = str(self.combo1.currentText()).strip()
        print((' INFO: Using Recording quality of {} ...'.format(qlt)))

        prio = str(self.combo5.currentText()).strip()
        print((' INFO: Using CPU Priority of {} ...'.format(prio)))

        downmix = '--downmix ' if self.chckbx1.isChecked() is True else ''
        print((' INFO: Using Downmix is {} ...'.format(downmix)))

        aut = '-a ' + getuser() if self.chckbx3.isChecked() is True else ''
        print((' INFO: The Author Artist of this sound is: {}'.format(aut)))

        T = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
        tim = '--date {} '.format(T) if self.chckbx2.isChecked() is True else ''
        print((' INFO: The Date and Time of this sound is: {}'.format(tim)))

        vol = ' --disable-softvol' if self.chckbx0.isChecked() is True else ''
        print((' INFO: Software based Volume Control is: {}'.format(vol)))

        # make base directory
        try:
            mkdir(self.base)
            print((' INFO: Base Directory path created {}'.format(self.base)))
        except OSError:
            print((' INFO: Base Directory already exist {}'.format(self.base)))
        except:
            print((' ERROR: Can not create Directory ?, {}'.format(self.base)))

        # make directory tree
        try:
            for dr in range(1, 13):
                mkdir(path.abspath(path.join(self.base, str(dr))))
                print((' INFO:Directory created {}/{}'.format(self.base, dr)))
        except OSError:
            print((' INFO: Directory already exist {}/1,12'.format(self.base)))
        except:
            print((' ERROR: Cant create Directory?, {}/1,12'.format(self.base)))

        # make new filename
        flnm = path.abspath(path.join(self.base, str(datetime.now().month),
                   datetime.now().strftime("%Y-%m-%d_%H:%M:%S.ogg")))
        self.actual_file = flnm
        print((' INFO: Recording on the file {}'.format(flnm)))

        # make custom commands
        cmd1 = self.cmd1.format(n=prio, f=frmt, c=chnl, b=btrt, v=vol)
        cmd2 = self.cmd2.format(c=chnl, b=btrt, q=qlt,
                                d=downmix, o=flnm, a=aut, t=tim)
        print((cmd1, cmd2))
        #  multiprocess recording loop pipe
        self.process1 = QProcess(self)
        self.process2 = QProcess(self)
        self.process1.setStandardOutputProcess(self.process2)
        self.process1.start(cmd1)
        if not self.process1.waitForStarted():
            print((" ERROR: RECORDER QProcess 1 Failed: \n {}   ".format(cmd1)))
        self.process2.start(cmd2)
        if not self.process2.waitForStarted():
            print((" ERROR: ENCODER QProcess 2 Failed: \n   {} ".format(cmd2)))
        self.nepomuk_set(flnm, 'testigo', 'testigo', 'AutoTag by Cinta-Testigo')

    def spectro(self):
        ' spectrometer '
        wid = self.spec.size().width()
        hei = self.spec.size().height()
        command = self.cmd3.format(o=self.actual_file, x=wid, y=hei)
        print(' INFO: Spectrometer is deleting OLD .ogg.png Files on target ')
        call('rm --verbose --force {}/*/*.ogg.png'.format(self.base), shell=1)
        print(' INFO: Spectrometer finished Deleting Files, Starting Render ')
        call(command, shell=True)
        print((''' INFO: Spectrometer finished Rendering Sound using:
               {}{}   OutPut: {}'''.format(command, linesep, self.actual_file)))
        self.spec.setIcon(QIcon('{o}.png'.format(o=self.actual_file)))
        self.spec.setIconSize(QSize(wid, hei))
        self.spec.resize(wid, hei)

    ###########################################################################

    def paintEvent(self, event):
        'Paint semi-transparent background, animated pattern, background text'
        QWidget.paintEvent(self, event)
        # make a painter
        p = QPainter(self)
        p.setRenderHint(QPainter.TextAntialiasing)
        p.setRenderHint(QPainter.HighQualityAntialiasing)
        # fill a rectangle with transparent painting
        p.fillRect(event.rect(), Qt.transparent)
        # animated random dots background pattern
        for i in range(4096):
            x = randint(9, self.size().width() - 9)
            y = randint(9, self.size().height() - 9)
            p.setPen(QPen(QColor(randint(200, 255), randint(200, 255), 255), 1))
            p.drawPoint(x, y)
        # set pen to use white color
        p.setPen(QPen(QColor(randint(9, 255), randint(9, 255), 255), 1))
        # Rotate painter 45 Degree
        p.rotate(35)
        # Set painter Font for text
        p.setFont(QFont('Ubuntu', 300))
        # draw the background text, with antialiasing
        p.drawText(99, 199, "Radio")
        # Rotate -45 the QPen back !
        p.rotate(-35)
        # set the pen to no pen
        p.setPen(Qt.NoPen)
        # Background Color
        p.setBrush(QColor(0, 0, 0))
        # Background Opacity
        p.setOpacity(0.75)
        # Background Rounded Borders
        p.drawRoundedRect(self.rect(), 50, 50)
        # finalize the painter
        p.end()

    def seTitle(self):
        ' set the title of the main window '
        dialog = QDialog(self)
        textEditInput = QLineEdit(' Type Title Here ')
        ok = QPushButton(' O K ')
        ok.clicked.connect(lambda: self.setWindowTitle(textEditInput.text()))
        ly = QVBoxLayout()
        [ly.addWidget(wdgt) for wdgt in (QLabel('Title:'), textEditInput, ok)]
        dialog.setLayout(ly)
        dialog.exec_()

    def timedate(self):
        ' get the time and date '
        dialog = QDialog(self)
        clock = QLCDNumber()
        clock.setNumDigits(24)
        timer = QTimer()
        timer.timeout.connect(lambda: clock.display(
            datetime.now().strftime("%d-%m-%Y %H:%M:%S %p")))
        timer.start(1000)
        clock.setToolTip(datetime.now().strftime("%c %x"))
        ok = QPushButton(' O K ')
        ok.clicked.connect(dialog.close)
        ly = QVBoxLayout()
        [ly.addWidget(wdgt) for wdgt in (QCalendarWidget(), clock, ok)]
        dialog.setLayout(ly)
        dialog.exec_()

    def closeEvent(self, event):
        ' Ask to Quit '
        if QMessageBox.question(self, ' Close ', ' Quit ? ',
           QMessageBox.Yes | QMessageBox.No, QMessageBox.No) == QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()

    def center(self):
        ' Center and resize the window '
        self.showNormal()
        self.resize(QDesktopWidget().screenGeometry().width() // 1.25,
                    QDesktopWidget().screenGeometry().height() // 1.25)
        qr = self.frameGeometry()
        qr.moveCenter(QDesktopWidget().availableGeometry().center())
        self.move(qr.topLeft())

    def nepomuk_set(self, file_tag=None, __tag='', _label='', _description=''):
        ' Quick and Easy Nepomuk Taggify for Files '
        print((''' INFO: Semantic Desktop Experience is Tagging Files :
              {}, {}, {}, {})'''.format(file_tag, __tag, _label, _description)))
        if Nepomuk.ResourceManager.instance().init() is 0:
            fle = Nepomuk.Resource(KUrl(QFileInfo(file_tag).absoluteFilePath()))
            _tag = Nepomuk.Tag(__tag)
            _tag.setLabel(_label)
            fle.addTag(_tag)
            fle.setDescription(_description)
            print(([str(a.label()) for a in fle.tags()], fle.description()))
            return ([str(a.label()) for a in fle.tags()], fle.description())
        else:
            print(" ERROR: FAIL: Nepomuk is not running ! ")

    def nepomuk_get(self, query_to_search):
        ' Quick and Easy Nepomuk Query for Files '
        print((''' INFO: Semantic Desktop Experience is Quering Files :
              {} '''.format(query_to_search)))
        results = []
        nepo = Nepomuk.Query.QueryServiceClient()
        nepo.desktopQuery("hasTag:{}".format(query_to_search))

        def _query(data):
            ''' ('filename.ext', 'file description', ['list', 'of', 'tags']) '''
            results.append(([str(a.resource().genericLabel()) for a in data][0],
                            [str(a.resource().description()) for a in data][0],
            [str(a.label()) for a in iter([a.resource().tags() for a in data][0]
            )]))
        nepo.newEntries.connect(_query)

        def _end():
            '''
            [  ('filename.ext', 'file description', ['list', 'of', 'tags']),
               ('filename.ext', 'file description', ['list', 'of', 'tags']),
               ('filename.ext', 'file description', ['list', 'of', 'tags'])  ]
            '''
            nepo.newEntries.disconnect
            print(results)
            return results
        nepo.finishedListing.connect(_end)
Пример #14
0
class Main(plugin.Plugin):
    " Main Class "
    def initialize(self, *args, **kwargs):
        " Init Main Class "
        ec = ExplorerContainer()
        super(Main, self).initialize(*args, **kwargs)

        self.editor_s = self.locator.get_service('editor')
        # directory auto completer
        self.completer = QCompleter(self)
        self.dirs = QDirModel(self)
        self.dirs.setFilter(QDir.AllEntries | QDir.NoDotAndDotDot)
        self.completer.setModel(self.dirs)
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.setCompletionMode(QCompleter.PopupCompletion)

        self.group0 = QGroupBox()
        self.group0.setTitle(' Source ')
        self.source = QComboBox()
        self.source.addItems(['Clipboard', 'Local File', 'Remote URL', 'Ninja'])
        self.source.currentIndexChanged.connect(self.on_source_changed)
        self.infile = QLineEdit(path.expanduser("~"))
        self.infile.setPlaceholderText(' /full/path/to/file.html ')
        self.infile.setCompleter(self.completer)
        self.open = QPushButton(QIcon.fromTheme("folder-open"), 'Open')
        self.open.setCursor(QCursor(Qt.PointingHandCursor))
        self.open.clicked.connect(lambda: self.infile.setText(str(
            QFileDialog.getOpenFileName(self.dock, "Open a File to read from",
            path.expanduser("~"), ';;'.join(['{}(*.{})'.format(e.upper(), e)
            for e in ['css', 'html', 'js', 'txt', '*']])))))
        self.inurl = QLineEdit('http://www.')
        self.inurl.setPlaceholderText('http://www.full/url/to/remote/file.html')
        self.output = QPlainTextEdit(SAMPLE_TEXT)
        vboxg0 = QVBoxLayout(self.group0)
        for each_widget in (self.source, self.infile, self.open, self.inurl,
            self.output, ):
            vboxg0.addWidget(each_widget)
        [a.hide() for a in iter((self.infile, self.open, self.inurl))]

        self.group1 = QGroupBox()
        self.group1.setTitle(' CSS3 ')
        self.group1.setCheckable(True)
        self.group1.setGraphicsEffect(QGraphicsBlurEffect(self))
        self.group1.graphicsEffect().setEnabled(False)
        self.group1.toggled.connect(self.toggle_css_group)
        self.ckcss1 = QCheckBox('Remove unnecessary Comments')
        self.ckcss2 = QCheckBox('Remove unnecessary Whitespace characters')
        self.ckcss3 = QCheckBox('Remove unnecessary Semicolons')
        self.ckcss4 = QCheckBox('Remove unnecessary Empty rules')
        self.ckcss5 = QCheckBox('Condense and Convert Colors from RGB to HEX')
        self.ckcss6 = QCheckBox('Condense all Zero units')
        self.ckcss7 = QCheckBox('Condense Multidimensional Zero units')
        self.ckcss8 = QCheckBox('Condense Floating point numbers')
        self.ckcss9 = QCheckBox('Condense HEX Colors')
        self.ckcss10 = QCheckBox('Condense multiple adjacent Whitespace chars')
        self.ckcss11 = QCheckBox('Condense multiple adjacent semicolon chars')
        self.ckcss12 = QCheckBox('Wrap the lines of the to 80 character length')
        self.ckcss13 = QCheckBox('Condense Font Weight values')
        self.ckcss14 = QCheckBox('Condense the 17 Standard Named Colors values')
        self.ckcss15 = QCheckBox('Condense the 124 Extra Named Colors values')
        self.ckcss16 = QCheckBox('Condense all Percentages values when posible')
        self.ckcss17 = QCheckBox('Condense all Pixels values when posible')
        self.ckcss18 = QCheckBox('Remove unnecessary quotes from url()')
        self.ckcss19 = QCheckBox('Add standard Encoding Declaration if missing')
        vboxg1 = QVBoxLayout(self.group1)
        for each_widget in (self.ckcss1, self.ckcss2, self.ckcss3, self.ckcss4,
            self.ckcss5, self.ckcss6, self.ckcss7, self.ckcss8, self.ckcss9,
            self.ckcss10, self.ckcss11, self.ckcss12, self.ckcss13,
            self.ckcss14, self.ckcss15, self.ckcss16, self.ckcss17,
            self.ckcss18, self.ckcss19):
            vboxg1.addWidget(each_widget)
            each_widget.setToolTip(each_widget.text())

        self.group2 = QGroupBox()
        self.group2.setTitle(' HTML5 ')
        self.group2.setCheckable(True)
        self.group2.setGraphicsEffect(QGraphicsBlurEffect(self))
        self.group2.graphicsEffect().setEnabled(False)
        self.group2.toggled.connect(self.toggle_html_group)
        self.ckhtml0 = QCheckBox('Condense Style and Script HTML Tags')
        self.ckhtml1 = QCheckBox('Condense DOCTYPE to new HTML5 Tags')
        self.ckhtml2 = QCheckBox('Condense Href and Src to protocol agnostic')
        self.ckhtml4 = QCheckBox('Remove unnecessary Tags but keep HTML valid')
        self.help1 = QLabel('''<a href=
            "https://developers.google.com/speed/articles/optimizing-html">
            <small><center>Help about Unneeded Unnecessary HTML tags ?</a>''')
        self.help1.setTextInteractionFlags(Qt.LinksAccessibleByMouse)
        self.help1.setOpenExternalLinks(True)
        vboxg2 = QVBoxLayout(self.group2)
        for each_widget in (self.ckhtml0, self.ckhtml1, self.ckhtml2,
            self.ckhtml4, self.help1, ):
            vboxg2.addWidget(each_widget)
            each_widget.setToolTip(each_widget.text())

        self.group3 = QGroupBox()
        self.group3.setTitle(' Javascript ')
        self.ckjs0 = QCheckBox('Condense and Compress Javascript')
        self.ckjs1 = QCheckBox('Condense $(document).ready(function(){ });')
        vboxg2 = QVBoxLayout(self.group3)
        for each_widget in (self.ckjs0, self.ckjs1):
            vboxg2.addWidget(each_widget)
            each_widget.setToolTip(each_widget.text())

        self.group4 = QGroupBox()
        self.group4.setTitle(' General ')
        self.chckbx1 = QCheckBox('Lower case ALL the text')
        self.chckbx2 = QCheckBox('Remove Spaces, Tabs, New Lines, Empty Lines')
        self.befor, self.after = QProgressBar(), QProgressBar()
        self.befor.setFormat("%v Chars")
        self.after.setFormat("%v Chars")
        vboxg4 = QVBoxLayout(self.group4)
        for each_widget in (self.chckbx1, self.chckbx2,
            QLabel('<b>Before:'), self.befor, QLabel('<b>After:'), self.after):
            vboxg4.addWidget(each_widget)
            each_widget.setToolTip(each_widget.text())

        [a.setChecked(True) for a in iter((self.ckcss1, self.ckcss2,
            self.ckcss3, self.ckcss4, self.ckcss5, self.ckcss6, self.ckcss7,
            self.ckcss8, self.ckcss9, self.ckcss10, self.ckcss11, self.ckcss12,
            self.ckcss13, self.ckcss14, self.ckcss15, self.ckcss16,
            self.ckcss17, self.ckcss18, self.ckcss19, self.ckjs1, self.ckhtml0,
            self.ckhtml1, self.ckhtml2, self.ckhtml4, self.chckbx1,
            self.chckbx2))]

        self.button = QPushButton(QIcon.fromTheme("face-cool"), 'Process Text')
        self.button.setCursor(QCursor(Qt.PointingHandCursor))
        self.button.setMinimumSize(100, 50)
        self.button.clicked.connect(self.run)

        def must_glow(widget_list):
            ' apply an glow effect to the widget '
            for glow, each_widget in enumerate(widget_list):
                try:
                    if each_widget.graphicsEffect() is None:
                        glow = QGraphicsDropShadowEffect(self)
                        glow.setOffset(0)
                        glow.setBlurRadius(99)
                        glow.setColor(QColor(99, 255, 255))
                        each_widget.setGraphicsEffect(glow)
                        glow.setEnabled(True)
                except:
                    pass

        must_glow((self.button, ))

        class TransientWidget(QWidget):
            ' persistant widget thingy '
            def __init__(self, widget_list):
                ' init sub class '
                super(TransientWidget, self).__init__()
                vbox = QVBoxLayout(self)
                for each_widget in widget_list:
                    vbox.addWidget(each_widget)

        tw = TransientWidget((QLabel('<b>HTML5/CSS3/JS Optimizer Compressor'),
            self.group0, self.group1, self.group2, self.group3, self.group4,
            self.button, ))
        self.scrollable = QScrollArea()
        self.scrollable.setWidgetResizable(True)
        self.scrollable.setWidget(tw)
        self.dock = QDockWidget()
        self.dock.setWindowTitle(__doc__)
        self.dock.setStyleSheet('QDockWidget::title{text-align: center;}')
        self.dock.setMinimumWidth(350)
        self.dock.setWidget(self.scrollable)
        ec.addTab(self.dock, "Web")
        QPushButton(QIcon.fromTheme("help-about"), 'About', self.dock
          ).clicked.connect(lambda: QMessageBox.information(self.dock, __doc__,
            HELPMSG))

    def run(self):
        ' run the string replacing '
        if self.source.currentText() == 'Local File':
            with open(path.abspath(str(self.infile.text()).strip()), 'r') as f:
                txt = f.read()
        elif self.source.currentText() == 'Remote URL':
            txt = urlopen(str(self.inurl.text()).strip()).read()
        elif  self.source.currentText() == 'Clipboard':
            txt = str(self.output.toPlainText()) if str(self.output.toPlainText()) is not '' else str(QApplication.clipboard().text())
        else:
            txt = self.editor_s.get_text()
        self.output.clear()
        self.befor.setMaximum(len(txt) + 10)
        self.after.setMaximum(len(txt) + 10)
        self.befor.setValue(len(txt))
        txt = txt.lower() if self.chckbx1.isChecked() is True else txt
        txt = condense_style(txt) if self.ckhtml0.isChecked() is True else txt
        txt = condense_script(txt) if self.ckhtml0.isChecked() is True else txt
        txt = condense_doctype(txt) if self.ckhtml1.isChecked() is True else txt
        txt = condense_href_src(txt) if self.ckhtml2 is True else txt
        txt = clean_unneeded_tags(txt) if self.ckhtml4.isChecked() is True else txt
        txt = condense_doc_ready(txt) if self.ckjs1.isChecked() is True else txt
        txt = jsmin(txt) if self.ckjs0.isChecked() is True else txt
        txt = remove_comments(txt) if self.ckcss1.isChecked() is True else txt
        txt = condense_whitespace(txt) if self.ckcss10.isChecked() is True else txt
        txt = remove_empty_rules(txt) if self.ckcss4.isChecked() is True else txt
        txt = remove_unnecessary_whitespace(txt) if self.ckcss2.isChecked() is True else txt
        txt = remove_unnecessary_semicolons(txt) if self.ckcss3.isChecked() is True else txt
        txt = condense_zero_units(txt) if self.ckcss6.isChecked() is True else txt
        txt = condense_multidimensional_zeros(txt) if self.ckcss7.isChecked() is True else txt
        txt = condense_floating_points(txt) if self.ckcss8.isChecked() is True else txt
        txt = normalize_rgb_colors_to_hex(txt) if self.ckcss5.isChecked() is True else txt
        txt = condense_hex_colors(txt) if self.ckcss9.isChecked() is True else txt
        txt = wrap_css_lines(txt, 80) if self.ckcss12.isChecked() is True else txt
        txt = condense_semicolons(txt) if self.ckcss11.isChecked() is True else txt
        txt = condense_font_weight(txt) if self.ckcss13.isChecked() is True else txt
        txt = condense_std_named_colors(txt) if self.ckcss14.isChecked() is True else txt
        # txt = condense_xtra_named_colors(txt) if self.ckcss14.isChecked() is True else txt  # FIXME
        txt = condense_percentage_values(txt) if self.ckcss16.isChecked() is True else txt
        txt = condense_pixel_values(txt) if self.ckcss17.isChecked() is True else txt
        txt = remove_url_quotes(txt) if self.ckcss18.isChecked() is True else txt
        txt = add_encoding(txt) if self.ckcss19.isChecked() is True else txt
        txt = " ".join(txt.strip().split()) if self.chckbx2.isChecked() is True else txt
        self.after.setValue(len(txt))
        self.output.setPlainText(txt)
        self.output.show()
        self.output.setFocus()
        self.output.selectAll()

    def on_source_changed(self):
        ' do something when the desired source has changed '
        if self.source.currentText() == 'Local File':
            self.open.show()
            self.infile.show()
            self.inurl.hide()
            self.output.hide()
        elif  self.source.currentText() == 'Remote URL':
            self.inurl.show()
            self.open.hide()
            self.infile.hide()
            self.output.hide()
        elif  self.source.currentText() == 'Clipboard':
            self.output.show()
            self.open.hide()
            self.infile.hide()
            self.inurl.hide()
            self.output.setText(QApplication.clipboard().text())
        else:
            self.output.show()
            self.open.hide()
            self.infile.hide()
            self.inurl.hide()
            self.output.setText(self.editor_s.get_text())

    def toggle_css_group(self):
        ' toggle on or off the css checkboxes '
        if self.group1.isChecked() is True:
            [a.setChecked(True) for a in iter((self.ckcss1, self.ckcss2,
            self.ckcss3, self.ckcss4, self.ckcss5, self.ckcss6, self.ckcss7,
            self.ckcss8, self.ckcss9, self.ckcss10, self.ckcss11, self.ckcss12,
            self.ckcss13, self.ckcss14, self.ckcss15, self.ckcss16,
            self.ckcss17, self.ckcss18, self.ckcss19))]
            self.group1.graphicsEffect().setEnabled(False)
        else:
            [a.setChecked(False) for a in iter((self.ckcss1, self.ckcss2,
            self.ckcss3, self.ckcss4, self.ckcss5, self.ckcss6, self.ckcss7,
            self.ckcss8, self.ckcss9, self.ckcss10, self.ckcss11, self.ckcss12,
            self.ckcss13, self.ckcss14, self.ckcss15, self.ckcss16,
            self.ckcss17, self.ckcss18, self.ckcss19))]
            self.group1.graphicsEffect().setEnabled(True)

    def toggle_html_group(self):
        ' toggle on or off the css checkboxes '
        if self.group2.isChecked() is True:
            [a.setChecked(True) for a in iter((self.ckhtml0, self.ckhtml1,
                                               self.ckhtml2, self.ckhtml4))]
            self.group2.graphicsEffect().setEnabled(False)
        else:
            [a.setChecked(False) for a in iter((self.ckhtml0, self.ckhtml1,
                                                self.ckhtml2, self.ckhtml4))]
            self.group2.graphicsEffect().setEnabled(True)
Пример #15
0
class Main(plugin.Plugin):
    " Main Class "
    def initialize(self, *args, **kwargs):
        " Init Main Class "
        super(Main, self).initialize(*args, **kwargs)

        # directory auto completer
        self.completer = QCompleter(self)
        self.dirs = QDirModel(self)
        self.dirs.setFilter(QDir.AllEntries | QDir.NoDotAndDotDot)
        self.completer.setModel(self.dirs)
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.setCompletionMode(QCompleter.PopupCompletion)

        # tab widget
        self.mainwidget = QTabWidget()
        self.mainwidget.setToolTip(__doc__)
        self.mainwidget.setTabShape(QTabWidget.Triangular)
        self.mainwidget.setMovable(True)
        self.mainwidget.setTabsClosable(True)
        self.mainwidget.tabCloseRequested.connect(lambda:
            self.mainwidget.setTabPosition(1)
            if self.mainwidget.tabPosition() == 0
            else self.mainwidget.setTabPosition(0))
        self.dock1 = QDockWidget()
        self.dock2 = QDockWidget()
        for indx, a in enumerate((self.dock1, self.dock2)):
            a.setWindowModality(Qt.NonModal)
            a.setWindowOpacity(0.9)
            a.setWindowTitle('Semantic Files' if indx == 0 else 'Simple Query')
            a.setStyleSheet('QDockWidget::title{text-align:center;}')
            self.mainwidget.addTab(a, QIcon.fromTheme("nepomuk"),
                             'Semantic Files' if indx == 0 else 'Simple Query')

        QPushButton(QIcon.fromTheme("help-about"), 'Help About', self.dock1
          ).clicked.connect(lambda:
          QMessageBox.information(self.dock1, __doc__, HELPMSG))

        # Group of widgets for each tab
        self.group1 = QGroupBox()
        self.filename = QLineEdit()
        self.filename.setPlaceholderText('/full/path/to/one_file.py')
        self.filename.setCompleter(self.completer)
        self.filebttn = QPushButton(QIcon.fromTheme("folder-open"), 'Open File')
        self.filebttn.clicked.connect(lambda: self.filename.setText(str(
            QFileDialog.getOpenFileName(self.mainwidget,
            " Please, open a .py file to add Semantics ", path.expanduser("~"),
            ';;'.join(['(*.{}) {}'.format(e, e.upper()) for e in ['*', 'py']])))
        ))

        self.group1a = QGroupBox()
        self.filetag = QLineEdit()
        self.filetag.setPlaceholderText('Type a short Tag for the choosen File')
        self.filelbl = QLineEdit()
        self.filelbl.setPlaceholderText('Type a descriptive Label for the Tag')
        self.filedsc = QLineEdit()
        self.filedsc.setPlaceholderText('Type a large and detailed Description')
        self.filerat = KRatingWidget()
        self.filerat.setToolTip('Set a File Rating')
        vboxg1a = QHBoxLayout(self.group1a)
        for each_widget in (QLabel('<b>File Tag'), self.filetag,
            QLabel('<b>Tag Label'), self.filelbl,
            QLabel('<b>Description'), self.filedsc,
            QLabel('<b>File Rating'), self.filerat):
            vboxg1a.addWidget(each_widget)

        self.nepobtn = QPushButton(QIcon.fromTheme("nepomuk"), 'Add Semantics')
        self.nepobtn.setMinimumSize(self.nepobtn.size().width(), 50)
        self.nepobtn.clicked.connect(lambda: self.nepomuk_set(
            str(self.filename.text()).strip(), str(self.filetag.text()).strip(),
            str(self.filelbl.text()).strip(), str(self.filedsc.text()).strip()))
        vboxg1 = QVBoxLayout(self.group1)
        for each_widget in (
            QLabel('<b>Choose a File'), self.filename, self.filebttn,
            self.group1a, self.nepobtn):
            vboxg1.addWidget(each_widget)

        self.group2 = QGroupBox()
        self.group2.setTitle('Sorry!, this Tab is not Ready yet...')
        QLabel('<b style="color:red;"><i>Not Ready Yet!', self.dock2)
        self.search = QLineEdit()
        self.search.setPlaceholderText('Type to Query...')
        self.srcbtn = QPushButton(QIcon.fromTheme("folder-open"), 'Query')
        self.result = QTextEdit()
        self.srcbtn.clicked.connect(lambda:
            self.nepomuk_get(str(self.search.text()).strip().lower()))
        vboxg2 = QVBoxLayout(self.group2)
        for each_widget in (
            QLabel('<b>Type for a Semantic Query'), self.search, self.srcbtn,
            QLabel('<b>Semantic Query Results'), self.result):
            vboxg2.addWidget(each_widget)

        # pack the group of widgets on the gui
        self.dock1.setWidget(self.group1)
        self.dock2.setWidget(self.group2)

        # pack the plugin on ninja-ide gui
        self.locator.get_service('misc').add_widget(
                        self.mainwidget, QIcon.fromTheme("nepomuk"), __doc__)

        def must_have_tooltip(widget_list):
            ' widget tuple passed as argument should have tooltips '
            for each_widget in widget_list:
                try:
                    each_widget.setToolTip(each_widget.text())
                except:
                    each_widget.setToolTip(each_widget.currentText())
                finally:
                    each_widget.setCursor(QCursor(Qt.PointingHandCursor))

        def must_glow(widget_list):
            ' apply an glow effect to the widget '
            for glow, each_widget in enumerate(widget_list):
                try:
                    if each_widget.graphicsEffect() is None:
                        glow = QGraphicsDropShadowEffect(self)
                        glow.setOffset(0)
                        glow.setBlurRadius(99)
                        glow.setColor(QColor(99, 255, 255))
                        each_widget.setGraphicsEffect(glow)
                        # glow.setEnabled(False)
                        try:
                            each_widget.clicked.connect(lambda:
                            each_widget.graphicsEffect().setEnabled(True)
                            if each_widget.graphicsEffect().isEnabled() is False
                            else each_widget.graphicsEffect().setEnabled(False))
                        except:
                            each_widget.sliderPressed.connect(lambda:
                            each_widget.graphicsEffect().setEnabled(True)
                            if each_widget.graphicsEffect().isEnabled() is False
                            else each_widget.graphicsEffect().setEnabled(False))
                except:
                    pass

        must_have_tooltip((self.filebttn, self.nepobtn, self.srcbtn, ))
        must_glow((self.nepobtn, self.srcbtn, ))

    def nepomuk_set(self, file_tag=None, __tag='', _label='', _description=''):
        ' Quick and Easy Nepomuk Taggify for Files '
        print((''' INFO: Semantic Desktop Experience is Tagging Files :
              {}, {}, {}, {})'''.format(file_tag, __tag, _label, _description)))
        if Nepomuk.ResourceManager.instance().init() is 0:
            fle = Nepomuk.Resource(KUrl(QFileInfo(file_tag).absoluteFilePath()))
            _tag = Nepomuk.Tag(__tag)
            _tag.setLabel(_label)
            fle.addTag(_tag)
            fle.setRating(int(self.filerat.rating()))
            fle.setDescription(_description)
            print(([str(a.label()) for a in fle.tags()], fle.description()))
            return ([str(a.label()) for a in fle.tags()], fle.description())
        else:
            print(" ERROR: FAIL: Nepomuk is not running ! ")

    def nepomuk_get(self, query_to_search):
        ' Quick and Easy Nepomuk Query for Files '
        print((''' INFO: Semantic Desktop Experience is Quering Files :
              {} '''.format(query_to_search)))
        results = []
        nepo = Nepomuk.Query.QueryServiceClient()
        nepo.desktopQuery("hasTag:{}".format(query_to_search))

        def _query(data):
            ''' ('filename.ext', 'file description', ['list', 'of', 'tags']) '''
            print(([str(a.resource().genericLabel()) for a in data][0],
                   [str(a.resource().description()) for a in data][0],
            [str(a.label()) for a in iter([a.resource().tags() for a in data][0]
            )]))
            self.result.append(str(
                ([str(a.resource().genericLabel()) for a in data][0],
                 [str(a.resource().description()) for a in data][0],
            [str(a.label()) for a in iter([a.resource().tags() for a in data][0]
            )],
            )))
        nepo.newEntries.connect(_query)
        nepo.finishedListing.connect(lambda: nepo.newEntries.disconnect)
        return results