예제 #1
0
파일: link_equation.py 프로젝트: eteq/glue
class ArgumentWidget(QWidget):
    def __init__(self, argument, parent=None):
        super(ArgumentWidget, self).__init__(parent)
        self.layout = QHBoxLayout()
        self.layout.setContentsMargins(1, 0, 1, 1)
        self.setLayout(self.layout)
        label = QLabel(argument)
        self._label = label
        self._component_id = None
        self.layout.addWidget(label)
        self.editor = QLineEdit()
        self.editor.setReadOnly(True)
        try:
            self.editor.setPlaceholderText("Drag a component from above")
        except AttributeError:  # feature added in Qt 4.7
            pass
        self.layout.addWidget(self.editor)
        self.setAcceptDrops(True)

    @property
    def component_id(self):
        return self._component_id

    @component_id.setter
    def component_id(self, cid):
        self._component_id = cid
        self.editor.setText(str(cid))

    @property
    def label(self):
        return self._label.text()

    @label.setter
    def label(self, label):
        self._label.setText(label)

    @property
    def editor_text(self):
        return self.editor.text()

    def clear(self):
        self.component_id = None
        self.editor.clear()

    def dragEnterEvent(self, event):
        if event.mimeData().hasFormat('application/py_instance'):
            event.accept()
        else:
            event.ignore()

    def dropEvent(self, event):
        obj = event.mimeData().data('application/py_instance')
        if not isinstance(obj, core.data.ComponentID):
            return
        self.component_id = obj
예제 #2
0
파일: reportexport.py 프로젝트: vertrex/DFF
class ReportExportOptionsDialog(QDialog):
    def __init__(self, exportContent=False):
        QDialog.__init__(self)
        self.setWindowTitle(self.tr("Export options"))
        self.reportManager = ReportManager()
        layout = QVBoxLayout()

        self.extractContentCheckBox = QCheckBox(self.tr("E&xtract content"))
        if exportContent:
            self.extractContentCheckBox.setChecked(True)
        else:
            self.extractContentCheckBox.setChecked(False)
        layout.addWidget(self.extractContentCheckBox)

        directoryPathLayout = QHBoxLayout()
        pathLabel = QLabel(self.tr("Report extraction path :"))
        self.pathLineEdit = QLineEdit(self.reportManager.export_path)
        self.pathLineEdit.setReadOnly(True)
        pathButton = QPushButton("...")
        self.connect(pathButton, SIGNAL("clicked()"), self.askPath)
        directoryPathLayout.addWidget(pathLabel)
        directoryPathLayout.addWidget(self.pathLineEdit)
        directoryPathLayout.addWidget(pathButton)
        layout.addLayout(directoryPathLayout)

        buttonLayout = QHBoxLayout()
        self.buttonOk = QPushButton("O&k")
        self.connect(self.buttonOk, SIGNAL("clicked()"), self.accept)
        self.buttonCancel = QPushButton("C&ancel")
        self.connect(self.buttonCancel, SIGNAL("clicked()"), self.reject)

        buttonLayout.addWidget(self.buttonOk)
        buttonLayout.addWidget(self.buttonCancel)
        layout.addLayout(buttonLayout)
        self.setLayout(layout)

    def askPath(self):
        directory = QFileDialog.getExistingDirectory(
            self, self.tr("Report extraction directory"),
            self.reportManager.export_path)
        if len(directory):
            directory = os.path.join(str(directory.toUtf8()), 'dff-report')
            self.pathLineEdit.clear()
            self.pathLineEdit.insert(directory)
            self.reportManager.setExportPath(directory)

    def exportContent(self):
        if self.extractContentCheckBox.isChecked():
            return True
        else:
            return False
예제 #3
0
class LilyPondDocumentVersion(SettingsGroup):
    def __init__(self, page):
        super(LilyPondDocumentVersion, self).__init__(i18n("LilyPond version number to use for new documents"), page)

        grid = QGridLayout(self)
        grid.setSpacing(0)

        self.versionOptions = {}
        self.customVersion = QLineEdit(textChanged=page.changed)

        def changed(dummy):
            page.changed()
            self.customVersion.setEnabled(self.versionOptions["custom"].isChecked())

        for title, name in (
            (i18n("Use version number of installed LilyPond"), "lilypond"),
            (i18n("Use version number of last convert-ly rule"), "convert-ly"),
            (i18n("Use custom version number:"), "custom"),
        ):
            self.versionOptions[name] = QRadioButton(title, toggled=changed)

        self.customVersion.setToolTip(i18n("Enter a valid LilyPond version number, e.g. 2.12.0"))
        self.versionOptions["custom"].clicked.connect(lambda: self.customVersion.setFocus())

        grid.addWidget(self.versionOptions["lilypond"], 0, 0, 1, 2)
        grid.addWidget(self.versionOptions["convert-ly"], 1, 0, 1, 2)
        grid.addWidget(self.versionOptions["custom"], 2, 0, 1, 1)
        grid.addWidget(self.customVersion, 2, 1, 1, 1)

    def defaults(self):
        self.customVersion.clear()
        self.versionOptions["lilypond"].setChecked(True)

    def loadSettings(self):
        conf = config("preferences")
        self.customVersion.setText(conf.readEntry("custom version", ""))
        name = conf.readEntry("default version", "")
        if name not in self.versionOptions:
            name = "lilypond"
        self.versionOptions[name].setChecked(True)

    def saveSettings(self):
        conf = config("preferences")
        conf.writeEntry("custom version", self.customVersion.text())
        for name, widget in self.versionOptions.items():
            if widget.isChecked():
                conf.writeEntry("default version", name)
                break
예제 #4
0
class embeddedTerminal(QWidget):

    def __init__(self):
        QWidget.__init__(self)
        self._processes = []
        self.banned_words = ['exit', 'prohibido']
        self.resize(800, 600)
        self.terminal = QWidget(self)
        layout = QVBoxLayout(self)
        layout.addWidget(self.terminal)
        self.kill_tmux()
        
        # self._start_process('tmux', ['new', '-s', 'npy'])
        # self._start_process('tmux', ['detach-client', '-s', 'npy'])

        # self._start_process('xterm',
        #                     ['-geometry', '640x480+0+0', '-into', str(self.terminal.winId()),
        #                      '-e', 'tmux', 'new', '-s', 'npy'])

        self._start_process('xterm', ['-fa', 'Monospace', '-fs', '14', '-geometry', '640x480+0+0', '-into', str(self.terminal.winId()),
                            '-e', 'tmux', 'new', '-s', 'npy'])
        self.textBox = QLineEdit(self)
        self.button = QPushButton('run-in-terminal')
        self.textBox.returnPressed.connect(self.button.click)
        layout.addWidget(self.textBox)
        layout.addWidget(self.button)
        self.textBox.setFocus()
        self.button.clicked.connect(
            lambda: self.run_command(self.textBox.text()))
        self.button.setAutoDefault(True)

    def _start_process(self, prog, args):
        child = QProcess()
        self._processes.append(child)
        child.start(prog, args)

    def run_command(self, command):
        if command not in self.banned_words:
            self._start_process(
                'tmux', ['send-keys', '-t', 'npy:0', command, 'Enter'])
        self.textBox.clear()

    def closeEvent(self, event):
        self.kill_tmux()
        event.accept()

    def kill_tmux(self):
        self._start_process('tmux', ['kill-server'])
예제 #5
0
class NumberFormatDlg(QDialog):

    def __init__(self, format, callback, parent=None):
        super(NumberFormatDlg, self).__init__(parent)

        punctuationRe = QRegExp(r"[ ,;:.]")
        thousandsLabel = QLabel("&Thousands separator")
        self.thousandsEdit = QLineEdit(format["thousandsseparator"])
        thousandsLabel.setBuddy(self.thousandsEdit)
        self.thousandsEdit.setMaxLength(1)
        self.thousandsEdit.setValidator(QRegExpValidator(
                punctuationRe, self))
        decimalMarkerLabel = QLabel("Decimal &marker")
        self.decimalMarkerEdit = QLineEdit(format["decimalmarker"])
        decimalMarkerLabel.setBuddy(self.decimalMarkerEdit)
        self.decimalMarkerEdit.setMaxLength(1)
        self.decimalMarkerEdit.setValidator(QRegExpValidator(
                punctuationRe, self))
        self.decimalMarkerEdit.setInputMask("X")
        decimalPlacesLabel = QLabel("&Decimal places")
        self.decimalPlacesSpinBox = QSpinBox()
        decimalPlacesLabel.setBuddy(self.decimalPlacesSpinBox)
        self.decimalPlacesSpinBox.setRange(0, 6)
        self.decimalPlacesSpinBox.setValue(format["decimalplaces"])
        self.redNegativesCheckBox = QCheckBox("&Red negative numbers")
        self.redNegativesCheckBox.setChecked(format["rednegatives"])

        self.format = format
        self.callback = callback

        grid = QGridLayout()
        grid.addWidget(thousandsLabel, 0, 0)
        grid.addWidget(self.thousandsEdit, 0, 1)
        grid.addWidget(decimalMarkerLabel, 1, 0)
        grid.addWidget(self.decimalMarkerEdit, 1, 1)
        grid.addWidget(decimalPlacesLabel, 2, 0)
        grid.addWidget(self.decimalPlacesSpinBox, 2, 1)
        grid.addWidget(self.redNegativesCheckBox, 3, 0, 1, 2)
        self.setLayout(grid)

        self.connect(self.thousandsEdit,
                SIGNAL("textEdited(QString)"), self.checkAndFix)
        self.connect(self.decimalMarkerEdit,
                SIGNAL("textEdited(QString)"), self.checkAndFix)
        self.connect(self.decimalPlacesSpinBox,
                SIGNAL("valueChanged(int)"), self.apply)
        self.connect(self.redNegativesCheckBox,
                SIGNAL("toggled(bool)"), self.apply)
        self.setWindowTitle("Set Number Format (`Live')")


    def checkAndFix(self):
        thousands = unicode(self.thousandsEdit.text())
        decimal = unicode(self.decimalMarkerEdit.text())
        if thousands == decimal:
            self.thousandsEdit.clear()
            self.thousandsEdit.setFocus()
        if len(decimal) == 0:
            self.decimalMarkerEdit.setText(".")
            self.decimalMarkerEdit.selectAll()
            self.decimalMarkerEdit.setFocus()
        self.apply()


    def apply(self):
        self.format["thousandsseparator"] = (
                unicode(self.thousandsEdit.text()))
        self.format["decimalmarker"] = (
                unicode(self.decimalMarkerEdit.text()))
        self.format["decimalplaces"] = (
                self.decimalPlacesSpinBox.value())
        self.format["rednegatives"] = (
                self.redNegativesCheckBox.isChecked())
        self.callback()
예제 #6
0
class QPyShell(QWidget):
    """QPyShell - a Qt based python command shell based on code.InteractiveInterpreter.
    Because it catches stdout and stderr there can be only one active instance of this
    class. Make sure initInterpreter() and exitInterpreter() is called!
    """

    activeInstance = None

    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        if parent:
            self.standalone = False
        else:
            self.standalone = True

        self.setWindowTitle(QCoreApplication.translate("QPyShell", "QPyShell - a simple python shell widget for Qt"))

        self.mainLayout = QVBoxLayout(self)

        self.outputBrowser = QTextEdit(self)
        self.outputBrowser.setMinimumSize(QSize(100,100))
        self.outputBrowser.setReadOnly(True)
        self.mainLayout.addWidget(self.outputBrowser)

        self.clLayout = QHBoxLayout()
        self.mainLayout.addLayout(self.clLayout)

        self.promptLabel = QLabel()
        self.promptLabel.setText(">>>")
        self.clLayout.addWidget(self.promptLabel)

        self.lineInput = QLineEdit()
        self.lineInput.setToolTip(QCoreApplication.translate('QPyShell', 'The python commandline: enter code her'))
        self.clLayout.addWidget(self.lineInput)

        self.enterButton = QToolButton(self)
        self.enterButton.setText(QCoreApplication.translate("QPyShell", "Enter"))
        self.enterButton.setToolTip(QCoreApplication.translate('QPyShell', 'This button or [Enter] executes the command'))
        self.enterButton.setIcon(QIcon(QPixmap(enterXPM)))
        self.clLayout.addWidget(self.enterButton)

        self.clLayout.addSpacing(8)

        self.clearButton = QToolButton(self)
        self.clearButton.setText(QCoreApplication.translate("QPyShell", "Clear"))
        self.clearButton.setToolTip(QCoreApplication.translate('QPyShell', 'Clear the output window'))
        self.clearButton.setIcon(QIcon(QPixmap(clearXPM)))
        self.clLayout.addWidget(self.clearButton)

        self.saveButton = QToolButton(self)
        self.saveButton.setText(QCoreApplication.translate("QPyShell", "Save ..."))
        self.saveButton.setToolTip(QCoreApplication.translate('QPyShell', 'Save the contents of the output window'))
        self.saveButton.setIcon(QIcon(QPixmap(saveXPM)))
        self.clLayout.addWidget(self.saveButton)

        self.printButton = QToolButton(self)
        self.printButton.setText(QCoreApplication.translate("QPyShell", "Print"))
        self.printButton.setToolTip(QCoreApplication.translate('QPyShell', 'Print the contents of the output window'))
        self.printButton.setIcon(QIcon(QPixmap(printXPM)))
        self.clLayout.addWidget(self.printButton)

        self.history = []
        self.historyFile = None
        self.history_i = -1
        self.cmdBuffer = []
        self.showCompletionLimit = 100
        self.interpreter = None
        self.old_displayhook = None
        self.cursor = QTextCursor(self.outputBrowser.document())
        self.outputBrowser.setTextCursor(self.cursor)
        self.outputBrowser.append(greeting)

        self.setTabOrder(self.lineInput, self.outputBrowser)
        self.setTabOrder(self.outputBrowser, self.enterButton)
        self.setTabOrder(self.enterButton, self.saveButton)
        self.setTabOrder(self.saveButton, self.clearButton)

        self.connect(self.enterButton, SIGNAL("pressed()"), self.run)
        self.connect(self.saveButton, SIGNAL("pressed()"), self.saveContents)
        self.connect(self.printButton, SIGNAL("pressed()"), self.printContents)
        self.connect(self.clearButton, SIGNAL("pressed()"), self.outputBrowser.clear)


    def initInterpreter(self, loc=None, greet=greeting, historyFile=None):
        if QPyShell.activeInstance:
            raise Exception(QCoreApplication.translate("QPyShell", "QPyShell: There can be only one highlander... sorry, I mean one active QPyShell widget!"))
        QPyShell.activeInstance = self
        self.loadHistoryFile(historyFile)
        self.interpreter = InteractiveInterpreter(loc)
        self.completer = Completer(loc)
        self.old_stdout = sys.stdout
        self.old_stderr = sys.stderr
        sys.stdout = DummyFileW(self.write)
        sys.stderr = sys.stdout
        # there's a strange problem with gettext and interactive interpreters
        # gettext's "_"" will be overwritten by the standard sys.displayhook...
        self.old_displayhook = sys.displayhook
        sys.displayhook = mydisplayhook


    def loadHistoryFile(self, historyFile):
        self.historyFile = historyFile
        if historyFile and os.path.exists(historyFile):
            lines = open(historyFile, 'r').read().split(os.linesep)
            self.history = [l for l in lines if not l.startswith('#')]


    def saveHistoryFile(self):
        if self.historyFile:
            h = self.history
            if len(h) > 100:
                h = h[:100]
            h.insert(0, unicode(QCoreApplication.translate('QPyShell', '# this is the command history of the QPyShell')))
            open(self.historyFile, 'w').write(os.linesep.join(h))


    def exitInterpreter(self, loc=None):
        sys.stdout = self.old_stdout
        sys.stderr = self.old_stderr
        self.saveHistoryFile()
        del self.interpreter
        self.interpreter = None
        sys.displayhook = self.old_displayhook
        QPyShell.ativeInstance = None


    def run(self):
        if not self.interpreter:
            raise Exception(QCoreApplication.translate("QPyShell", "No interpreter found! You need to call QPyShell.initInterpreter() first!"))
        line = unicode(self.lineInput.text())
        self.lineInput.clear()
        if line:
            if (not self.history) or line != self.history[0]:
                # no consecutive identical entries
                self.history.insert(0, line)
            self.history_i = -1
            self.cursor.movePosition(QTextCursor.End)
            if not self.cmdBuffer:
                self.cursor.insertHtml('<br><b>|&gt;&gt;&gt;&nbsp;%s</b><br>' % formatPyLine(line))
            else:
                self.cursor.insertHtml('<br><b>|.&nbsp;.&nbsp;.&nbsp;&nbsp;%s</b><br>' % formatPyLine(line))
            self.cursor.movePosition(QTextCursor.End)
            self.outputBrowser.ensureCursorVisible()
        self.cmdBuffer.append(line)
        more = self.interpreter.runsource('\n'.join(self.cmdBuffer))
        if more:
            self.promptLabel.setText('...')
        else:
            self.cmdBuffer = []
            self.promptLabel.setText('>>>')


    def appendHtml(self, txt):
        self.cursor.movePosition(QTextCursor.End)
        self.cursor.insertHtml(txt)
        self.cursor.movePosition(QTextCursor.End)
        self.outputBrowser.ensureCursorVisible()


    def appendText(self, txt):
        self.cursor.movePosition(QTextCursor.End)
        self.outputBrowser.insertPlainText(txt)
        self.cursor.movePosition(QTextCursor.End)
        self.outputBrowser.ensureCursorVisible()


    write = appendText


    def keyPressEvent(self, event):
        key = event.key()
        mod = event.modifiers()
        if key == Qt.Key_Up and self.history:
            self.history_i = min(self.history_i+1, len(self.history)-1)
            self.lineInput.setText(self.history[self.history_i])
        elif key == Qt.Key_Down and self.history:
            self.history_i = max(self.history_i-1, -1)
            if self.history_i >= 0:
                self.lineInput.setText(self.history[self.history_i])
            else:
                self.lineInput.setText('')
        elif key == Qt.Key_Enter or key == Qt.Key_Return:
            if mod & Qt.ShiftModifier:
                self.complete()
            else:
                self.run()
        elif key == Qt.Key_Escape:
            txt, r = QInputDialog.getItem(self, QCoreApplication.translate("QPyShell", "Command line history"),
                QCoreApplication.translate("QPyShell", "Please select a history item:"),
                self.history, 0, False)
            if r and txt:
                self.lineInput.setText(txt)
        elif self.standalone and key == Qt.Key_Print:
            self.printContents()
        elif self.standalone and key == Qt.Key_Q and (mod & Qt.ControlModifier):
            self.close()
        else:
            QWidget.keyPressEvent(self, event)


    def closeEvent(self, event):
        if self.standalone:
            self.exitInterpreter()
        QWidget.closeEvent(self, event)


    def printContents(self, printer=None):
        if not printer:
            printer = QPrinter()
        dialog = QPrintDialog(printer, self)
        dialog.setWindowTitle(QCoreApplication.translate("QPyShell", "Print Document"))
        if dialog.exec_() != QDialog.Accepted:
            return
        self.outputBrowser.document().print_(printer)


    def saveContents(self, fileName=None):
        if not fileName:
            fileTypes = {'Text':('txt',), 'HTML':('htm', 'html')}
            filters = ';;'.join(['%s (%s)' % (k, ' '.join(['*.'+e for e in v])) for k, v in fileTypes.items()])
            dlg = QFileDialog(self,
                QCoreApplication.translate('QPyShell', 'Select name of file to save'),
                os.getcwd(), filters)
            dlg.setFileMode(QFileDialog.AnyFile)
            dlg.setAcceptMode(QFileDialog.AcceptSave)
            if dlg.exec_() != QDialog.Accepted:
                return
            tmp = unicode(dlg.selectedFilter())
            fileType = tmp[:tmp.find('(')-1]
            dlg.setDefaultSuffix(fileTypes[fileType][0])
            files = dlg.selectedFiles()
            if not files:
                return
            fileName = unicode(files[0])
        if fileType == 'Text':
            txt = self.outputBrowser.toPlainText()
        elif fileType == 'HTML':
            txt = self.outputBrowser.toHtml()
        else:
            raise IOError('Unknown FileType: %s' % fileType)
        try:
            open(fileName, 'w').write(txt)
        except IOError:
            QMessageBox.critical(self,
                QCoreApplication.translate('QPyShell', 'Could not save file!'),
                QCoreApplication.translate('QPyShell', 'Writing failed! Make sure you have write permissions!'))


    def complete(self):
        """ a very simple, quick and dirty completion of identifiers in the namespace """
        # FIXME: fertig machen!
        txt = unicode(self.lineInput.text())
        cur = self.lineInput.cursorPosition()
        s = cur
        while s>0 and txt[s-1] in identChars:
            s -= 1
        try:
            completions = self.completer.matches(txt[s:cur])
        except:
            return
        if not completions:
            return
        n_comp = len(completions)
        if n_comp == 1:
            comp = completions.pop()
            self.lineInput.insert(comp[cur-s:])
        elif n_comp < self.showCompletionLimit:
            tmp = list(completions)
            tmp.sort()
            self.appendHtml('<font color="#0000ff">[%s]</font>' % ', '.join(tmp))
            # get common prefix ... stolen from the python cookbook
            pref = tmp[0][:([min([x[0]==elem for elem in x]) for x in zip(*tmp)]+[0]).index(0)]
            if len(pref) > (cur-s):
                self.lineInput.insert(pref[cur-s:])
        else:
            self.appendHtml(unicode(QCoreApplication.translate("QPyShell",
                '<font color="#0000ff">[Too many completions: %d]</font>')) % n_comp)
예제 #7
0
class MyWidget(QWidget):
    def __init__(self):
        super(MyWidget, self).__init__()
        self.i = 0
        self.setup_window()
        t = threading.Thread(target=self.setup_networking)
        t.start()

    def setup_window(self):
        self.setWindowTitle("Chat app")
        self.setGeometry(100, 100, 400, 300)

        self.layout = QVBoxLayout(self)
        self.setLayout(self.layout)

        self.label = QLabel(self)
        self.textbox = QLineEdit(self)
        self.textbox.setReadOnly(True)

        self.layout2 = QHBoxLayout(self)

        self.chathistory = QTextEdit(self)
        self.chathistory.setReadOnly(True)

        self.widget2 = QWidget()
        self.widget2.setLayout(self.layout2)

        self.layout.addWidget(self.textbox)
        self.layout.addWidget(self.chathistory)
        self.layout2.addWidget(self.label)

        self.layout.addWidget(self.widget2)

        #first it'll try to be client and fail. So it will be server. Next time it'll be client
#
#        t3=threading.Thread(target=self.be_client)
#        t3.start()
#        t4=threading.Thread(target=self.be_server)
#        t4.start()

    def setup_networking(self):
        try:
            self.be_client()
        except:
            print "unable to connect as client, opening server mode:\n"
            self.be_server()

        self.textbox.setReadOnly(False)
        t2 = threading.Thread(target=self.recv_message)
        t2.start()
        self.textbox.returnPressed.connect(
            self.send_message)  #if they press enter, then call send_message fn
#        self.isclosed = False #doesnt work

    def be_client(self):
        host = '127.0.0.1'
        port = 5000
        self.s = socket.socket()
        print "client socket opened"
        self.i = t(self.i, True)
        self.s.connect((host, port))
        self.label.setText("<connected>")

    def be_server(self):
        host = '127.0.0.1'
        port = 5000
        self.ss = socket.socket()
        print "temp sock open"
        self.i = t(self.i, True)
        self.ss.bind((host, port))
        self.ss.listen(1)
        self.label.setText("<waiting to be connected>")
        self.s, self.address = self.ss.accept(
        )  #address is  ip address of what tries to connect
        self.ss.close()
        print "temp client socket closed"
        self.i = t(self.i, False)
        self.label.setText("<connected>")

    def send_message(self):
        message = self.textbox.text()
        if message != "":
            self.chathistory.append("Sent: " + str(message))
            self.s.send(message)
            self.textbox.clear()
        else:
            t2 = threading.Thread(target=self.recv_message)
            t2.start()
        sys.stdout.flush()

    def loner(self):
        self.label.setText("<Connection Lost>")
        print "socket closed"
        self.s.close()
        self.i = t(self.i, False)
        print "^should be zero"
        self.textbox.setReadOnly(True)
        self.be_server()
        self.textbox.setReadOnly(False)
        t2 = threading.Thread(target=self.recv_message)
        t2.start()

    def recv_message(self):
        #        try: #so it doesn't keep saying socket.timeout on console
        if 1 == 1:
            data = self.s.recv(1024)
            #            print self.isclosed
            #            if self.isclosed is True: #gonna send a blank message when u close window
            #                self.label.setText("<connection closed>")
            #                print "got here"
            if data == "<close command>":
                print "Cmnd received"
                self.loner()
#                self.label.setText("<Connection Lost>")
#                print "socket closed"
#                self.i = t(self.i, False)
#                print "^should be zero"
#                self.s.close()
#                self.textbox.setReadOnly(True)
#                self.setup_networking()
            else:
                self.chathistory.append("Recieved: " + str(data))
            sys.stdout.flush()


#        except socket.timeout: #we dont want it to keep saying it on the console
#            pass
#        except socket.error: #when it closes, need to make a new socket
#            self.s = socket.socket()

    def closeEvent(self, e):
        self.s.send("<close command>")
        print "cmd sent"
        print "closed window"
        #self.isclosed=True
        print "socket closed"
        self.i = t(self.i, False)
        print "^ should be zero"
        self.s.close()
예제 #8
0
class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setWindowTitle('Address Book')
        self.resize(704, 459)
        self.db_file = self.database_file()
        self.db = database.Database(self.db_file)

        dialog = dialogs.UserPanelDlg(self)
        if dialog.exec_():
            self.user = dialog.user
        else:
            self.close()

        self.categComboBox = QComboBox()
        self.cont_numLabel = QLabel()
        self.contactsListWidget = QListWidget()
        self.searchLineEdit = QLineEdit()

        widgets = ((QLabel('Category:'), self.categComboBox),
                   (self.cont_numLabel, None),
                   (self.contactsListWidget,),
                   (QLabel('Search:'), self.searchLineEdit))
        vlayout1 = QVBoxLayout()

        for i in widgets:
            hlayout = pyqttools.add_to_layout(QHBoxLayout(), i)
            vlayout1.addLayout(hlayout)

        addToolButton = QToolButton()
        addToolButton.setIcon(QIcon(':addcontact.jpeg'))
        addToolButton.setIconSize(QSize(45, 45))
        self.showLabel = QLabel()
        self.showLabel.setFrameShape(QFrame.StyledPanel)
        self.showLabel.setAlignment(Qt.AlignLeading|Qt.AlignLeft|Qt.AlignTop)
        self.editButton = QPushButton('Edit')
        self.delButton = QPushButton('Delete')

        widgets = ((None, addToolButton, None),
                   (self.showLabel,),
                   (None, self.editButton, self.delButton))
        vlayout2 = QVBoxLayout()

        for i in widgets:
            hlayout = pyqttools.add_to_layout(QHBoxLayout(), i)
            vlayout2.addLayout(hlayout)

        f_layout = pyqttools.add_to_layout(QHBoxLayout(), (vlayout1, vlayout2))

        Widget = QWidget()
        Widget.setLayout(f_layout)
        self.setCentralWidget(Widget)

        self.statusBar = self.statusBar()
        self.userLabel = QLabel()
        self.statusBar.addPermanentWidget(self.userLabel)

        c_action = pyqttools.create_action
        panelAction = c_action(self, 'User panel', triggered=self.user_panel)
        quitAction = c_action(self, 'Quit', 'Ctrl+Q',triggered=self.close)
        add_contactAction = c_action(self, 'Add contact', 'Ctrl+N',
                                                    triggered=self.add_contact)
        delete_allAction = c_action(self, 'Delete all contacts',
                                                     triggered=self.delete_all)
        delete_categAction = c_action(self, 'Delete categories',
                                              triggered=self.delete_categories)
        backupAction = c_action(self, 'Backup', triggered=self.backup)
        restoreAction = c_action(self, 'Restore', triggered=self.restore)
        aboutAction = c_action(self, 'About', 'Ctrl+?', triggered=self.about)

        fileMenu = self.menuBar().addMenu('File')
        contactsMenu = self.menuBar().addMenu('Contacts')
        deleteMenu = self.menuBar().addMenu(self.tr('Delete'))
        backupMenu = self.menuBar().addMenu(self.tr('Backup'))
        helpMenu = self.menuBar().addMenu('Help')

        pyqttools.add_actions(fileMenu, [panelAction, None, quitAction])
        pyqttools.add_actions(contactsMenu, [add_contactAction])
        pyqttools.add_actions(deleteMenu,[delete_allAction,delete_categAction])
        pyqttools.add_actions(backupMenu, [backupAction, restoreAction])
        pyqttools.add_actions(helpMenu, [aboutAction])

        addToolButton.clicked.connect(self.add_contact)
        self.editButton.clicked.connect(self.edit_contact)
        self.delButton.clicked.connect(self.delete_contact)
        self.categComboBox.currentIndexChanged.connect(self.fill_ListWidget)
        self.contactsListWidget.currentRowChanged.connect(self.show_contact)
        self.searchLineEdit.textEdited.connect(self.search)

        self.fill_categComboBox()
        self.refresh_userLabel()

    def fill_categComboBox(self):
        categories = ['All']
        categories.extend([i[1] for i in self.db.get_categories(self.user)])
        self.categComboBox.currentIndexChanged.disconnect(self.fill_ListWidget)
        self.categComboBox.clear()
        self.categComboBox.addItems(categories)
        self.categComboBox.currentIndexChanged.connect(self.fill_ListWidget)
        self.fill_ListWidget()

    def fill_ListWidget(self):
        self.showLabel.clear()
        self.contactsListWidget.clear()
        if self.categComboBox.currentIndex() != 0: self.searchLineEdit.clear()

        category = self.categComboBox.currentText()
        if category == 'All':
            contacts = self.db.get_all_contacts(self.user)
        else:
            categ_id = self.db.get_category_id(category, self.user)
            if categ_id is None: return
            contacts = self.db.get_contacts(categ_id)
        for i in contacts:
            self.contactsListWidget.addItem(MyListItem(i[1]+' '+i[2], i[0]))

        self.contactsListWidget.setCurrentRow(0)
        self.refresh_contacts_number()
        self.set_buttons_enabled()

    def refresh_userLabel(self):
        self.userLabel.setText('User:  '******'Contacts Numer:  {0}'.format(self.contactsListWidget.count())
        self.cont_numLabel.setText(text)

    def set_buttons_enabled(self):
        enable = bool(self.contactsListWidget)
        self.editButton.setEnabled(enable)
        self.delButton.setEnabled(enable)

    def user_panel(self):
        dialog = dialogs.UserPanelDlg(self)
        if dialog.exec_():
            self.user = dialog.user
            self.fill_categComboBox()
            self.refresh_userLabel()

    def show_contact(self):
        try:
            _id = self.contactsListWidget.currentItem()._id
        except AttributeError:
            return
        _id, name, surname, mail, address, tel, categ_id = \
                                           self.db.get_contact_from_id(_id)[0]
        category = self.db.get_category_from_id(categ_id)
        text = ''
        data = (name, surname, mail, address, tel, category)
        labs = ('Name', 'Surname', 'e-mail', 'Address', 'Telephone', 'Category')
        for i, y in zip(labs, data):
            text += '''<p style=\' margin-top:0px; margin-bottom:0px; \'>
                  <span style=\' font-weight:600;\'>{0}:</span> {1} </p>\n'''\
                                                                  .format(i, y)
        self.showLabel.setText(text)

    def add_contact(self):
        categories = [i[1] for i in self.db.get_categories(self.user)]
        dialog = dialogs.AddorEditContactDlg(categories)
        if dialog.exec_():
            data = dialog.values
            if data[-1] not in categories:
                self.db.addto_categories(data[-1], self.user)
            categ_id = self.db.get_category_id(data[-1], self.user)
            data[-1] = categ_id
            self.db.addto_contacts(data)
            self.fill_categComboBox()

    def edit_contact(self):
        _id = self.contactsListWidget.currentItem()._id
        data = list(self.db.get_contact_from_id(_id)[0])
        categ = self.db.get_category_from_id(data[-1])
        data[-1] = categ
        categories = [i[1] for i in self.db.get_categories(self.user)]
        dialog = dialogs.AddorEditContactDlg(categories, True, data)
        if dialog.exec_():
            new_data = dialog.values
            if new_data[-1] not in categories:
                self.db.addto_categories(new_data[-1], self.user)
            categ_id = self.db.get_category_id(new_data[-1], self.user)
            new_data[-1] = categ_id
            self.db.edit_contact(new_data, _id)
            self.fill_categComboBox()

    def delete_contact(self):
        reply = QMessageBox.question(self, 'Address Book - Delete Contact',
        'Are you sure that you want to delete this contact?',
        QMessageBox.Yes|QMessageBox.Cancel)
        if reply == QMessageBox.Yes:
            _id = self.contactsListWidget.currentItem()._id
            self.db.delete_contact(_id)
            self.fill_ListWidget()

    def delete_all(self):
        reply = QMessageBox.question(self, 'Address Book - Delete Contact',
        'Are you sure that you want to delete all contacts?',
        QMessageBox.Yes|QMessageBox.Cancel)
        if reply == QMessageBox.Yes:
            self.db.delete_all_contacts()
            self.fill_ListWidget()

    def delete_categories(self):
        categories = [i[1] for i in self.db.get_categories(self.user)]
        dialogs.DelCategoriesDlg(categories, self).exec_()
        self.fill_categComboBox()

    def search(self):
        self.categComboBox.setCurrentIndex(0)
        self.showLabel.clear()
        self.contactsListWidget.clear()

        txt = self.searchLineEdit.text()

        if all(i == ' ' for i in txt):
            self.fill_ListWidget()
            return

        must_appear = []
        contacts = self.db.get_all_contacts(self.user)

        if not ' ' in txt:
            for i in contacts:
                if txt.lower() in i[1].lower() or txt.lower() in i[2].lower():
                    must_appear.append(i)
        else:
            try:
                first, last = txt.split()
            except ValueError:
                return
            for i in contacts:
                _bool = bool(first.lower() in i[1].lower() or first.lower() in
                             i[2].lower() or last.lower() in i[1].lower() or
                             last.lower() in i[2].lower())
                if _bool: must_appear.append(i)

        for i in must_appear:
            item = MyListItem(i[1] + ' ' + i[2], i[0])
            self.contactsListWidget.addItem(item)

        self.contactsListWidget.setCurrentRow(0)
        self.refresh_contacts_number()
        self.set_buttons_enabled()

    def backup(self):
        fname = QFileDialog.getSaveFileName(self,'Address Book - Backup','.db')
        if fname:
            try:
                shutil.copy(self.db_file, fname)
            except IOError:
                pass

    def restore(self):
        reply = QMessageBox.question(self, 'Address Book - Restore',
            'All current contacts will be deleted.\nAre you sure that you want'
            ' to continue?', QMessageBox.Yes|QMessageBox.Cancel)
        if reply == QMessageBox.Yes:
            fname = QFileDialog.getOpenFileName(self, 'Address Book - Restore')
            if fname:
                msg = 'Succesful restore!'
                try:
                    os.remove(self.db_file)
                    shutil.copy(fname, self.db_file)
                except (OSError, IOError):
                    msg = 'Restore failed!'
                QMessageBox.information(self, 'Addess Book - Restore', msg)
                self.db = database.Database(self.db_file)
                self.fill_categComboBox()

    def database_file(self):
        _file = 'addressbook.db'
        if not platform.platform().startswith('Windows'):
            folder = os.getenv('HOME') + os.sep + '.addressbook'
            if not os.path.exists(folder): os.mkdir(folder)
            _file = folder + os.sep + _file
        return _file

    def about(self):
        link = 'http://wiki.ubuntu-gr.org/Address%20Book'
        QMessageBox.about(self, self.tr('About') + ' FF Multi Converter',
            '''<b> Address Book {0} </b>
            <p>Gui application to organize your contacts!
            <p>Copyright &copy; 2012 Ilias Stamatis
            <br>License: GNU GPL3
            <p><a href='{1}'>http://wiki.ubuntu-gr.org/Address Book</a>
            <p>Python {2} - Qt {3} - PyQt {4} on {5}'''
            .format(__version__, link, platform.python_version()[:5],
            QT_VERSION_STR, PYQT_VERSION_STR, platform.system()))

    def close(self):
        self.db.close()
        sys.exit()
예제 #9
0
class bookDiag(QDialog):
    def __init__(self, parent):
        QDialog.__init__(self)
        self.setWindowTitle("Add bookmark entry")
        self.init(parent)
        self.initShape()

    def init(self, parent):
        self.bookmark = parent
        self.heditor = self.bookmark.heditor

    def createButtons(self):
        self.buttonbox = QDialogButtonBox()
        self.buttonbox.setStandardButtons(QDialogButtonBox.Cancel
                                          | QDialogButtonBox.Ok)
        self.connect(self.buttonbox, SIGNAL("accepted()"), self.accept)
        self.connect(self.buttonbox, SIGNAL("rejected()"), self.reject)
        return self.buttonbox

    def initShape(self):
        self.grid = QGridLayout()

        decoration = self.createDecoration()
        wButton = self.createButtons()
        wInfos = self.createInformations()

        self.grid.addWidget(decoration, 0, 0)
        self.grid.addWidget(wInfos, 1, 0)
        self.grid.addWidget(wButton, 2, 0)

        self.setLayout(self.grid)

    def createDecoration(self):
        self.deco = QWidget()
        self.hdeco = QHBoxLayout()

        pixlabel = QLabel()
        pix = QPixmap(":bookmark.png")
        pixlabel.setPixmap(pix)

        booklabel = QLabel("Add a description to this entry")

        self.hdeco.addWidget(pixlabel)
        self.hdeco.addWidget(booklabel)

        self.deco.setLayout(self.hdeco)
        return self.deco

    def createInformations(self):
        self.info = QWidget()
        self.igrid = QGridLayout()

        addressLabel = QLabel("Address: ")
        self.address = QLineEdit()
        self.address.setReadOnly(True)

        lend = QLabel("Length (dec): ")
        self.lendec = QLineEdit()
        self.lendec.setReadOnly(True)

        lenh = QLabel("Length (hex): ")
        self.lenhex = QLineEdit()
        self.lenhex.setReadOnly(True)

        deslabel = QLabel("Description: ")
        self.description = QLineEdit()

        hvlabel = QLabel("Hex value:")
        self.hexvalue = QLineEdit()
        self.hexvalue.setReadOnly(True)

        avlabel = QLabel("Ascii value:")
        self.asciivalue = QLineEdit()
        self.asciivalue.setReadOnly(True)

        self.igrid.addWidget(addressLabel, 0, 0, Qt.AlignLeft)
        self.igrid.addWidget(self.address, 0, 1, Qt.AlignLeft)

        self.igrid.addWidget(lend, 1, 0, Qt.AlignLeft)
        self.igrid.addWidget(self.lendec, 1, 1, Qt.AlignLeft)

        self.igrid.addWidget(lenh, 2, 0, Qt.AlignLeft)
        self.igrid.addWidget(self.lenhex, 2, 1, Qt.AlignLeft)

        self.igrid.addWidget(hvlabel, 3, 0, Qt.AlignLeft)
        self.igrid.addWidget(self.hexvalue, 3, 1, Qt.AlignLeft)

        self.igrid.addWidget(avlabel, 4, 0, Qt.AlignLeft)
        self.igrid.addWidget(self.asciivalue, 4, 1, Qt.AlignLeft)

        self.igrid.addWidget(deslabel, 5, 0, Qt.AlignLeft)
        self.igrid.addWidget(self.description, 5, 1, Qt.AlignLeft)

        self.info.setLayout(self.igrid)

        return self.info

    def cleanInformations(self):
        self.address.clear()
        self.lendec.clear()
        self.lenhex.clear()
        self.hexvalue.clear()
        self.asciivalue.clear()
        self.description.clear()

    def setInformations(self):
        self.cleanInformations()

        if self.heditor.decimalview:
            add = "%.2d" % self.heditor.selection.startoffset
        else:
            add = "0x"
            add += "%.2x" % self.heditor.selection.startoffset
        self.address.insert(add)

        if self.heditor.selection.length > 0:
            len = self.heditor.selection.length
        else:
            len = 1
        tolendec = "%.1d" % len
        self.lendec.insert(tolendec)

        tolenhex = "0x"
        tolenhex += "%.1X" % len
        self.lenhex.insert(tolenhex)

        hval = self.heditor.readHexValue(self.heditor.selection.offset, len)
        self.hexvalue.insert(hval)

        aval = self.heditor.readAsciiValue(self.heditor.selection.offset, len)
        self.asciivalue.insert(aval)
예제 #10
0
class DefaultAttributeHandler(QGroupBox, AbstractAttributeHandler):
    def __init__(self, attribute, values, parent=None):
        QGroupBox.__init__(self, attribute, parent)
        self._attribute = attribute
        self._current_items = []
        self._defaults = {}
        self._inputField = None
        self._inputFieldType = None
        self._insertIndex = -1
        self._insertAtEnd = False
        self._shortcuts = {}

        # Setup GUI
        self._layout = FloatingLayout()
        self.setLayout(self._layout)
        self._buttons = {}

        # Add interface elements
        self.updateValues(values)

    def focusInputField(self, selectInput=True):
        if self._inputField is not None:
            if selectInput:
                self._inputField.selectAll()
            self._inputField.setFocus(Qt.ShortcutFocusReason)

    def addShortcut(self, shortcut, widget, value):
        if widget is not None:
            if shortcut not in self._shortcuts:
                sc = QShortcut(QKeySequence(shortcut), self)
                self._shortcuts[shortcut] = sc
                if isinstance(widget, QPushButton):
                    sc.activated.connect(bind(lambda w: w.click() if not w.isChecked() else None, widget))
                elif isinstance(widget, QLineEdit):
                    sc.activated.connect(self.focusInputField)
            else:
                raise ImproperlyConfigured("Shortcut '%s' defined more than once" % shortcut)
        else:
            raise ImproperlyConfigured("Shortcut '%s' defined for value '%s' which is hidden" % (shortcut, value))

    def updateValues(self, values):
        if isinstance(values, type):
            self.addInputField(values)
        else:
            for val in values:
                v = val
                shortcut = None
                widget = None

                # Handle the case of the value being a 2-tuple consisting of (value, shortcut)
                if type(val) is tuple or type(val) is list:
                    if len(val) == 2:
                        v = val[0]
                        shortcut = val[1]
                    else:
                        raise ImproperlyConfigured("Values must be types, strings, numbers, or tuples of length 2: '%s'" % str(val))

                # Handle the case where value is a Python type
                if isinstance(v, type):
                    if v is float or v is int or v is str:
                        self.addInputField(v)
                        widget = self._inputField
                    else:
                        raise ImproperlyConfigured("Input field with type '%s' not supported" % v)

                # * marks the position where buttons for new values will be insered
                elif val == "*" or val == "<*":
                    self._insertIndex = self._layout.count()
                elif val == "*>":
                    self._insertIndex = self._layout.count()
                    self._insertAtEnd = True

                # Add the value button
                else:
                    self.addValue(v)
                    widget = self._buttons[v]

                # If defined, add the specified shortcut
                if shortcut is not None:
                    self.addShortcut(shortcut, widget, v)

    def defaults(self):
        return self._defaults

    def autoAddEnabled(self):
        return self._insertIndex >= 0

    def onInputFieldReturnPressed(self):
        val = str(self._inputField.text())
        self.addValue(val, True)
        for item in self._current_items:
            item[self._attribute] = val
        self.updateButtons()
        self.updateInputField()
        self._inputField.clearFocus()

    def addInputField(self, _type):
        if self._inputField is None:
            self._inputFieldType = _type
            self._inputField = QLineEdit()
            if _type is float:
                self._inputField.setValidator(QDoubleValidator())
            elif _type is int:
                self._inputField.setValidator(QIntValidator())

            self._layout.addWidget(self._inputField)
            self._inputField.returnPressed.connect(self.onInputFieldReturnPressed)
        elif self._inputFieldType is not _type:
            raise ImproperlyConfigured("Input field for attribute '%s' configured twice with different types %s != %s"\
                    % (self._attribute, self._inputFieldType, _type))

    def addValue(self, v, autoAddValue=False):
        if v in self._buttons: return
        if autoAddValue and self._insertIndex < 0: return
        button = QPushButton(v, self)
        button.setFlat(True)
        button.setCheckable(True)
        self._buttons[v] = button
        if autoAddValue:
            self._layout.insertWidget(self._insertIndex, button)
            if self._insertAtEnd:
                self._insertIndex += 1
        else:
            self._layout.addWidget(button)
        button.clicked.connect(bind(self.onButtonClicked, v))

    def reset(self):
        self._current_items = []
        for v, button in self._buttons.items():
            button.setChecked(False)
            button.setFlat(True)

    def getSelectedValues(self):
        return set([str(item[self._attribute]) for item in self._current_items if self._attribute in item and item[self._attribute] is not None])

    def updateInputField(self):
        if self._inputField is not None:
            self._inputField.clear()
            selected_values = self.getSelectedValues()
            if len(selected_values) > 1:
                self._inputField.setPlaceholderText(", ".join(selected_values))
            elif len(selected_values) == 1:
                it = iter(selected_values)
                self._inputField.setText(next(it))

    def updateButtons(self):
        selected_values = self.getSelectedValues()
        for val, button in self._buttons.items():
            if val in selected_values:
                if len(selected_values) > 1:
                    button.setFlat(False)
                    button.setChecked(False)
                else:
                    button.setFlat(True)
                    button.setChecked(True)
            else:
                button.setFlat(True)
                button.setChecked(False)

    def setItems(self, items, showItemClasses=False):
        self.reset()
        if showItemClasses:
            title = ", ".join(set([item['class'] for item in items]))
            self.setTitle(self._attribute + " (" + title + ")")
        else:
            self.setTitle(self._attribute)

        self._current_items = items

        self.updateButtons()
        self.updateInputField()

    def onButtonClicked(self, val):
        attr = self._attribute
        LOG.debug("Button %s: %s clicked" % (attr, val))
        button = self._buttons[val]

        # Update model item
        for item in self._current_items:
            if button.isChecked():
                item[attr] = val
            else:
                item[attr] = None

        # Unpress all other buttons
        for v, but in self._buttons.items():
            but.setFlat(True)
            if but is not button:
                but.setChecked(False)

        # Update input field
        self.updateInputField()
예제 #11
0
class IgnoredExceptionsViewer(QWidget):
    " Implements the client exceptions viewer for a debugger "

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

        self.__createPopupMenu()
        self.__createLayout()
        self.__ignored = []
        self.__currentItem = None

        GlobalData().project.projectChanged.connect(self.__onProjectChanged)

        if Settings().showIgnoredExcViewer == False:
            self.__onShowHide(True)
        return

    def __createPopupMenu(self):
        " Creates the popup menu "
        self.__excptMenu = QMenu()
        self.__removeMenuItem = self.__excptMenu.addAction(
            PixmapCache().getIcon('ignexcptdel.png'),
            "Remove from ignore list", self.__onRemoveFromIgnore)
        return

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

        verticalLayout = QVBoxLayout(self)
        verticalLayout.setContentsMargins(0, 0, 0, 0)
        verticalLayout.setSpacing(0)

        self.headerFrame = QFrame()
        self.headerFrame.setFrameStyle(QFrame.StyledPanel)
        self.headerFrame.setAutoFillBackground(True)
        headerPalette = self.headerFrame.palette()
        headerBackground = headerPalette.color(QPalette.Background)
        headerBackground.setRgb(min(headerBackground.red() + 30, 255),
                                min(headerBackground.green() + 30, 255),
                                min(headerBackground.blue() + 30, 255))
        headerPalette.setColor(QPalette.Background, headerBackground)
        self.headerFrame.setPalette(headerPalette)
        self.headerFrame.setFixedHeight(24)

        self.__excptLabel = QLabel("Ignored exception types")

        expandingSpacer = QSpacerItem(10, 10, QSizePolicy.Expanding)
        fixedSpacer = QSpacerItem(3, 3)

        self.__showHideButton = QToolButton()
        self.__showHideButton.setAutoRaise(True)
        self.__showHideButton.setIcon(PixmapCache().getIcon('less.png'))
        self.__showHideButton.setFixedSize(20, 20)
        self.__showHideButton.setToolTip("Hide ignored exceptions list")
        self.__showHideButton.setFocusPolicy(Qt.NoFocus)
        self.__showHideButton.clicked.connect(self.__onShowHide)

        headerLayout = QHBoxLayout()
        headerLayout.setContentsMargins(1, 1, 1, 1)
        headerLayout.addSpacerItem(fixedSpacer)
        headerLayout.addWidget(self.__excptLabel)
        headerLayout.addSpacerItem(expandingSpacer)
        headerLayout.addWidget(self.__showHideButton)
        self.headerFrame.setLayout(headerLayout)

        self.exceptionsList = QTreeWidget(self)
        self.exceptionsList.setSortingEnabled(False)
        self.exceptionsList.setAlternatingRowColors(True)
        self.exceptionsList.setRootIsDecorated(False)
        self.exceptionsList.setItemsExpandable(True)
        self.exceptionsList.setUniformRowHeights(True)
        self.exceptionsList.setSelectionMode(QAbstractItemView.SingleSelection)
        self.exceptionsList.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.exceptionsList.setItemDelegate(NoOutlineHeightDelegate(4))
        self.exceptionsList.setContextMenuPolicy(Qt.CustomContextMenu)

        self.exceptionsList.customContextMenuRequested.connect(
            self.__showContextMenu)
        self.exceptionsList.itemSelectionChanged.connect(
            self.__onSelectionChanged)
        self.exceptionsList.setHeaderLabels(["Exception type"])

        self.__excTypeEdit = QLineEdit()
        self.__excTypeEdit.setFixedHeight(26)
        self.__excTypeEdit.textChanged.connect(self.__onNewFilterChanged)
        self.__excTypeEdit.returnPressed.connect(self.__onAddExceptionFilter)
        self.__addButton = QPushButton("Add")
        # self.__addButton.setFocusPolicy( Qt.NoFocus )
        self.__addButton.setEnabled(False)
        self.__addButton.clicked.connect(self.__onAddExceptionFilter)

        expandingSpacer2 = QWidget()
        expandingSpacer2.setSizePolicy(QSizePolicy.Expanding,
                                       QSizePolicy.Expanding)

        self.__removeButton = QAction(PixmapCache().getIcon('delitem.png'),
                                      "Remove selected exception type", self)
        self.__removeButton.triggered.connect(self.__onRemoveFromIgnore)
        self.__removeButton.setEnabled(False)

        fixedSpacer1 = QWidget()
        fixedSpacer1.setFixedWidth(5)

        self.__removeAllButton = QAction(
            PixmapCache().getIcon('ignexcptdelall.png'),
            "Remove all the exception types", self)
        self.__removeAllButton.triggered.connect(self.__onRemoveAllFromIgnore)
        self.__removeAllButton.setEnabled(False)

        self.toolbar = QToolBar()
        self.toolbar.setOrientation(Qt.Horizontal)
        self.toolbar.setMovable(False)
        self.toolbar.setAllowedAreas(Qt.TopToolBarArea)
        self.toolbar.setIconSize(QSize(16, 16))
        self.toolbar.setFixedHeight(28)
        self.toolbar.setContentsMargins(0, 0, 0, 0)
        self.toolbar.addWidget(expandingSpacer2)
        self.toolbar.addAction(self.__removeButton)
        self.toolbar.addWidget(fixedSpacer1)
        self.toolbar.addAction(self.__removeAllButton)

        addLayout = QHBoxLayout()
        addLayout.setContentsMargins(1, 1, 1, 1)
        addLayout.setSpacing(1)
        addLayout.addWidget(self.__excTypeEdit)
        addLayout.addWidget(self.__addButton)

        verticalLayout.addWidget(self.headerFrame)
        verticalLayout.addWidget(self.toolbar)
        verticalLayout.addWidget(self.exceptionsList)
        verticalLayout.addLayout(addLayout)
        return

    def clear(self):
        " Clears the content "
        self.exceptionsList.clear()
        self.__excTypeEdit.clear()
        self.__addButton.setEnabled(False)
        self.__ignored = []
        self.__currentItem = None
        self.__updateTitle()
        return

    def __onShowHide(self, startup=False):
        " Triggered when show/hide button is clicked "
        if startup or self.exceptionsList.isVisible():
            self.exceptionsList.setVisible(False)
            self.__excTypeEdit.setVisible(False)
            self.__addButton.setVisible(False)
            self.__removeButton.setVisible(False)
            self.__removeAllButton.setVisible(False)
            self.__showHideButton.setIcon(PixmapCache().getIcon('more.png'))
            self.__showHideButton.setToolTip("Show ignored exceptions list")

            self.__minH = self.minimumHeight()
            self.__maxH = self.maximumHeight()

            self.setMinimumHeight(self.headerFrame.height())
            self.setMaximumHeight(self.headerFrame.height())

            Settings().showIgnoredExcViewer = False
        else:
            self.exceptionsList.setVisible(True)
            self.__excTypeEdit.setVisible(True)
            self.__addButton.setVisible(True)
            self.__removeButton.setVisible(True)
            self.__removeAllButton.setVisible(True)
            self.__showHideButton.setIcon(PixmapCache().getIcon('less.png'))
            self.__showHideButton.setToolTip("Hide ignored exceptions list")

            self.setMinimumHeight(self.__minH)
            self.setMaximumHeight(self.__maxH)

            Settings().showIgnoredExcViewer = True
        return

    def __onSelectionChanged(self):
        " Triggered when the current item is changed "
        selected = list(self.exceptionsList.selectedItems())
        if selected:
            self.__currentItem = selected[0]
            self.__removeButton.setEnabled(True)
        else:
            self.__currentItem = None
            self.__removeButton.setEnabled(False)
        return

    def __showContextMenu(self, coord):
        " Shows the frames list context menu "
        contextItem = self.exceptionsList.itemAt(coord)
        if contextItem is not None:
            self.__currentItem = contextItem
            self.__excptMenu.popup(QCursor.pos())
        return

    def __updateTitle(self):
        " Updates the section title "
        count = self.exceptionsList.topLevelItemCount()
        if count == 0:
            self.__excptLabel.setText("Ignored exception types")
        else:
            self.__excptLabel.setText("Ignored exception types (total: " +
                                      str(count) + ")")
        self.__removeAllButton.setEnabled(count != 0)
        return

    def __onProjectChanged(self, what):
        " Triggered when a project is changed "
        if what != CodimensionProject.CompleteProject:
            return

        self.clear()
        project = GlobalData().project
        if project.isLoaded():
            self.__ignored = list(project.ignoredExcpt)
        else:
            self.__ignored = list(Settings().ignoredExceptions)

        for exceptionType in self.__ignored:
            item = QTreeWidgetItem(self.exceptionsList)
            item.setText(0, exceptionType)
        self.__updateTitle()
        return

    def __onNewFilterChanged(self, text):
        " Triggered when the text is changed "
        text = str(text).strip()
        if text == "":
            self.__addButton.setEnabled(False)
            return
        if " " in text:
            self.__addButton.setEnabled(False)
            return

        if text in self.__ignored:
            self.__addButton.setEnabled(False)
            return

        self.__addButton.setEnabled(True)
        return

    def __onAddExceptionFilter(self):
        " Adds an item into the ignored exceptions list "
        text = self.__excTypeEdit.text().strip()
        self.addExceptionFilter(text)

    def addExceptionFilter(self, excType):
        " Adds a new item into the ignored exceptions list "
        if excType == "":
            return
        if " " in excType:
            return
        if excType in self.__ignored:
            return

        item = QTreeWidgetItem(self.exceptionsList)
        item.setText(0, excType)

        project = GlobalData().project
        if project.isLoaded():
            project.addExceptionFilter(excType)
        else:
            Settings().addExceptionFilter(excType)
        self.__ignored.append(excType)
        self.__updateTitle()
        return

    def __onRemoveFromIgnore(self):
        " Removes an item from the ignored exception types list "
        if self.__currentItem is None:
            return

        text = self.__currentItem.text(0)

        # Find the item index and remove it
        index = 0
        while True:
            if self.exceptionsList.topLevelItem(index).text(0) == text:
                self.exceptionsList.takeTopLevelItem(index)
                break
            index += 1

        project = GlobalData().project
        if project.isLoaded():
            project.deleteExceptionFilter(text)
        else:
            Settings().deleteExceptionFilter(text)
        self.__ignored.remove(text)
        self.__updateTitle()
        return

    def __onRemoveAllFromIgnore(self):
        " Triggered when all the ignored exceptions should be deleted "
        self.clear()

        project = GlobalData().project
        if project.isLoaded():
            project.setExceptionFilters([])
        else:
            Settings().setExceptionFilters([])
        return

    def isIgnored(self, exceptionType):
        " Returns True if this exception type should be ignored "
        return exceptionType in self.__ignored
예제 #12
0
class SettingsManager(QDialog):
    def __init__(self, num, n, parent=None):
        super(SettingsManager, self).__init__(parent)

        #main
        self.par = n
        title = Settingz().positions(num)
        self.titleID = title['id']
        self.titleIDx = str(title['id']) + 'x'
        self.titlePage = title['page']
        self.titleName = title['name']
        self.titleSub = title['subID']
        self.titleIcon = title['icon']
        self.pagetitle = self.titlePage
        self.sessionMain = 0
        #stylesheet
        stylesheet = Valid().background() + Valid().font()
        treeStyleSheet = Valid().treez()

        self.groupBox1 = QGroupBox(self.titleName)
        self.groupBox2 = QGroupBox('Add')

        #items
        self.tree = QTreeWidget()
        self.tree.setHeaderLabel("Choose " + self.titleName)
        self.tree.headerItem().setText(0, 'Name')
        self.tree.headerItem().setText(1, 'Abbrv.')
        self.tree.setStyleSheet(treeStyleSheet)
        self.makeTree()
        self.tree.setMinimumHeight(250)
        self.tree.clicked.connect(lambda: self.getSelection())
        self.tree.itemClicked.connect(lambda state: self.getChecked(state))
        #buttons
        #add
        nImg = Buttons().addButton()
        self.pb = QPushButton()
        self.pb.setFlat(True)
        self.pb.setIcon(QIcon(nImg))
        self.pb.setMaximumHeight(30)
        self.pb.setMaximumWidth(30)

        nImg1 = Buttons().closeButton()
        self.pb1 = QPushButton()
        self.pb1.setFlat(True)
        self.pb1.setIcon(QIcon(nImg1))
        self.pb1.setMaximumHeight(30)
        self.pb1.setMaximumWidth(30)

        nImg2 = Buttons().editButton()
        self.pb2 = QPushButton()
        self.pb2.setFlat(True)
        self.pb2.setIcon(QIcon(nImg2))
        self.pb2.setMaximumHeight(30)
        self.pb2.setMaximumWidth(30)

        nImg3 = Buttons().deleteButton()
        self.pb3 = QPushButton()
        self.pb3.setFlat(True)
        self.pb3.setIcon(QIcon(nImg3))
        self.pb3.setMaximumHeight(30)
        self.pb3.setMaximumWidth(30)

        nImg4 = Buttons().saveButton()
        self.pb4 = QPushButton()
        self.pb4.setFlat(True)
        self.pb4.setIcon(QIcon(nImg4))
        self.pb4.setMaximumHeight(30)
        self.pb4.setMaximumWidth(30)

        nImg5 = Buttons().resetButton()
        self.pb5 = QPushButton()
        self.pb5.setFlat(True)
        self.pb5.setIcon(QIcon(nImg5))
        self.pb5.setMaximumHeight(30)
        self.pb5.setMaximumWidth(30)

        nImg6 = Buttons().closeButton()
        self.pb6 = QPushButton()
        self.pb6.setFlat(True)
        self.pb6.setIcon(QIcon(nImg6))
        self.pb6.setMaximumHeight(30)
        self.pb6.setMaximumWidth(30)

        nImg7 = Buttons().addButton()
        self.pb7 = QPushButton()
        self.pb7.setFlat(True)
        self.pb7.setIcon(QIcon(nImg7))
        self.pb7.setMaximumHeight(30)
        self.pb7.setMaximumWidth(30)

        hbo = QHBoxLayout()
        hbo.addStretch()
        hbo.addWidget(self.pb1)
        hbo.addWidget(self.pb3)
        hbo.addWidget(self.pb2)
        hbo.addWidget(self.pb7)

        vbo = QVBoxLayout()
        vbo.addWidget(self.tree)
        vbo.addLayout(hbo)

        self.l1 = QLabel("Name")
        self.le1 = QLineEdit()
        self.le1.setObjectName("name")
        vals1 = Valid().fullText()
        self.le1.setValidator(vals1)
        self.le1.setPlaceholderText("Lowercase max 25 letters")

        self.l2 = QLabel("Abbrv")
        self.le2 = QLineEdit()
        self.le2.setObjectName("abbrv")
        vals2 = Valid().limitText()
        self.le2.setValidator(vals2)
        self.le2.setPlaceholderText("Lowercase max 5 letters")

        FormLayout = QFormLayout()
        FormLayout.addRow(self.l1, self.le1)
        FormLayout.addRow(self.l2, self.le2)

        Hlayout1 = QHBoxLayout()
        Hlayout1.addStretch()
        Hlayout1.addWidget(self.pb6)
        Hlayout1.addWidget(self.pb5)
        Hlayout1.addWidget(self.pb4)
        Hlayout1.addWidget(self.pb)

        Vlayout1 = QVBoxLayout()
        Vlayout1.addLayout(FormLayout)
        Vlayout1.addLayout(Hlayout1)

        self.groupBox1.setLayout(vbo)
        self.groupBox2.setLayout(Vlayout1)
        self.groupBox2.hide()

        self.connect(self.pb, SIGNAL("clicked()"),
                     lambda: self.button_add())  #add
        self.connect(self.pb1, SIGNAL("clicked()"),
                     lambda: self.button_close())  #close
        self.connect(self.pb2, SIGNAL("clicked()"),
                     lambda: self.button_edit())  #edit
        self.connect(self.pb3, SIGNAL("clicked()"),
                     lambda: self.button_delete())  #delete
        self.connect(self.pb4, SIGNAL("clicked()"),
                     lambda: self.button_save())  #save
        self.connect(self.pb5, SIGNAL("clicked()"),
                     lambda: self.button_reset())  #reset

        self.pb4.hide()
        self.pb7.hide()

        grid = QGridLayout()
        grid.addWidget(self.groupBox1, 0, 0)
        grid.addWidget(self.groupBox2, 1, 0)

        self.setLayout(grid)
        self.setStyleSheet(stylesheet)
        self.setWindowIcon(QIcon(self.titleIcon))
        self.setWindowTitle(self.pagetitle)

    def makeTree(self):
        self.tree.clear()
        arr = Valid().pullData('datas', '', {'pubID': self.titleID})
        self.hold_data = {}
        self.hold_mdata = {}
        self.hold_data_add = {}
        self.hold_data_add_item = {}

        if self.titleSub and self.titleSub > 0:
            if arr and len(arr) > 0:
                for val in arr:
                    ch = Valid().pullData('datas', '', {'subID': val['id']})
                    child = QTreeWidgetItem(self.tree)
                    child.setFlags(child.flags() | Qt.ItemIsUserCheckable)
                    child.setText(0, str(val['name']).upper())
                    child.setText(1, str(val['abbrv']).upper())
                    self.hold_data[val['id']] = child
                    self.hold_mdata[val['id']] = child
                    if (val['active'] == 0):
                        child.setCheckState(0, Qt.Checked)
                    else:
                        child.setCheckState(0, Qt.Unchecked)

                    for va in ch:
                        child1 = QTreeWidgetItem(child)
                        child1.setFlags(child1.flags()
                                        | Qt.ItemIsUserCheckable)
                        child1.setText(0, str(va['name']).upper())
                        child1.setText(1, str(va['abbrv']).upper())
                        self.hold_data[va['id']] = child1
                        if (va['active'] == 0):
                            child1.setCheckState(0, Qt.Checked)
                        else:
                            child1.setCheckState(0, Qt.Unchecked)

                    child1 = QTreeWidgetItem(child)
                    child1.setFlags(child1.flags() | Qt.ItemIsUserCheckable)
                    child1.setText(0, 'Add New Item')
                    self.hold_data_add_item[val['id']] = child1
        else:
            if arr and len(arr) > 0:
                for val in arr:
                    child = QTreeWidgetItem(self.tree)
                    child.setFlags(child.flags() | Qt.ItemIsUserCheckable)
                    child.setText(0, str(val['name']).upper())
                    child.setText(1, str(val['abbrv']).upper())
                    self.hold_data[val['id']] = child
                    if (val['active'] == 0):
                        child.setCheckState(0, Qt.Checked)
                    else:
                        child.setCheckState(0, Qt.Unchecked)

        child = QTreeWidgetItem(self.tree)
        child.setFlags(child.flags() | Qt.ItemIsUserCheckable)
        child.setText(0, 'Add New')
        self.hold_data_add['addnew'] = child

    def getChecked(self, a):
        g = Db()
        for i in self.hold_data:
            if self.hold_data[i].checkState(0) == Qt.Checked:
                g.update('datas', {'active': 0}, {'id': i})
            else:
                g.update('datas', {'active': 1}, {'id': i})

        if self.titleID == 1:
            #if class was changed only reload class menu on main window
            self.par.menuStudent()
            self.par.dropdownStudent()

    def getSelected(self):
        r = None
        k = None
        for i in self.hold_data:
            if self.hold_data[i].isSelected():
                r = i
        for j in self.hold_mdata:
            if self.hold_mdata[j].isSelected():
                k = j

        if r and r > 0:
            if r == k:
                self.sessionMain = r
            else:
                self.sessionMain = 0
            self.groupBox2.show()
            return r
        else:
            self.groupBox2.hide()

    def getSelection(self):

        self.le1.clear()
        self.le2.clear()

        if self.hold_data_add['addnew'].isSelected():
            self.sessionMain = 0
            self.groupBox2.setTitle('Add New')
            self.groupBox2.show()
        else:
            r = None
            for i in self.hold_data_add_item:
                if self.hold_data_add_item[i].isSelected():
                    r = i
            if r:
                self.sessionMain = r
                g = Db()
                v = g.selectn('datas', '', 1, {'id': r})
                vname = str(v['name']).upper()
                self.groupBox2.setTitle('ADD ' + str(vname) + ' ITEM')
                self.groupBox2.show()
            else:
                self.groupBox2.setTitle('Add')
                self.groupBox2.hide()

    def setActive(self):
        g = Db()
        for i in self.hold_data:
            if self.hold_data[i].checkState(0) == Qt.Checked:
                g.update('datas', {'active': 0}, {'id': i})
            else:
                g.update('datas', {'active': 1}, {'id': i})

    def button_add(self):
        s1 = self.le1.text()
        s2 = self.le2.text()
        g = Db()
        try:
            if (len(s1) > 0) and (len(s2) > 0):
                if self.sessionMain == 0:
                    y = {
                        'name': s1.lower(),
                        'abbrv': s2.lower(),
                        'pubID': self.titleID,
                        'active': 0
                    }
                else:
                    y = {
                        'name': s1.lower(),
                        'abbrv': s2.lower(),
                        'subID': self.sessionMain,
                        'pubID': self.titleIDx,
                        'active': 0
                    }
                g.insert('datas', y)

                self.makeTree()
                self.button_reset()
                if self.titleID == 1:
                    #if class was changed only relod class menu on main window
                    self.par.menuStudent()
                    self.par.dropdownStudent()
            else:
                pass
        except:
            pass

    def button_save(self):
        row = self.editrow

        s1 = self.le1.text()
        s2 = self.le2.text()
        g = Db()
        try:
            if (len(s1) > 0) and (len(s2) > 0) and row and row > 0:
                y = {'name': s1.lower(), 'abbrv': s2.lower(), 'active': 0}
                z = {'id': row}
                g.update('datas', y, z)
                self.makeTree()
                self.button_reset()
                if self.titleID == 1:
                    #if class was changed only relod class menu on main window
                    self.par.menuStudent()
                    self.par.dropdownStudent()
            else:
                pass
        except:
            pass

    def button_delete(self):
        row = self.getSelected()
        g = Db()
        try:
            if row and row > 0:
                y = {'abbrv': '', 'active': 2}
                z = {'id': row}
                g.update('datas', y, z)
                self.makeTree()
            else:
                pass
        except:
            pass

    def button_reset(self):
        self.le1.clear()
        self.le2.clear()
        self.groupBox2.setTitle('Add')
        self.groupBox2.hide()
        self.pb.show()
        self.pb4.hide()
        self.sessionMain = 0

    def button_edit(self):
        row = self.getSelected()
        self.sessionMain = 0
        if row:
            self.groupBox2.setTitle('Edit')
            self.editrow = row
            g = Db()
            data = g.selectn('datas', '', 1, {'id': row})
            if self.titleID == data['pubID']:
                self.sessionMain = 1
            else:
                self.sessionMain = 0

            try:
                self.le1.setText(data['name'])
            except:
                self.le1.setText('')
            try:
                self.le2.setText(data['abbrv'])
            except:
                self.le2.setText('')
            self.pb.hide()
            self.pb4.show()

    def button_close(self):
        self.close()
예제 #13
0
class SpreadSheet(QMainWindow):

   dateFormats = ["dd/M/yyyy", "yyyy/M/dd", "dd.MM.yyyy"]

   currentDateFormat = dateFormats[0]

   def __init__(self, rows, cols, parent = None):
      super(SpreadSheet, self).__init__(parent)

      self.toolBar = QToolBar()
      self.addToolBar(self.toolBar)
      self.formulaInput = QLineEdit()
      self.cellLabel = QLabel(self.toolBar)
      self.cellLabel.setMinimumSize(80, 0)
      self.toolBar.addWidget(self.cellLabel)
      self.toolBar.addWidget(self.formulaInput)
      self.table = QTableWidget(rows, cols, self)
      for c in range(cols):
         character = chr(ord('A') + c)
         self.table.setHorizontalHeaderItem(c, QTableWidgetItem(character))

      self.table.setItemPrototype(self.table.item(rows - 1, cols - 1))
      self.table.setItemDelegate(SpreadSheetDelegate(self))
      self.createActions()
      self.updateColor(0)
      self.setupMenuBar()
      self.setupContents()
      self.setupContextMenu()
      self.setCentralWidget(self.table)
      self.statusBar()
      self.table.currentItemChanged.connect(self.updateStatus)
      self.table.currentItemChanged.connect(self.updateColor)
      self.table.currentItemChanged.connect(self.updateLineEdit)
      self.table.itemChanged.connect(self.updateStatus)
      self.formulaInput.returnPressed.connect(self.returnPressed)
      self.table.itemChanged.connect(self.updateLineEdit)
      self.setWindowTitle("Spreadsheet")

   def createActions(self):
      self.cell_sumAction = QAction("Sum", self)
      self.cell_sumAction.triggered.connect(self.actionSum)

      self.cell_addAction = QAction("&Add", self)
      self.cell_addAction.setShortcut(Qt.CTRL | Qt.Key_Plus)
      self.cell_addAction.triggered.connect(self.actionAdd)

      self.cell_subAction = QAction("&Subtract", self)
      self.cell_subAction.setShortcut(Qt.CTRL | Qt.Key_Minus)
      self.cell_subAction.triggered.connect(self.actionSubtract)

      self.cell_mulAction = QAction("&Multiply", self)
      self.cell_mulAction.setShortcut(Qt.CTRL | Qt.Key_multiply)
      self.cell_mulAction.triggered.connect(self.actionMultiply)

      self.cell_divAction = QAction("&Divide", self)
      self.cell_divAction.setShortcut(Qt.CTRL | Qt.Key_division)
      self.cell_divAction.triggered.connect(self.actionDivide)

      self.fontAction = QAction("Font...", self)
      self.fontAction.setShortcut(Qt.CTRL | Qt.Key_F)
      self.fontAction.triggered.connect(self.selectFont)

      self.colorAction = QAction(QIcon(QPixmap(16, 16)), "Background &Color...", self)
      self.colorAction.triggered.connect(self.selectColor)

      self.clearAction = QAction("Clear", self)
      self.clearAction.setShortcut(Qt.Key_Delete)
      self.clearAction.triggered.connect(self.clear)

      self.aboutSpreadSheet = QAction("About Spreadsheet", self)
      self.aboutSpreadSheet.triggered.connect(self.showAbout)

      self.exitAction = QAction("E&xit", self)
      self.exitAction.setShortcut(QKeySequence.Quit)
      self.exitAction.triggered.connect(QApplication.instance().quit)

      self.printAction = QAction("&Print", self)
      self.printAction.setShortcut(QKeySequence.Print)
      self.printAction.triggered.connect(self.print_)

      self.firstSeparator = QAction(self)
      self.firstSeparator.setSeparator(True)

      self.secondSeparator = QAction(self)
      self.secondSeparator.setSeparator(True)

   def setupMenuBar(self):
      self.fileMenu = self.menuBar().addMenu("&File")
      self.dateFormatMenu = self.fileMenu.addMenu("&Date format")
      self.dateFormatGroup = QActionGroup(self)
      for f in self.dateFormats:
         action = QAction(f, self, checkable=True,
                 triggered=self.changeDateFormat)
         self.dateFormatGroup.addAction(action)
         self.dateFormatMenu.addAction(action)
         if f == self.currentDateFormat:
            action.setChecked(True)
              
      self.fileMenu.addAction(self.printAction)
      self.fileMenu.addAction(self.exitAction)
      self.cellMenu = self.menuBar().addMenu("&Cell")
      self.cellMenu.addAction(self.cell_addAction)
      self.cellMenu.addAction(self.cell_subAction)
      self.cellMenu.addAction(self.cell_mulAction)
      self.cellMenu.addAction(self.cell_divAction)
      self.cellMenu.addAction(self.cell_sumAction)
      self.cellMenu.addSeparator()
      self.cellMenu.addAction(self.colorAction)
      self.cellMenu.addAction(self.fontAction)
      self.menuBar().addSeparator()
      self.aboutMenu = self.menuBar().addMenu("&Help")
      self.aboutMenu.addAction(self.aboutSpreadSheet)

   def changeDateFormat(self):
      action = self.sender()
      oldFormat = self.currentDateFormat
      newFormat = self.currentDateFormat = action.text()
      for row in range(self.table.rowCount()):
         item = self.table.item(row, 1)
         date = QDate.fromString(item.text(), oldFormat)
         item.setText(date.toString(newFormat))

   def updateStatus(self, item):
      if item and item == self.table.currentItem():
         self.statusBar().showMessage(item.data(Qt.StatusTipRole).toString(), 1000)
         self.cellLabel.setText("Cell: (%s)" % encode_pos(self.table.row(item),
                                                                    self.table.column(item)))

   def updateColor(self, item):
      pixmap = QPixmap(16, 16)
      color = QColor()
      if item:
         color = item.backgroundColor()
      if not color.isValid():
         color = self.palette().base().color()
      painter = QPainter(pixmap)
      painter.fillRect(0, 0, 16, 16, color)
      lighter = color.lighter()
      painter.setPen(lighter)
      # light frame
      painter.drawPolyline(QPoint(0, 15), QPoint(0, 0), QPoint(15, 0))
      painter.setPen(color.darker())
      # dark frame
      painter.drawPolyline(QPoint(1, 15), QPoint(15, 15), QPoint(15, 1))
      painter.end()
      self.colorAction.setIcon(QIcon(pixmap))

   def updateLineEdit(self, item):
      if item != self.table.currentItem():
         return
      if item:
         self.formulaInput.setText(item.data(Qt.EditRole).toString())
      else:
         self.formulaInput.clear()

   def returnPressed(self):
      text = self.formulaInput.text()
      row = self.table.currentRow()
      col = self.table.currentColumn()
      item = self.table.item(row, col)
      if not item:
         self.table.setItem(row, col, SpreadSheetItem(text))
      else:
         item.setData(Qt.EditRole, text)
      self.table.viewport().update()

   def selectColor(self):
      item = self.table.currentItem()
      color = item and QColor(item.background()) or self.table.palette().base().color()
      color = QColorDialog.getColor(color, self)
      if not color.isValid():
         return
      selected = self.table.selectedItems()
      if not selected:
         return
      for i in selected:
         i and i.setBackground(color)
      self.updateColor(self.table.currentItem())

   def selectFont(self):
      selected = self.table.selectedItems()
      if not selected:
         return
      font, ok = QFontDialog.getFont(self.font(), self)
      if not ok:
         return
      for i in selected:
         i and i.setFont(font)

   def runInputDialog(self, title, c1Text, c2Text, opText,
                      outText, cell1, cell2, outCell):
      rows = []
      cols = []
      for r in range(self.table.rowCount()):
         rows.append(str(r + 1))
      for c in range(self.table.columnCount()):
         cols.append(chr(ord('A') + c))
      addDialog = QDialog(self)
      addDialog.setWindowTitle(title)
      group = QGroupBox(title, addDialog)
      group.setMinimumSize(250, 100)
      cell1Label = QLabel(c1Text, group)
      cell1RowInput = QComboBox(group)
      c1Row, c1Col = decode_pos(cell1)
      cell1RowInput.addItems(rows)
      cell1RowInput.setCurrentIndex(c1Row)
      cell1ColInput = QComboBox(group)
      cell1ColInput.addItems(cols)
      cell1ColInput.setCurrentIndex(c1Col)
      operatorLabel = QLabel(opText, group)
      operatorLabel.setAlignment(Qt.AlignHCenter)
      cell2Label = QLabel(c2Text, group)
      cell2RowInput = QComboBox(group)
      c2Row, c2Col = decode_pos(cell2)
      cell2RowInput.addItems(rows)
      cell2RowInput.setCurrentIndex(c2Row)
      cell2ColInput = QComboBox(group)
      cell2ColInput.addItems(cols)
      cell2ColInput.setCurrentIndex(c2Col)
      equalsLabel = QLabel("=", group)
      equalsLabel.setAlignment(Qt.AlignHCenter)
      outLabel = QLabel(outText, group)
      outRowInput = QComboBox(group)
      outRow, outCol = decode_pos(outCell)
      outRowInput.addItems(rows)
      outRowInput.setCurrentIndex(outRow)
      outColInput = QComboBox(group)
      outColInput.addItems(cols)
      outColInput.setCurrentIndex(outCol)

      cancelButton = QPushButton("Cancel", addDialog)
      cancelButton.clicked.connect(addDialog.reject)
      okButton = QPushButton("OK", addDialog)
      okButton.setDefault(True)
      okButton.clicked.connect(addDialog.accept)
      buttonsLayout = QHBoxLayout()
      buttonsLayout.addStretch(1)
      buttonsLayout.addWidget(okButton)
      buttonsLayout.addSpacing(10)
      buttonsLayout.addWidget(cancelButton)

      dialogLayout = QVBoxLayout(addDialog)
      dialogLayout.addWidget(group)
      dialogLayout.addStretch(1)
      dialogLayout.addItem(buttonsLayout)

      cell1Layout = QHBoxLayout()
      cell1Layout.addWidget(cell1Label)
      cell1Layout.addSpacing(10)
      cell1Layout.addWidget(cell1ColInput)
      cell1Layout.addSpacing(10)
      cell1Layout.addWidget(cell1RowInput)

      cell2Layout = QHBoxLayout()
      cell2Layout.addWidget(cell2Label)
      cell2Layout.addSpacing(10)
      cell2Layout.addWidget(cell2ColInput)
      cell2Layout.addSpacing(10)
      cell2Layout.addWidget(cell2RowInput)
      outLayout = QHBoxLayout()
      outLayout.addWidget(outLabel)
      outLayout.addSpacing(10)
      outLayout.addWidget(outColInput)
      outLayout.addSpacing(10)
      outLayout.addWidget(outRowInput)
      vLayout = QVBoxLayout(group)
      vLayout.addItem(cell1Layout)
      vLayout.addWidget(operatorLabel)
      vLayout.addItem(cell2Layout)
      vLayout.addWidget(equalsLabel)
      vLayout.addStretch(1)
      vLayout.addItem(outLayout)
      if addDialog.exec_():
         cell1 = cell1ColInput.currentText() + cell1RowInput.currentText()
         cell2 = cell2ColInput.currentText() + cell2RowInput.currentText()
         outCell = outColInput.currentText() + outRowInput.currentText()
         return True, cell1, cell2, outCell

      return False, None, None, None

   def actionSum(self):
      row_first = 0
      row_last = 0
      row_cur = 0
      col_first = 0
      col_last = 0
      col_cur = 0
      selected = self.table.selectedItems()
      if selected:
         first = selected[0]
         last = selected[-1]
         row_first = self.table.row(first)
         row_last = self.table.row(last)
         col_first = self.table.column(first)
         col_last = self.table.column(last)

      current = self.table.currentItem()
      if current:
         row_cur = self.table.row(current)
         col_cur = self.table.column(current)

      cell1 = encode_pos(row_first, col_first)
      cell2 = encode_pos(row_last, col_last)
      out = encode_pos(row_cur, col_cur)
      ok, cell1, cell2, out = self.runInputDialog("Sum cells", "First cell:",
              "Last cell:", u"\N{GREEK CAPITAL LETTER SIGMA}", "Output to:",
              cell1, cell2, out)
      if ok:
         row, col = decode_pos(out)
         self.table.item(row, col).setText("sum %s %s" % (cell1, cell2))

   def actionMath_helper(self, title, op):
      cell1 = "C1"
      cell2 = "C2"
      out = "C3"
      current = self.table.currentItem()
      if current:
         out = encode_pos(self.table.currentRow(), self.table.currentColumn())
      ok, cell1, cell2, out = self.runInputDialog(title, "Cell 1", "Cell 2",
              op, "Output to:", cell1, cell2, out)
      if ok:
         row, col = decode_pos(out)
         self.table.item(row, col).setText("%s %s %s" % (op, cell1, cell2))

   def actionAdd(self):
      self.actionMath_helper("Addition", "+")

   def actionSubtract(self):
      self.actionMath_helper("Subtraction", "-")

   def actionMultiply(self):
      self.actionMath_helper("Multiplication", "*")

   def actionDivide(self):
      self.actionMath_helper("Division", "/")

   def clear(self):
      for i in self.table.selectedItems():
         i.setText("")

   def setupContextMenu(self):
      self.addAction(self.cell_addAction)
      self.addAction(self.cell_subAction)
      self.addAction(self.cell_mulAction)
      self.addAction(self.cell_divAction)
      self.addAction(self.cell_sumAction)
      self.addAction(self.firstSeparator)
      self.addAction(self.colorAction)
      self.addAction(self.fontAction)
      self.addAction(self.secondSeparator)
      self.addAction(self.clearAction)
      self.setContextMenuPolicy(Qt.ActionsContextMenu)

   def setupContents(self):
      titleBackground = QColor(Qt.lightGray)
      titleFont = self.table.font()
      titleFont.setBold(True)
      # column 0
      self.table.setItem(0, 0, SpreadSheetItem("Item"))
      self.table.item(0, 0).setBackground(titleBackground)
      self.table.item(0, 0).setToolTip("This column shows the purchased item/service")
      self.table.item(0, 0).setFont(titleFont)
      self.table.setItem(1, 0, SpreadSheetItem("AirportBus"))
      self.table.setItem(2, 0, SpreadSheetItem("Flight (Munich)"))
      self.table.setItem(3, 0, SpreadSheetItem("Lunch"))
      self.table.setItem(4, 0, SpreadSheetItem("Flight (LA)"))
      self.table.setItem(5, 0, SpreadSheetItem("Taxi"))
      self.table.setItem(6, 0, SpreadSheetItem("Dinner"))
      self.table.setItem(7, 0, SpreadSheetItem("Hotel"))
      self.table.setItem(8, 0, SpreadSheetItem("Flight (Oslo)"))
      self.table.setItem(9, 0, SpreadSheetItem("Total:"))
      self.table.item(9, 0).setFont(titleFont)
      self.table.item(9, 0).setBackground(Qt.lightGray)
      # column 1
      self.table.setItem(0, 1, SpreadSheetItem("Date"))
      self.table.item(0, 1).setBackground(titleBackground)
      self.table.item(0, 1).setToolTip("This column shows the purchase date, double click to change")
      self.table.item(0, 1).setFont(titleFont)
      self.table.setItem(1, 1, SpreadSheetItem("15/6/2006"))
      self.table.setItem(2, 1, SpreadSheetItem("15/6/2006"))
      self.table.setItem(3, 1, SpreadSheetItem("15/6/2006"))
      self.table.setItem(4, 1, SpreadSheetItem("21/5/2006"))
      self.table.setItem(5, 1, SpreadSheetItem("16/6/2006"))
      self.table.setItem(6, 1, SpreadSheetItem("16/6/2006"))
      self.table.setItem(7, 1, SpreadSheetItem("16/6/2006"))
      self.table.setItem(8, 1, SpreadSheetItem("18/6/2006"))
      self.table.setItem(9, 1, SpreadSheetItem())
      self.table.item(9, 1).setBackground(Qt.lightGray)
      # column 2
      self.table.setItem(0, 2, SpreadSheetItem("Price"))
      self.table.item(0, 2).setBackground(titleBackground)
      self.table.item(0, 2).setToolTip("This column shows the price of the purchase")
      self.table.item(0, 2).setFont(titleFont)
      self.table.setItem(1, 2, SpreadSheetItem("150"))
      self.table.setItem(2, 2, SpreadSheetItem("2350"))
      self.table.setItem(3, 2, SpreadSheetItem("-14"))
      self.table.setItem(4, 2, SpreadSheetItem("980"))
      self.table.setItem(5, 2, SpreadSheetItem("5"))
      self.table.setItem(6, 2, SpreadSheetItem("120"))
      self.table.setItem(7, 2, SpreadSheetItem("300"))
      self.table.setItem(8, 2, SpreadSheetItem("1240"))
      self.table.setItem(9, 2, SpreadSheetItem())
      self.table.item(9, 2).setBackground(Qt.lightGray)
      # column 3
      self.table.setItem(0, 3, SpreadSheetItem("Currency"))
      self.table.item(0, 3).setBackgroundColor(titleBackground)
      self.table.item(0, 3).setToolTip("This column shows the currency")
      self.table.item(0, 3).setFont(titleFont)
      self.table.setItem(1, 3, SpreadSheetItem("NOK"))
      self.table.setItem(2, 3, SpreadSheetItem("NOK"))
      self.table.setItem(3, 3, SpreadSheetItem("EUR"))
      self.table.setItem(4, 3, SpreadSheetItem("EUR"))
      self.table.setItem(5, 3, SpreadSheetItem("USD"))
      self.table.setItem(6, 3, SpreadSheetItem("USD"))
      self.table.setItem(7, 3, SpreadSheetItem("USD"))
      self.table.setItem(8, 3, SpreadSheetItem("USD"))
      self.table.setItem(9, 3, SpreadSheetItem())
      self.table.item(9,3).setBackground(Qt.lightGray)
      # column 4
      self.table.setItem(0, 4, SpreadSheetItem("Ex. Rate"))
      self.table.item(0, 4).setBackground(titleBackground)
      self.table.item(0, 4).setToolTip("This column shows the exchange rate to NOK")
      self.table.item(0, 4).setFont(titleFont)
      self.table.setItem(1, 4, SpreadSheetItem("1"))
      self.table.setItem(2, 4, SpreadSheetItem("1"))
      self.table.setItem(3, 4, SpreadSheetItem("8"))
      self.table.setItem(4, 4, SpreadSheetItem("8"))
      self.table.setItem(5, 4, SpreadSheetItem("7"))
      self.table.setItem(6, 4, SpreadSheetItem("7"))
      self.table.setItem(7, 4, SpreadSheetItem("7"))
      self.table.setItem(8, 4, SpreadSheetItem("7"))
      self.table.setItem(9, 4, SpreadSheetItem())
      self.table.item(9,4).setBackground(Qt.lightGray)
      # column 5
      self.table.setItem(0, 5, SpreadSheetItem("NOK"))
      self.table.item(0, 5).setBackground(titleBackground)
      self.table.item(0, 5).setToolTip("This column shows the expenses in NOK")
      self.table.item(0, 5).setFont(titleFont)
      self.table.setItem(1, 5, SpreadSheetItem("* C2 E2"))
      self.table.setItem(2, 5, SpreadSheetItem("* C3 E3"))
      self.table.setItem(3, 5, SpreadSheetItem("* C4 E4"))
      self.table.setItem(4, 5, SpreadSheetItem("* C5 E5"))
      self.table.setItem(5, 5, SpreadSheetItem("* C6 E6"))
      self.table.setItem(6, 5, SpreadSheetItem("* C7 E7"))
      self.table.setItem(7, 5, SpreadSheetItem("* C8 E8"))
      self.table.setItem(8, 5, SpreadSheetItem("* C9 E9"))
      self.table.setItem(9, 5, SpreadSheetItem("sum F2 F9"))
      self.table.item(9,5).setBackground(Qt.lightGray)

   def showAbout(self):
      QMessageBox.about(self, "About Spreadsheet", """
          <HTML>
          <p><b>This demo shows use of <c>QTableWidget</c> with custom handling for
           individual cells.</b></p>
          <p>Using a customized table item we make it possible to have dynamic
           output in different cells. The content that is implemented for this
           particular demo is:
          <ul>
          <li>Adding two cells.</li>
          <li>Subtracting one cell from another.</li>
          <li>Multiplying two cells.</li>
          <li>Dividing one cell with another.</li>
          <li>Summing the contents of an arbitrary number of cells.</li>
          </HTML>
      """)

   def print_(self):
      pass
예제 #14
0
class SVNPluginPropsDialog(QDialog):
    " SVN plugin properties dialog "

    def __init__(self, plugin, client, path, parent=None):
        QDialog.__init__(self, parent)

        self.__plugin = plugin
        self.__client = client
        self.__path = path

        self.__createLayout()
        self.setWindowTitle("SVN Properties of " + path)
        self.__populate()
        self.__propsView.setFocus()
        return

    def __populate(self):
        " Populate the properties list "
        # Get the currently selected name
        selectedName = None
        selected = list(self.__propsView.selectedItems())
        if selected:
            selectedName = str(selected[0].text(0))

        self.__propsView.clear()
        properties = readProperties(self.__client, self.__path)
        if properties:
            for itemPath, itemProps in properties:
                if self.__path == itemPath or \
                   self.__path == itemPath + os.path.sep:
                    for name, value in itemProps.iteritems():
                        name = str(name).strip()
                        value = str(value).strip()
                        newItem = QTreeWidgetItem([name, value])
                        self.__propsView.addTopLevelItem(newItem)

        self.__resizePropsView()
        self.__sortPropsView()

        if selectedName:
            index = 0
            for index in xrange(0, self.__propsView.topLevelItemCount()):
                item = self.__propsView.topLevelItem(index)
                if selectedName == item.text(0):
                    item.setSelected(True)
        return

    def __resizePropsView(self):
        " Resizes the properties table "
        self.__propsView.header().setStretchLastSection(True)
        self.__propsView.header().resizeSections(QHeaderView.ResizeToContents)
        return

    def __sortPropsView(self):
        " Sorts the properties table "
        self.__propsView.sortItems(
            self.__propsView.sortColumn(),
            self.__propsView.header().sortIndicatorOrder())
        return

    def __createLayout(self):
        " Creates the dialog layout "
        self.resize(640, 480)
        self.setSizeGripEnabled(True)

        vboxLayout = QVBoxLayout(self)

        hLayout = QHBoxLayout()
        self.__propsView = QTreeWidget()
        self.__propsView.setAlternatingRowColors(True)
        self.__propsView.setRootIsDecorated(False)
        self.__propsView.setItemsExpandable(False)
        self.__propsView.setSortingEnabled(True)
        self.__propsView.setItemDelegate(NoOutlineHeightDelegate(4))
        self.__propsView.itemSelectionChanged.connect(
            self.__propsSelectionChanged)

        propsViewHeader = QTreeWidgetItem(["Property Name", "Property Value"])
        self.__propsView.setHeaderItem(propsViewHeader)
        self.__propsView.header().setSortIndicator(0, Qt.DescendingOrder)
        hLayout.addWidget(self.__propsView)

        self.__delButton = QToolButton()
        self.__delButton.setText("Delete")
        self.__delButton.setFocusPolicy(Qt.NoFocus)
        self.__delButton.setEnabled(False)
        self.__delButton.clicked.connect(self.__onDel)
        hLayout.addWidget(self.__delButton, 0, Qt.AlignBottom)
        vboxLayout.addLayout(hLayout)

        # Set property part
        setGroupbox = QGroupBox(self)
        setGroupbox.setTitle("Set Property")

        setLayout = QGridLayout(setGroupbox)
        setLayout.addWidget(QLabel("Name"), 0, 0, Qt.AlignTop | Qt.AlignRight)
        setLayout.addWidget(QLabel("Value"), 1, 0, Qt.AlignTop | Qt.AlignRight)

        self.__nameEdit = QLineEdit()
        self.__nameEdit.textChanged.connect(self.__nameChanged)
        setLayout.addWidget(self.__nameEdit, 0, 1)

        self.__valueEdit = QTextEdit()
        self.__valueEdit.setAcceptRichText(False)
        self.__valueEdit.textChanged.connect(self.__valueChanged)
        metrics = QFontMetrics(self.__valueEdit.font())
        rect = metrics.boundingRect("X")
        self.__valueEdit.setFixedHeight(rect.height() * 4 + 5)
        setLayout.addWidget(self.__valueEdit, 1, 1)

        self.__setButton = QToolButton()
        self.__setButton.setText("Set")
        self.__setButton.setFocusPolicy(Qt.NoFocus)
        self.__setButton.setEnabled(False)
        self.__setButton.clicked.connect(self.__onSet)
        setLayout.addWidget(self.__setButton, 1, 2,
                            Qt.AlignBottom | Qt.AlignHCenter)

        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Maximum)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            setGroupbox.sizePolicy().hasHeightForWidth())
        setGroupbox.setSizePolicy(sizePolicy)
        vboxLayout.addWidget(setGroupbox)

        # Buttons at the bottom
        buttonBox = QDialogButtonBox(self)
        buttonBox.setOrientation(Qt.Horizontal)
        buttonBox.setStandardButtons(QDialogButtonBox.Ok)
        buttonBox.button(QDialogButtonBox.Ok).setDefault(True)
        buttonBox.accepted.connect(self.close)
        vboxLayout.addWidget(buttonBox)
        return

    def __onSet(self):
        " Triggered when propery set is clicked "
        name = self.__nameEdit.text().strip()
        value = self.__valueEdit.toPlainText().strip()
        try:
            commitInfo = self.__client.propset(name, value, self.__path)
            if commitInfo:
                logging.info(str(commitInfo))
            self.__populate()
            self.__plugin.notifyPathChanged(self.__path)
            self.__nameEdit.clear()
            self.__valueEdit.clear()
            self.__propsView.setFocus()
        except pysvn.ClientError, exc:
            message = exc.args[0]
            logging.error(message)
            return
        except Exception, exc:
            logging.error(str(exc))
            return
예제 #15
0
class SessionEditor(QDialog):
    def __init__(self, parent=None):
        super(SessionEditor, self).__init__(parent)
        self.setWindowModality(Qt.WindowModal)

        layout = QVBoxLayout()
        self.setLayout(layout)

        grid = QGridLayout()
        layout.addLayout(grid)

        self.name = QLineEdit()
        self.nameLabel = l = QLabel()
        l.setBuddy(self.name)
        grid.addWidget(l, 0, 0)
        grid.addWidget(self.name, 0, 1)

        self.autosave = QCheckBox()
        grid.addWidget(self.autosave, 1, 1)

        self.basedir = widgets.urlrequester.UrlRequester()
        self.basedirLabel = l = QLabel()
        l.setBuddy(self.basedir)
        grid.addWidget(l, 2, 0)
        grid.addWidget(self.basedir, 2, 1)

        self.inclPaths = ip = QGroupBox(self, checkable=True, checked=False)
        ipLayout = QVBoxLayout()
        ip.setLayout(ipLayout)

        self.replPaths = QCheckBox()
        ipLayout.addWidget(self.replPaths)
        self.replPaths.toggled.connect(self.toggleReplace)

        self.include = widgets.listedit.FilePathEdit()
        self.include.listBox.setDragDropMode(QAbstractItemView.InternalMove)
        ipLayout.addWidget(self.include)

        grid.addWidget(ip, 3, 1)

        self.revt = QPushButton(self)
        self.clear = QPushButton(self)
        self.revt.clicked.connect(self.revertPaths)
        self.clear.clicked.connect(self.clearPaths)

        self.include.layout().addWidget(self.revt, 5, 1)
        self.include.layout().addWidget(self.clear, 6, 1)

        layout.addWidget(widgets.Separator())
        self.buttons = b = QDialogButtonBox(self)
        layout.addWidget(b)
        b.setStandardButtons(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        b.accepted.connect(self.accept)
        b.rejected.connect(self.reject)
        userguide.addButton(b, "sessions")
        app.translateUI(self)

    def translateUI(self):
        self.nameLabel.setText(_("Name:"))
        self.autosave.setText(
            _("Always save the list of documents in this session"))
        self.basedirLabel.setText(_("Base directory:"))
        self.inclPaths.setTitle(_("Use session specific include path"))
        self.replPaths.setText(_("Replace global path"))
        self.replPaths.setToolTip(
            _("When checked, paths in LilyPond preferences are not included."))
        self.revt.setText(_("Copy global path"))
        self.revt.setToolTip(
            _("Add and edit the path from LilyPond preferences."))
        self.clear.setText(_("Clear"))
        self.clear.setToolTip(_("Remove all paths."))

    def load(self, name):
        settings = sessions.sessionGroup(name)
        self.autosave.setChecked(settings.value("autosave", True, bool))
        self.basedir.setPath(settings.value("basedir", "", type("")))
        self.include.setValue(
            qsettings.get_string_list(settings, "include-path"))
        self.inclPaths.setChecked(settings.value("set-paths", False, bool))
        self.replPaths.setChecked(settings.value("repl-paths", False, bool))
        if not self.replPaths.isChecked():
            self.addDisabledGenPaths()
            self.revt.setEnabled(False)
        # more settings here

    def fetchGenPaths(self):
        """Fetch paths from general preferences."""
        return qsettings.get_string_list(QSettings(),
                                         "lilypond_settings/include_path")

    def addDisabledGenPaths(self):
        """Add global paths, but set as disabled."""
        genPaths = self.fetchGenPaths()
        for p in genPaths:
            i = QListWidgetItem(p, self.include.listBox)
            i.setFlags(Qt.NoItemFlags)

    def toggleReplace(self):
        """Called when user changes setting for replace of global paths."""
        if self.replPaths.isChecked():
            items = self.include.items()
            for i in items:
                if not (i.flags() & Qt.ItemIsEnabled):  #is not enabled
                    self.include.listBox.takeItem(self.include.listBox.row(i))
            self.revt.setEnabled(True)
        else:
            self.addDisabledGenPaths()
            self.revt.setEnabled(False)

    def revertPaths(self):
        """Add global paths (for edit)."""
        genPaths = self.fetchGenPaths()
        for p in genPaths:
            i = QListWidgetItem(p, self.include.listBox)

    def clearPaths(self):
        """Remove all active paths."""
        items = self.include.items()
        for i in items:
            if i.flags() & Qt.ItemIsEnabled:
                self.include.listBox.takeItem(self.include.listBox.row(i))

    def save(self, name):
        settings = sessions.sessionGroup(name)
        settings.setValue("autosave", self.autosave.isChecked())
        settings.setValue("basedir", self.basedir.path())
        settings.setValue("set-paths", self.inclPaths.isChecked())
        settings.setValue("repl-paths", self.replPaths.isChecked())
        path = [
            i.text() for i in self.include.items()
            if i.flags() & Qt.ItemIsEnabled
        ]
        settings.setValue("include-path", path)
        # more settings here

    def defaults(self):
        self.autosave.setChecked(True)
        self.basedir.setPath('')
        self.inclPaths.setChecked(False)
        self.replPaths.setChecked(False)
        self.addDisabledGenPaths()
        self.revt.setEnabled(False)
        # more defaults here

    def edit(self, name=None):
        self._originalName = name
        if name:
            caption = _("Edit session: {name}").format(name=name)
            self.name.setText(name)
            self.load(name)
        else:
            caption = _("Edit new session")
            self.name.clear()
            self.name.setFocus()
            self.defaults()
        self.setWindowTitle(app.caption(caption))
        if self.exec_():
            # name changed?
            name = self.name.text()
            if self._originalName and name != self._originalName:
                sessions.renameSession(self._originalName, name)
            self.save(name)
            return name

    def done(self, result):
        if not result or self.validate():
            super(SessionEditor, self).done(result)

    def validate(self):
        """Checks if the input is acceptable.
        
        If this method returns True, the dialog is accepted when OK is clicked.
        Otherwise a messagebox could be displayed, and the dialog will remain
        visible.
        """
        name = self.name.text().strip()
        self.name.setText(name)
        if not name:
            self.name.setFocus()
            QMessageBox.warning(self, app.caption(_("Warning")),
                                _("Please enter a session name."))
            if self._originalName:
                self.name.setText(self._originalName)
            return False

        elif name == '-':
            self.name.setFocus()
            QMessageBox.warning(
                self, app.caption(_("Warning")),
                _("Please do not use the name '{name}'.".format(name="-")))
            return False

        elif self._originalName != name and name in sessions.sessionNames():
            self.name.setFocus()
            box = QMessageBox(
                QMessageBox.Warning, app.caption(_("Warning")),
                _("Another session with the name {name} already exists.\n\n"
                  "Do you want to overwrite it?").format(name=name),
                QMessageBox.Discard | QMessageBox.Cancel, self)
            box.button(QMessageBox.Discard).setText(_("Overwrite"))
            result = box.exec_()
            if result != QMessageBox.Discard:
                return False

        return True
예제 #16
0
class TalkDetailsWidget(QWidget):
    def __init__(self, parent=None):
        super(TalkDetailsWidget, self).__init__(parent)

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

        self.buttonLayout = QHBoxLayout()

        saveIcon = QIcon.fromTheme("document-save")
        self.saveButton = QPushButton('Save Talk')
        self.saveButton.setIcon(saveIcon)
        self.buttonLayout.addWidget(self.saveButton)

        self.layout.addLayout(self.buttonLayout, 0, 1, 1, 1)

        self.titleLabel = QLabel('Title')
        self.titleLineEdit = QLineEdit()
        self.presenterLabel = QLabel('Presenter')
        self.presenterLineEdit = QLineEdit()
        self.layout.addWidget(self.titleLabel, 1, 0, 1, 1)
        self.layout.addWidget(self.titleLineEdit, 1, 1, 1, 1)
        self.layout.addWidget(self.presenterLabel, 1, 2, 1, 1)
        self.layout.addWidget(self.presenterLineEdit, 1, 3, 1, 1)

        self.eventLabel = QLabel('Event')
        self.eventLineEdit = QLineEdit()
        self.categoryLabel = QLabel('Category')
        self.categoryLineEdit = QLineEdit()

        self.layout.addWidget(self.eventLabel, 2, 0, 1, 1)
        self.layout.addWidget(self.eventLineEdit, 2, 1, 1, 1)
        self.layout.addWidget(self.categoryLabel, 2, 2, 1, 1)
        self.layout.addWidget(self.categoryLineEdit, 2, 3, 1, 1)

        self.roomLabel = QLabel('Room')
        self.roomLineEdit = QLineEdit()
        self.dateLayout = QHBoxLayout()
        self.dateLabel = QLabel('Date')
        self.dateEdit = QDateEdit()
        currentDate = QDate()
        self.dateEdit.setDate(currentDate.currentDate())
        self.dateEdit.setCalendarPopup(True)

        self.layout.addWidget(self.roomLabel, 3, 0, 1, 1)
        self.layout.addWidget(self.roomLineEdit, 3, 1, 1, 1)
        self.dateLayout.addWidget(self.dateEdit)
        self.layout.addWidget(self.dateLabel, 3, 2, 1, 1)
        self.layout.addLayout(self.dateLayout, 3, 3, 1, 1)

        self.startTimeLayout = QHBoxLayout()
        self.startTimeLabel = QLabel('Start Time')
        self.startTimeEdit = QTimeEdit()
        self.startTimeLayout.addWidget(self.startTimeEdit)
        self.endTimeLayout = QHBoxLayout()
        self.endTimeLabel = QLabel('End Time')
        self.endTimeEdit = QTimeEdit()
        self.endTimeLayout.addWidget(self.endTimeEdit)

        self.layout.addWidget(self.startTimeLabel, 4, 0, 1, 1)
        self.layout.addLayout(self.startTimeLayout, 4, 1, 1, 1)
        self.layout.addWidget(self.endTimeLabel, 4, 2, 1, 1)
        self.layout.addLayout(self.endTimeLayout, 4, 3, 1, 1)

        self.descriptionLabel = QLabel('Description')
        self.descriptionLabel.setAlignment(Qt.AlignTop)
        self.descriptionTextEdit = QPlainTextEdit()
        self.layout.addWidget(self.descriptionLabel, 5, 0, 1, 1)
        self.layout.addWidget(self.descriptionTextEdit, 5, 1, 1, 3)

    def enable_input_fields(self):
        self.titleLineEdit.setPlaceholderText("Enter Talk Title")
        self.presenterLineEdit.setPlaceholderText("Enter Presenter Name")
        self.categoryLineEdit.setPlaceholderText("Enter Category Type")
        self.eventLineEdit.setPlaceholderText("Enter Event Name")
        self.roomLineEdit.setPlaceholderText("Enter Room Location")
        self.titleLineEdit.setEnabled(True)
        self.presenterLineEdit.setEnabled(True)
        self.categoryLineEdit.setEnabled(True)
        self.eventLineEdit.setEnabled(True)
        self.roomLineEdit.setEnabled(True)
        self.dateEdit.setEnabled(True)
        self.startTimeEdit.setEnabled(True)
        self.endTimeEdit.setEnabled(True)
        self.descriptionTextEdit.setEnabled(True)

    def disable_input_fields(self):
        self.titleLineEdit.setPlaceholderText("")
        self.presenterLineEdit.setPlaceholderText("")
        self.categoryLineEdit.setPlaceholderText("")
        self.eventLineEdit.setPlaceholderText("")
        self.roomLineEdit.setPlaceholderText("")
        self.titleLineEdit.setEnabled(False)
        self.presenterLineEdit.setEnabled(False)
        self.categoryLineEdit.setEnabled(False)
        self.eventLineEdit.setEnabled(False)
        self.roomLineEdit.setEnabled(False)
        self.dateEdit.setEnabled(False)
        self.startTimeEdit.setEnabled(False)
        self.endTimeEdit.setEnabled(False)
        self.descriptionTextEdit.setEnabled(False)

    def clear_input_fields(self):
        self.titleLineEdit.clear()
        self.presenterLineEdit.clear()
        self.categoryLineEdit.clear()
        self.eventLineEdit.clear()
        self.roomLineEdit.clear()
        self.descriptionTextEdit.clear()
예제 #17
0
class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        self.fnames = []  # list of file names to be converted
        self.office_listener_started = False

        self.parse_cla()

        addQPB = QPushButton(self.tr('Add'))
        delQPB = QPushButton(self.tr('Delete'))
        clearQPB = QPushButton(self.tr('Clear'))
        vlayout1 = utils.add_to_layout('v', addQPB, delQPB, clearQPB, None)

        self.filesList = utils.FilesList()
        self.filesList.setSelectionMode(QAbstractItemView.ExtendedSelection)
        hlayout1 = utils.add_to_layout('h', self.filesList, vlayout1)

        outputQL = QLabel(self.tr('Output folder:'))
        self.toQLE = QLineEdit()
        self.toQLE.setReadOnly(True)
        self.toQTB = QToolButton()
        self.toQTB.setText('...')
        hlayout2 = utils.add_to_layout('h', outputQL, self.toQLE, self.toQTB)

        self.audiovideo_tab = AudioVideoTab(self)
        self.image_tab = ImageTab(self)
        self.document_tab = DocumentTab(self)

        self.tabs = [self.audiovideo_tab, self.image_tab, self.document_tab]
        tab_names = [
            self.tr('Audio/Video'),
            self.tr('Images'),
            self.tr('Documents')
        ]

        self.tabWidget = QTabWidget()
        for num, tab in enumerate(tab_names):
            self.tabWidget.addTab(self.tabs[num], tab)
        self.tabWidget.setCurrentIndex(0)

        self.origQCB = QCheckBox(
            self.tr('Save each file in the same\nfolder as input file'))
        self.deleteQCB = QCheckBox(self.tr('Delete original'))
        convertQPB = QPushButton(self.tr('&Convert'))

        hlayout3 = utils.add_to_layout('h', self.origQCB, self.deleteQCB, None)
        hlayout4 = utils.add_to_layout('h', None, convertQPB)
        final_layout = utils.add_to_layout('v', hlayout1, self.tabWidget,
                                           hlayout2, hlayout3, hlayout4)

        self.dependenciesQL = QLabel()
        self.statusBar().addPermanentWidget(self.dependenciesQL, stretch=1)

        widget = QWidget()
        widget.setLayout(final_layout)
        self.setCentralWidget(widget)

        openAction = utils.create_action(self, self.tr('Open'),
                                         QKeySequence.Open, None,
                                         self.tr('Open a file'),
                                         self.add_files)
        convertAction = utils.create_action(self, self.tr('Convert'), 'Ctrl+C',
                                            None, self.tr('Convert files'),
                                            self.start_conversion)
        quitAction = utils.create_action(self, self.tr('Quit'), 'Ctrl+Q', None,
                                         self.tr('Quit'), self.close)
        edit_presetsAction = utils.create_action(self, self.tr('Edit Presets'),
                                                 'Ctrl+P', None,
                                                 self.tr('Edit Presets'),
                                                 self.open_dialog_presets)
        importAction = utils.create_action(self, self.tr('Import'), None, None,
                                           self.tr('Import presets'),
                                           self.import_presets)
        exportAction = utils.create_action(self, self.tr('Export'), None, None,
                                           self.tr('Export presets'),
                                           self.export_presets)
        resetAction = utils.create_action(self, self.tr('Reset'), None, None,
                                          self.tr('Reset presets'),
                                          self.reset_presets)
        syncAction = utils.create_action(self, self.tr('Synchronize'), None,
                                         None, self.tr('Synchronize presets'),
                                         self.sync_presets)
        removeoldAction = utils.create_action(self, self.tr('Remove old'),
                                              None, None,
                                              self.tr('Remove old presets'),
                                              self.removeold_presets)
        clearallAction = utils.create_action(self, self.tr('Clear All'), None,
                                             None, self.tr('Clear form'),
                                             self.clear_all)
        preferencesAction = utils.create_action(self, self.tr('Preferences'),
                                                'Alt+Ctrl+P', None,
                                                self.tr('Preferences'),
                                                self.open_dialog_preferences)
        trackerAction = utils.create_action(
            self, 'Issue tracker', None, None, None, lambda: webbrowser.open(
                "https://github.com/Ilias95/FF-Multi-Converter/issues"))
        wikiAction = utils.create_action(
            self, 'Wiki', None, None, None, lambda: webbrowser.open(
                "https://github.com/Ilias95/FF-Multi-Converter/wiki"))
        ffmpegdocAction = utils.create_action(
            self, 'FFmpeg ' + self.tr('documentation'), None, None, None,
            lambda: webbrowser.open("https://www.ffmpeg.org/documentation.html"
                                    ))
        imagemagickdocAction = utils.create_action(
            self, 'ImageMagick ' + self.tr('documentation'), None, None, None,
            lambda: webbrowser.open(
                "http://www.imagemagick.org/script/convert.php"))
        aboutAction = utils.create_action(self, self.tr('About'), 'Ctrl+?',
                                          None, self.tr('About'),
                                          self.open_dialog_about)

        fileMenu = self.menuBar().addMenu(self.tr('File'))
        editMenu = self.menuBar().addMenu(self.tr('Edit'))
        presetsMenu = self.menuBar().addMenu(self.tr('Presets'))
        helpMenu = self.menuBar().addMenu(self.tr('Help'))

        utils.add_actions(fileMenu,
                          [openAction, convertAction, None, quitAction])
        utils.add_actions(presetsMenu, [
            edit_presetsAction, importAction, exportAction, resetAction, None,
            syncAction, removeoldAction
        ])
        utils.add_actions(editMenu, [clearallAction, None, preferencesAction])
        utils.add_actions(helpMenu, [
            trackerAction, wikiAction, None, ffmpegdocAction,
            imagemagickdocAction, None, aboutAction
        ])

        self.filesList.dropped.connect(self.add_files_dropped)
        addQPB.clicked.connect(self.add_files)
        delQPB.clicked.connect(self.delete_files)
        clearQPB.clicked.connect(self.clear_fileslist)
        self.tabWidget.currentChanged.connect(
            lambda: self.tabs[0].moreQPB.setChecked(False))
        self.origQCB.toggled.connect(
            lambda: self.toQLE.setEnabled(not self.origQCB.isChecked()))
        self.toQTB.clicked.connect(self.open_dir)
        convertQPB.clicked.connect(convertAction.triggered)

        del_shortcut = QShortcut(self)
        del_shortcut.setKey(Qt.Key_Delete)
        del_shortcut.activated.connect(self.delete_files)

        self.setWindowTitle('FF Multi Converter')

        QTimer.singleShot(0, self.check_for_dependencies)
        QTimer.singleShot(0, self.load_settings)
        QTimer.singleShot(0, self.audiovideo_tab.set_default_command)
        QTimer.singleShot(0, self.image_tab.set_default_command)
        QTimer.singleShot(0, self.update_filesList)

    def parse_cla(self):
        """Parse command line arguments."""
        for i in QCoreApplication.argv()[1:]:
            i = os.path.abspath(i)
            if os.path.isfile(i):
                self.fnames.append(i)
            else:
                print("ffmulticonverter: {0}: Not a file".format(i))

    def check_for_dependencies(self):
        """
        Check if each one of the program dependencies are installed and
        update self.dependenciesQL with the appropriate message.
        """
        self.vidconverter = None
        if utils.is_installed('ffmpeg'):
            self.vidconverter = 'ffmpeg'
        elif utils.is_installed('avconv'):
            self.vidconverter = 'avconv'
        self.unoconv = utils.is_installed('unoconv')
        self.imagemagick = utils.is_installed('convert')

        missing = []
        if self.vidconverter is None:
            missing.append('ffmpeg/avconv')
        if not self.unoconv:
            missing.append('unoconv')
        if not self.imagemagick:
            missing.append('imagemagick')

        if missing:
            missing = ', '.join(missing)
            status = self.tr('Missing dependencies:') + ' ' + missing
            self.dependenciesQL.setText(status)

    def load_settings(self, onstart=True):
        """
        Load settings values.

        onstart -- True means that this is the first time the method called,
                   usually when program beggins
        """
        def get_str_value(settings, name):
            value = settings.value(name)
            if value is not None:
                return value
            return ''

        settings = QSettings()
        self.overwrite_existing = utils.str_to_bool(
            get_str_value(settings, 'overwrite_existing'))
        self.default_output = get_str_value(settings, 'default_output')
        self.prefix = get_str_value(settings, 'prefix')
        self.suffix = get_str_value(settings, 'suffix')
        defcmd = get_str_value(settings, 'default_command')
        extraformats_video = get_str_value(settings, 'extraformats')
        videocodecs = settings.value('videocodecs')
        audiocodecs = settings.value('audiocodecs')
        defcmd_image = get_str_value(settings, 'default_command_image')
        extraformats_image = get_str_value(settings, 'extraformats_image')

        if videocodecs is None:
            videocodecs = "\n".join(config.video_codecs)
            settings.setValue('videocodecs', videocodecs)
        if audiocodecs is None:
            audiocodecs = "\n".join(config.audio_codecs)
            settings.setValue('audiocodecs', audiocodecs)

        if defcmd:
            self.default_command = defcmd
        else:
            self.default_command = config.default_ffmpeg_cmd
        if defcmd_image:
            self.default_command_image = defcmd_image
        else:
            self.default_command_image = config.default_imagemagick_cmd

        self.audiovideo_tab.fill_video_comboboxes(videocodecs, audiocodecs,
                                                  extraformats_video)
        self.image_tab.fill_extension_combobox(extraformats_image)

        if onstart:
            self.toQLE.setText(self.default_output)

    def current_tab(self):
        """Return the corresponding object of the selected tab."""
        for i in self.tabs:
            if self.tabs.index(i) == self.tabWidget.currentIndex():
                return i

    def update_filesList(self):
        """Clear self.filesList and add to it all items of self.fname."""
        self.filesList.clear()
        for i in self.fnames:
            self.filesList.addItem(i)

    def add_files(self):
        """
        Get file names using a standard Qt dialog.
        Append to self.fnames each file name that not already exists
        and update self.filesList.
        """
        # Create lists holding file formats extension.
        # To be passed in QFileDialog.getOpenFileNames().
        all_files = '*'
        audiovideo_files = ' '.join(
            ['*.' + i for i in self.audiovideo_tab.formats])
        img_formats = self.image_tab.formats[:]
        img_formats.extend(self.image_tab.extra_img)
        image_files = ' '.join(['*.' + i for i in img_formats])
        document_files = ' '.join(
            ['*.' + i for i in self.document_tab.formats])
        formats = [all_files, audiovideo_files, image_files, document_files]
        strings = [
            self.tr('All Files'),
            self.tr('Audio/Video Files'),
            self.tr('Image Files'),
            self.tr('Document Files')
        ]

        filters = ''
        for string, extensions in zip(strings, formats):
            filters += string + ' ({0});;'.format(extensions)
        filters = filters[:-2]  # remove last ';;'

        fnames = QFileDialog.getOpenFileNames(
            self, 'FF Multi Converter - ' + self.tr('Choose File'),
            config.home, filters)

        if fnames:
            for i in fnames:
                if not i in self.fnames:
                    self.fnames.append(i)
            self.update_filesList()

    def add_files_dropped(self, links):
        """
        Append to self.fnames each file name that not already exists
        and update self.filesList.
        """
        for path in links:
            if os.path.isfile(path) and not path in self.fnames:
                self.fnames.append(path)
        self.update_filesList()

    def delete_files(self):
        """
        Get selectedItems of self.filesList, remove them from self.fnames and
        update the filesList.
        """
        items = self.filesList.selectedItems()
        if items:
            for i in items:
                self.fnames.remove(i.text())
            self.update_filesList()

    def clear_fileslist(self):
        """Make self.fnames empty and update self.filesList."""
        self.fnames = []
        self.update_filesList()

    def clear_all(self):
        """Clear all values of graphical widgets."""
        self.toQLE.clear()
        self.origQCB.setChecked(False)
        self.deleteQCB.setChecked(False)
        self.clear_fileslist()

        self.audiovideo_tab.clear()
        self.image_tab.clear()

    def open_dir(self):
        """
        Get a directory name using a standard QtDialog and update
        self.toQLE with dir's name.
        """
        if self.toQLE.isEnabled():
            output = QFileDialog.getExistingDirectory(
                self,
                'FF Multi Converter - ' + self.tr('Choose output destination'),
                config.home)
            if output:
                self.toQLE.setText(output)

    def import_presets(self):
        presets_dlgs.ShowPresets().import_presets()

    def export_presets(self):
        presets_dlgs.ShowPresets().export_presets()

    def reset_presets(self):
        presets_dlgs.ShowPresets().reset()

    def sync_presets(self):
        presets_dlgs.ShowPresets().synchronize()

    def removeold_presets(self):
        presets_dlgs.ShowPresets().remove_old()

    def ok_to_continue(self):
        """
        Check if everything is ok to continue with conversion.

        Check if:
        - At least one file has given for conversion.
        - An output folder has given.
        - Output folder exists.

        Return False if an error arises, else True.
        """
        try:
            if not self.fnames:
                raise ValidationError(
                    self.tr('You must add at least one file to convert!'))
            elif not self.origQCB.isChecked() and not self.toQLE.text():
                raise ValidationError(
                    self.tr('You must choose an output folder!'))
            elif (not self.origQCB.isChecked()
                  and not os.path.exists(self.toQLE.text())):
                raise ValidationError(
                    self.tr('Output folder does not exists!'))
            if not self.current_tab().ok_to_continue():
                return False
            return True

        except ValidationError as e:
            QMessageBox.warning(self,
                                'FF Multi Converter - ' + self.tr('Error!'),
                                str(e))
            return False

    def get_output_extension(self):
        """Extract the desired output file extension from GUI and return it."""
        tab = self.current_tab()
        if tab.name == 'AudioVideo':
            ext_to = self.audiovideo_tab.extQCB.currentText()
        elif tab.name == 'Images':
            ext_to = tab.extQCB.currentText()
        else:
            ext_to = tab.convertQCB.currentText().split()[-1]

        return '.' + ext_to

    def start_conversion(self):
        """
        Extract the appropriate information from GUI and call the
        Progress dialog with the suitable argumens.
        """
        if not self.ok_to_continue():
            return

        tab = self.current_tab()
        if tab.name == 'Documents' and not self.office_listener_started:
            utils.start_office_listener()
            self.office_listener_started = True

        ext_to = self.get_output_extension()
        _list = utils.create_paths_list(self.fnames, ext_to, self.prefix,
                                        self.suffix, self.toQLE.text(),
                                        self.origQCB.isChecked(),
                                        self.overwrite_existing)

        dialog = progress.Progress(_list, tab, self.deleteQCB.isChecked(),
                                   self)
        dialog.show()

    def open_dialog_preferences(self):
        """Open the preferences dialog."""
        dialog = preferences_dlg.Preferences(self)
        if dialog.exec_():
            self.load_settings(onstart=False)

    def open_dialog_presets(self):
        """Open the presets dialog."""
        dialog = presets_dlgs.ShowPresets(self)
        dialog.exec_()

    def open_dialog_about(self):
        """Call the about dialog with the appropriate values."""
        msg = self.tr('Convert among several file types to other formats')
        msg = textwrap.fill(msg, 54).replace('\n', '<br>')
        text = '''<b> FF Multi Converter {0} </b>
                 <p>{1}
                 <p><a href="{2}">FF Multi Converter - Home Page</a>
                 <p>Copyright &copy; 2011-2015 {3}
                 <br>License: {4}
                 <p>Python {5} - Qt {6} - PyQt {7} on {8}'''\
                 .format(ffmc.__version__, msg, ffmc.__url__, ffmc.__author__,
                         ffmc.__license__, platform.python_version()[:5],
                         QT_VERSION_STR, PYQT_VERSION_STR, platform.system())
        image = ':/ffmulticonverter.png'
        authors = '{0} <{1}>\n\n'.format(ffmc.__author__,
                                         ffmc.__author_email__)
        authors += 'Contributors:\nPanagiotis Mavrogiorgos'
        translators = []
        for i in config.translators:
            translators.append('{0}\n     {1}'.format(i[0], i[1]))
        translators = '\n\n'.join(translators)

        dialog = about_dlg.AboutDialog(text, image, authors, translators, self)
        dialog.exec_()
예제 #18
0
파일: main.py 프로젝트: xiaq/chat
class MainWindow(QWidget):
    def __init__(self):
        super(MainWindow, self).__init__()

        self.createServer()
        self.configureWindow()
        self.createUi()
        self.readConfig()
        self.loginName = ''

        for cmd in self.config['autorun']:
            self.evalCmd(cmd)

    def configureWindow(self):
        self.setWindowTitle('Simple Chat Program')
        self.resize(700, 600)
        self.center()

    def readConfig(self):
        self.config = {
            'friends': [],
            'autorun': [],
            'receiveDirectory': 'received',
        }
        path = os.path.join(mydir, 'config.json')
        try:
            with open(path, 'r') as f:
                self.config.update(json.load(f))
        except IOError:
            self.buf.error('Cannot read configuration file %s.' % path)
        except ValueError:
            self.buf.error('Configuration file %s contains errors.' % path)

        rdir = self.config['receiveDirectory']
        if os.path.isabs(rdir):
            self.receiveDirectory = rdir
        else:
            self.receiveDirectory = os.path.join(mydir, rdir)

    def createUi(self):
        main = QHBoxLayout()

        console = QVBoxLayout()
        self.buf = TextBrowser()
        self.buf.setFontFamily('monospace')
        self.buf.setFocusPolicy(Qt.NoFocus)
        console.addWidget(self.buf)
        self.command_line = QLineEdit()
        console.addWidget(self.command_line)

        main.addLayout(console, 1)
        self.tab = QTabWidget()
        self.tab.setTabsClosable(True)
        self.peers = {}
        main.addWidget(self.tab, 3)

        self.setLayout(main)

        self.command_line.returnPressed.connect(self.onCommand)
        self.tab.tabCloseRequested.connect(self.onTabCloseRequested)

    def createServer(self):
        self.server = QTcpServer()
        if not self.server.listen(port=PEER_PORT):
            QMessageBox.critical(
                self, "Server Error",
                "Cannot start server. Port %d seems in use." % PEER_PORT)
            sys.exit(1)
        self.server.newConnection.connect(self.onNewConnection)

    def center(self):
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

    def addPage(self, socket):
        addr = socket.peerAddress()
        page = ChatWindow(socket, addr)
        self.peers[addr] = page
        self.tab.addTab(page, addr.toString())

    def newActive(self, peer, resolve=True):
        if resolve and peer in self.config['friends']:
            self.buf.info('%s is in friends list, querying...' % peer)

            def cb(res):
                if res == 'n':
                    self.buf.error('%s is offline' % peer)
                elif res[0].isdigit():
                    self.buf.info('%s has IP address %s' % (peer, res))
                    self.newActive(res, False)
                else:
                    self.buf.error('status of %s is unknown' % peer)
            self.talkToCentral('q%s' % peer, u'query', r'', cb, False)
            return

        socket = QTcpSocket()
        socket.connectToHost(peer, PEER_PORT)

        def onConnected():
            self.buf.info('Connected to %s' % peer)
            self.addPage(socket)

        def onError():
            self.buf.error('Error communicating with %s: %s' % (
                peer, socket.errorString()))
        socket.connected.connect(onConnected)
        socket.error.connect(onError)

        self.buf.info('Reaching out to %s...' % peer)

    def talkToCentral(self, msg, name, pattern, cb=None, successMsg=True):
        Name = name.title()
        socket = QTcpSocket()
        socket.connectToHost(CENTRAL_ADDR, CENTRAL_PORT)

        def onConnected():
            socket.write(msg)

            def onReadyRead():
                response = str(socket.readAll())
                if re.match(pattern, response):
                    if successMsg:
                        self.buf.info(u'%s successful.' % Name)
                    if cb:
                        cb(response)
                else:
                    self.buf.error(u'%s failed, server said %s.' %
                        (Name, repr(response)))
                socket.close()
            socket.readyRead.connect(onReadyRead)

        def onError():
            self.buf.error(u'Error %s: %s' %
                (name, urepr(socket.errorString())))

        socket.connected.connect(onConnected)
        socket.error.connect(onError)

    def login(self, obj):
        name, sep, passwd = obj.partition(' ')

        def cb(res):
            self.loginName = name
        self.talkToCentral('%s_%s' % (name, passwd), u'login', r'^lol$', cb)

    def logout(self):
        if not self.loginName:
            self.buf.error(u'Not logged in')
            return

        def cb(res):
            self.loginName = ''

        self.talkToCentral('logout%s' % self.loginName,
                           u'logout', r'^loo$', cb)

    def queryOne(self, p):
        def cb(res):
            if res == 'n':
                self.buf.info('%s: offline' % p)
            elif res[0].isdigit():
                self.buf.info('%s: online, %s' % (p, res))
            else:
                self.buf.info('%s: unknown' % p)
        self.talkToCentral('q%s' % p, u'query', r'', cb, False)

    def query(self, obj):
        if obj:
            self.queryOne(obj)
        else:
            for p in self.config['friends']:
                self.queryOne(p)

    def evalCmd(self, command):
        if len(command) == 0:
            return

        if command[0] != u'/':
            self.buf.info(u"%s taken as implicit /talk" % urepr(command))
            command = u'/talk ' + command

        verb, sep, obj = command[1:].partition(' ')
        if verb in (u't', u'talk'):
            self.newActive(obj)
        elif verb in (u'h', u'help'):
            self.buf.info(COMMANDS_HELP)
        elif verb == u'login':
            self.login(obj)
        elif verb == u'logout':
            self.logout()
        elif verb in (u'q', u'query'):
            self.query(obj)
        else:
            self.buf.error(u'Unknown command %s.' % urepr(verb))

    def onCommand(self):
        self.evalCmd(unicode(self.command_line.text()))
        self.command_line.clear()

    readBufSize = 1024
    text_msg_pattern = re.compile(r'^T(\d+) (.*)$', re.S)
    file_msg_pattern = re.compile(r'^F(\d+) ([^/]+)/(.*)$', re.S)

    def onNewConnection(self):
        socket = self.server.nextPendingConnection()

        def onReadyRead():
            addr = socket.peerAddress()
            if addr not in self.peers:
                self.addPage(socket)

            addr_s = addr.toString()
            payload = str(socket.read(self.readBufSize))

            if payload[0] == 'T':
                payload_m = re.match(self.text_msg_pattern, payload)
                if not payload_m:
                    self.buf.error('Bad text message from %s' % addr_s)
                    return

                size = int(payload_m.group(1))
                segments = [payload_m.group(2)]

                remain = size - len(segments[0])
                while remain > 0:
                    payload = str(socket.read(remain))
                    if len(payload) <= 0:
                        self.buf.error('Incomplete text message from %s'
                                       ' - need %d more bytes' %
                                       (addr_s, remain))
                        break
                    segments.append(payload)
                    remain -= len(payload)
                self.peers[addr].buf.feed(''.join(segments))

            elif payload[0] == 'F':
                payload_m = re.match(self.file_msg_pattern, payload)
                if not payload_m:
                    self.buf.error('Bad file message from %s: %s' % (addr_s,
                        repr(payload)))
                    return

                size = int(payload_m.group(1))
                bname = payload_m.group(2)
                rdir = self.receiveDirectory
                path = os.path.join(rdir, bname)

                with open(path, 'wb') as f:
                    segment = payload_m.group(3)
                    f.write(segment)
                    remain = size - len(segment)
                    while remain > 0:
                        segment = str(socket.read(
                            min(remain, self.readBufSize)))
                        if len(segment) <= 0:
                            self.buf.error('Incomplete file message from %s'
                                           ' - need %d more bytes' %
                                           (addr_s, remain))
                            break
                        f.write(segment)
                        remain -= len(segment)
                self.buf.info('File %s from %s saved at %s' %
                    (repr(bname), addr_s, rdir))

            else:
                self.buf.error('Bad message from %s: unknown type '
                               '"%s"' % (addr.toString(), payload[0]))

        socket.readyRead.connect(onReadyRead)

    def onTabCloseRequested(self, idx):
        page = self.tab.widget(idx)
        self.tab.removeTab(idx)
        page.close()
        page.deleteLater()
예제 #19
0
class SessionsManager(QDialog):
    def __init__(self, n, parent=None):
        super(SessionsManager, self).__init__(parent)
        self.par = n
        #main
        title = Settingz().positions(30)
        self.titleID = title['id']
        self.titlePage = title['page']
        self.titleName = title['name']
        self.titleSub = title['subID']
        self.titleIcon = title['icon']
        self.pagetitle = self.titlePage
        #stylesheet
        stylesheet = Valid().background() + Valid().font()
        treeStyleSheet = Valid().treez()

        self.groupBox1 = QGroupBox(self.titleName)
        self.groupBox2 = QGroupBox('Add')

        #items
        self.tree = QTreeWidget()
        self.tree.setHeaderLabel("Choose " + self.titleName)
        #tree.setItemDelegate(Delegate())
        self.tree.setItemDelegate(Delegates())
        self.tree.headerItem().setText(0, 'Name')
        self.tree.setStyleSheet(treeStyleSheet)
        self.makeTree()
        self.tree.setMinimumHeight(250)
        self.tree.clicked.connect(lambda: self.getSelection())
        self.tree.itemClicked.connect(lambda state: self.getChecked(state))
        #buttons
        #add
        nImg = Buttons().addButton()
        self.pb = QPushButton()
        self.pb.setFlat(True)
        self.pb.setIcon(QIcon(nImg))
        self.pb.setMaximumHeight(30)
        self.pb.setMaximumWidth(30)

        nImg1 = Buttons().closeButton()
        self.pb1 = QPushButton()
        self.pb1.setFlat(True)
        self.pb1.setIcon(QIcon(nImg1))
        self.pb1.setMaximumHeight(30)
        self.pb1.setMaximumWidth(30)

        nImg2 = Buttons().editButton()
        self.pb2 = QPushButton()
        self.pb2.setFlat(True)
        self.pb2.setIcon(QIcon(nImg2))
        self.pb2.setMaximumHeight(30)
        self.pb2.setMaximumWidth(30)

        nImg3 = Buttons().deleteButton()
        self.pb3 = QPushButton()
        self.pb3.setFlat(True)
        self.pb3.setIcon(QIcon(nImg3))
        self.pb3.setMaximumHeight(30)
        self.pb3.setMaximumWidth(30)

        nImg4 = Buttons().saveButton()
        self.pb4 = QPushButton()
        self.pb4.setFlat(True)
        self.pb4.setIcon(QIcon(nImg4))
        self.pb4.setMaximumHeight(30)
        self.pb4.setMaximumWidth(30)

        nImg5 = Buttons().resetButton()
        self.pb5 = QPushButton()
        self.pb5.setFlat(True)
        self.pb5.setIcon(QIcon(nImg5))
        self.pb5.setMaximumHeight(30)
        self.pb5.setMaximumWidth(30)

        nImg6 = Buttons().closeButton()
        self.pb6 = QPushButton()
        self.pb6.setFlat(True)
        self.pb6.setIcon(QIcon(nImg6))
        self.pb6.setMaximumHeight(30)
        self.pb6.setMaximumWidth(30)

        nImg7 = Buttons().addButton()
        self.pb7 = QPushButton()
        self.pb7.setFlat(True)
        self.pb7.setIcon(QIcon(nImg7))
        self.pb7.setMaximumHeight(30)
        self.pb7.setMaximumWidth(30)

        hbo = QHBoxLayout()
        hbo.addStretch()
        hbo.addWidget(self.pb1)
        hbo.addWidget(self.pb3)
        hbo.addWidget(self.pb2)
        hbo.addWidget(self.pb7)

        vbo = QVBoxLayout()
        vbo.addWidget(self.tree)
        vbo.addLayout(hbo)

        self.l1 = QLabel("Name")
        self.le1 = QLineEdit()
        self.le1.setObjectName("name")
        vals1 = Valid().fullNum()
        self.le1.setValidator(vals1)
        self.le1.setPlaceholderText("Lowercase max 25 letters")

        self.fromLbl = QLabel("Starts")
        self.toLbl = QLabel("Ends")
        self.fromData = QDateEdit()
        self.toData = QDateEdit()
        currentDate = QDate()
        self.fromData.setDate(currentDate.currentDate())
        self.fromData.setCalendarPopup(True)
        self.toData.setDate(currentDate.currentDate())
        self.toData.setCalendarPopup(True)

        FormLayout = QFormLayout()
        FormLayout.addRow(self.l1, self.le1)
        FormLayout.addRow(self.fromLbl, self.fromData)
        FormLayout.addRow(self.toLbl, self.toData)

        Hlayout1 = QHBoxLayout()
        Hlayout1.addStretch()
        Hlayout1.addWidget(self.pb6)
        Hlayout1.addWidget(self.pb5)
        Hlayout1.addWidget(self.pb4)
        Hlayout1.addWidget(self.pb)

        Vlayout1 = QVBoxLayout()
        Vlayout1.addLayout(FormLayout)
        Vlayout1.addLayout(Hlayout1)

        self.groupBox1.setLayout(vbo)
        self.groupBox2.setLayout(Vlayout1)
        self.groupBox2.hide()

        self.connect(self.pb, SIGNAL("clicked()"),
                     lambda: self.button_add())  #add
        self.connect(self.pb1, SIGNAL("clicked()"),
                     lambda: self.button_close())  #close
        self.connect(self.pb2, SIGNAL("clicked()"),
                     lambda: self.button_edit())  #edit
        self.connect(self.pb3, SIGNAL("clicked()"),
                     lambda: self.button_delete())  #delete
        self.connect(self.pb4, SIGNAL("clicked()"),
                     lambda: self.button_save())  #save
        self.connect(self.pb5, SIGNAL("clicked()"),
                     lambda: self.button_reset())  #reset

        self.pb4.hide()
        self.pb7.hide()

        grid = QGridLayout()
        grid.addWidget(self.groupBox1, 0, 0)
        grid.addWidget(self.groupBox2, 1, 0)

        self.setLayout(grid)
        self.setStyleSheet(stylesheet)
        self.setWindowIcon(QIcon(self.titleIcon))
        self.setWindowTitle(self.pagetitle)

    def makeTree(self):
        self.tree.clear()
        arr = Db().selectn('session', '', 5)
        self.hold_data = {}
        self.hold_mdata = {}
        self.hold_data_add = {}
        self.hold_data_add_item = {}
        current = time.time()

        if self.titleSub and self.titleSub > 0:
            if arr and len(arr) > 0:
                for val in arr:
                    ch = Valid().pullData('terms', '',
                                          {'sessionID': val['id']})
                    child = QTreeWidgetItem(self.tree)
                    child.setIcon(0, QIcon('icons.cfolder.png'))
                    try:
                        ts = int(float(val['start_date']))
                    except:
                        ts = int(current)
                    ts = datetime.utcfromtimestamp(ts).strftime('%d-%m-%Y')

                    try:
                        ts1 = int(float(val['end_date']))
                    except:
                        ts1 = int(current)
                    ts1 = datetime.utcfromtimestamp(ts1).strftime('%d-%m-%Y')

                    child.setText(
                        0,
                        str(val['name']).upper() + " - " + ts + " " + ts1)
                    self.hold_mdata[val['id']] = child

                    for va in ch:
                        child1 = QTreeWidgetItem(child)
                        child1.setFlags(child1.flags()
                                        | Qt.ItemIsUserCheckable)

                        try:
                            ts2 = int(float(va['start_date']))
                        except:
                            ts2 = int(current)
                        ts2 = datetime.utcfromtimestamp(ts2).strftime(
                            '%d-%m-%Y')
                        try:
                            ts3 = int(float(va['end_date']))
                        except:
                            ts3 = int(current)
                        ts3 = datetime.utcfromtimestamp(ts3).strftime(
                            '%d-%m-%Y')

                        child1.setText(
                            0,
                            str(va['name']).upper() + " " + ts2 + " " + ts3)
                        self.hold_data[va['id']] = child1
                        if (va['active'] == 1):
                            child1.setCheckState(0, Qt.Checked)
                        else:
                            child1.setCheckState(0, Qt.Unchecked)

                    child1 = QTreeWidgetItem(child)
                    child1.setFlags(child1.flags() | Qt.ItemIsUserCheckable)
                    child1.setText(0, 'Add New Term')
                    self.hold_data_add_item[val['id']] = child1
        else:
            if arr and len(arr) > 0:
                for val in arr:
                    child = QTreeWidgetItem(self.tree)
                    child.setFlags(child.flags() | Qt.ItemIsUserCheckable)
                    child.setText(0, str(val['name']).upper())
                    child.setText(1, str(val['abbrv']).upper())
                    self.hold_data[val['id']] = child
                    if (val['active'] == 0):
                        child.setCheckState(0, Qt.Checked)
                    else:
                        child.setCheckState(0, Qt.Unchecked)

        child = QTreeWidgetItem(self.tree)
        child.setFlags(child.flags() | Qt.ItemIsUserCheckable)
        child.setText(0, 'Add New Session')
        self.hold_data_add['addnew'] = child

    def getChecked(self, a):
        arr_hold = []
        g = Db()
        for i in self.hold_data:
            if self.hold_data[i].checkState(0) == Qt.Checked:
                arr_hold.append(i)
                self.hold_data[i].setCheckState(0, Qt.Checked)
                g.update('terms', {'active': 0}, {'active': 1})
                g.update('terms', {'active': 1}, {'id': i})
                tt = g.selectn('terms', '', 1, {'id': i})
                g.update('session', {'active': 0}, {'active': 1})
                g.update('session', {'active': 1}, {'id': tt['sessionID']})
                g.selectn('session', '', 1, {'id': tt['sessionID']})
            else:
                self.hold_data[i].setCheckState(0, Qt.Unchecked)

        self.reloadTerm()

    def reloadTerm(self):
        session = self.par.activeTerm()
        activeTerm = str(session[1]) + ' SESSION ' + str(session[3]) + ' TERM'
        self.par.majorSession = session[2]
        self.par.lbl.setText(activeTerm)

    def getSelected(self):
        r = False
        self.sessionMain = False
        for i in self.hold_mdata:
            if self.hold_mdata[i].isSelected():
                r = i

        if r and r > 0:
            self.groupBox2.show()
            self.sessionMain = True
            return r
        else:
            for i in self.hold_data:
                if self.hold_data[i].isSelected():
                    r = i
            if r and r > 0:
                self.sessionMain = False
                self.groupBox2.show()
                return r
            else:
                self.groupBox2.hide()

    def getSession(self):
        self.sessionID = None
        for i in self.hold_data_session:
            if self.hold_data_session[i].isSelected():
                r = i
        if r and r > 0:
            self.sessionID = r

    def getSelection(self):
        self.le1.clear()
        currentDate = QDate()
        self.fromData.setDate(currentDate.currentDate())
        self.toData.setDate(currentDate.currentDate())
        self.sessionMain = False

        if self.hold_data_add['addnew'].isSelected():
            self.groupBox2.setTitle('Add New')
            self.groupBox2.show()
            self.sessionMain = True
            self.sessionID = False
        else:
            self.sessionMain = False
            r = None
            for i in self.hold_data_add_item:
                if self.hold_data_add_item[i].isSelected():
                    r = i
            if r:
                g = Db()
                v = g.selectn('session', '', 1, {'id': r})
                vname = str(v['name']).upper() + ' Session'
                self.groupBox2.setTitle('ADD ' + str(vname) + ' Term')
                self.sessionID = r
                self.groupBox2.show()
            else:
                self.groupBox2.setTitle('Add')
                self.sessionID = False
                self.groupBox2.hide()

    def setActive(self):
        g = Db()
        for i in self.hold_data:
            if self.hold_data[i].checkState(0) == Qt.Checked:
                g.update('datas', {'active': 0}, {'id': i})
            else:
                g.update('datas', {'active': 1}, {'id': i})

    def button_add(self):
        s1 = self.le1.text()
        _datef = self.fromData.date().toPyDate()
        _datef = time.mktime(_datef.timetuple())
        _datee = self.toData.date().toPyDate()
        _datee = time.mktime(_datee.timetuple())
        g = Db()

        if self.sessionID and self.sessionID > 0:
            try:
                if (len(s1) > 0):
                    y = {
                        'name': s1.lower(),
                        'start_date': _datef,
                        'sessionID': self.sessionID,
                        'end_date': _datee,
                        'active': 0
                    }
                    z = g.insert('terms', y)
                    if z and z > 0:
                        g.createClass(z)
                        g.createSubject(z)
                        g.createFee(z)
                        g.createPay(z)
                        g.createResult(z)
                        g.createAffective(z)
                        g.createPsychomoto(z)
                    self.makeTree()
                    self.button_reset()
                    self.par.menuSession()
                    self.par.dropdownSession()
                else:
                    pass
            except:
                pass
        else:
            try:
                if (len(s1) > 0):
                    y = {
                        'name': s1.lower(),
                        'start_date': _datef,
                        'end_date': _datee,
                        'active': 0
                    }
                    z = g.insert('session', y)
                    if z and z > 0:
                        g.createExpenses(z)
                        g.createStores(z)
                        g.createAwards(z)
                        g.createConducts(z)
                        g.createMails(z)
                        g.createMedicals(z)
                    self.makeTree()
                    self.button_reset()
                    self.par.menuSession()
                    self.par.dropdownSession()
                else:
                    pass
            except:
                pass

    def button_save(self):
        row = self.editrow
        s1 = self.le1.text()
        _datef = self.fromData.date().toPyDate()
        _datef = time.mktime(_datef.timetuple())
        _datee = self.toData.date().toPyDate()
        _datee = time.mktime(_datee.timetuple())

        g = Db()

        if (len(s1) > 0) and row and row > 0:
            if self.sessionID and self.sessionID > 0:
                try:
                    if (len(s1) > 0):
                        y = {
                            'name': s1.lower(),
                            'start_date': _datef,
                            'sessionID': self.sessionID,
                            'end_date': _datee,
                            'active': 0
                        }
                        k = {'id': row}
                        g.update('terms', y, k)
                        z = row
                        if z and z > 0:
                            g.createClass(z)
                            g.createSubject(z)
                            g.createFee(z)
                            g.createPay(z)
                            g.createResult(z)
                            g.createAffective(z)
                            g.createPsychomoto(z)
                        self.makeTree()
                        self.button_reset()
                        self.par.menuSession()
                        self.par.dropdownSession()
                    else:
                        pass
                except:
                    pass
            else:
                try:
                    if (len(s1) > 0):
                        y = {
                            'name': s1.lower(),
                            'start_date': _datef,
                            'end_date': _datee,
                            'active': 0
                        }
                        k = {'id': row}
                        g.update('session', y, k)
                        z = row
                        if z and z > 0:
                            g.createExpenses(z)
                            g.createStores(z)
                            g.createAwards(z)
                            g.createConducts(z)
                            g.createMails(z)
                            g.createMedicals(z)
                        self.makeTree()
                        self.button_reset()
                        self.par.menuSession()
                        self.par.dropdownSession()
                    else:
                        pass
                except:
                    pass

    def button_delete(self):
        row = self.getSelected()
        g = Db()
        try:
            if row and row > 0:
                y = {'abbrv': '', 'active': 2}
                z = {'id': row}
                g.update('datas', y, z)
                self.makeTree()
            else:
                pass
        except:
            pass

    def button_reset(self):
        self.le1.clear()
        currentDate = QDate()
        self.fromData.setDate(currentDate.currentDate())
        self.toData.setDate(currentDate.currentDate())
        self.groupBox2.setTitle('Add')
        self.groupBox2.hide()
        self.pb.show()
        self.pb4.hide()

    def button_edit(self):
        row = self.getSelected()
        currentDate = QDate()
        if row:
            self.editrow = row
            g = Db()
            if self.sessionMain:
                data = g.selectn('session', '', 1, {'id': row})
                data_name = str(data['name'])
                self.groupBox2.setTitle('Edit')
                self.sessionID = False
            else:
                data = g.selectn('terms', '', 1, {'id': row})
                data_sess = g.selectn('session', '', 1,
                                      {'id': data['sessionID']})
                data_name = str(data['name'])
                self.sessionID = data['sessionID']
                self.groupBox2.setTitle('Edit ' + str(data_sess['name']))
            try:
                self.le1.setText(data_name)
            except:
                self.le1.setText('')
            try:
                self.fromData.setDate(data['start_date'])
            except:
                self.fromData.setDate(currentDate.currentDate())
            try:
                self.toData.setDate(data['end_date'])
            except:
                self.toData.setDate(currentDate.currentDate())
            self.pb.hide()
            self.pb4.show()

    def button_close(self):
        self.close()
예제 #20
0
class EditorDialog(KPageDialog):
    """A dialog to edit properties of a session.
    
    You can subclass this to add more settings to a session config dialog.
    Add more pages in the __init__() method, and inherit the validate() method
    to check the input if necessary. Implement the load and save methods to
    load and save the settings.
    
    """
    def __init__(self, manager):
        super(EditorDialog, self).__init__(manager.mainwin)
        self.mainwin = manager.mainwin
        self.sm = manager
        self.setButtons(KDialog.ButtonCode(
            KDialog.Help | KDialog.Ok | KDialog.Cancel))
        self.setFaceType(KPageDialog.List)
        self.setHelp("sessions")
        
        # First page with name and auto-save option
        page = QWidget(self)
        item = self.firstPage = self.addPage(page, i18n("Session"))
        item.setHeader(i18n("Properties of this session"))
        item.setIcon(KIcon("configure"))
        
        layout = QGridLayout(page)
        
        l = QLabel(i18n("Name:"))
        self.name = QLineEdit()
        l.setBuddy(self.name)
        layout.addWidget(l, 0, 0)
        layout.addWidget(self.name, 0, 1)
        
        self.autosave = QCheckBox(i18n(
            "Always save the list of documents in this session"))
        layout.addWidget(self.autosave, 1, 1)
        
        l = QLabel(i18n("Base directory:"))
        self.basedir = KUrlRequester()
        self.basedir.setMode(KFile.Mode(
            KFile.Directory | KFile.ExistingOnly | KFile.LocalOnly))
        l.setBuddy(self.basedir)
        layout.addWidget(l, 2, 0)
        layout.addWidget(self.basedir, 2, 1)
        
    def edit(self, name=None):
        """Edit the named or new (if not given) session."""
        # load the session
        self._originalName = name
        if name:
            self.setCaption(i18n("Edit session: %1", name))
            self.name.setText(name)
            conf = self.sm.config(name)
            self.autosave.setChecked(conf.readEntry("autosave", True))
            self.basedir.setUrl(KUrl(conf.readPathEntry("basedir", "")))
            self.loadSessionConfig(conf)
        else:
            self.setCaption(i18n("Edit new session"))
            self.name.clear()
            self.name.setFocus()
            self.autosave.setChecked(True)
            self.basedir.setUrl(KUrl())
            self.loadSessionDefaults()
        self.setCurrentPage(self.firstPage)
        if self.exec_():
            # save
            name = self.name.text()
            if self._originalName and name != self._originalName:
                self.sm.renameSession(self._originalName, name)
            conf = self.sm.config(name)
            conf.writeEntry("autosave", self.autosave.isChecked())
            conf.writePathEntry("basedir", self.basedir.url().path())
            self.saveSessionConfig(conf)
            return name

    def done(self, result):
        if not result or self.validate():
            super(EditorDialog, self).done(result)
        
    def validate(self):
        """Checks if the input is acceptable.
        
        If this method returns True, the dialog is accepted when OK is clicked.
        Otherwise a messagebox could be displayed, and the dialog will remain
        visible.
        """
        # strip off whitespace
        name = self.name.text().strip()
        self.name.setText(name)
        
        if not name:
            self.setCurrentPage(self.firstPage)
            self.name.setFocus()
            KMessageBox.error(self, i18n("Please enter a session name."))
            if self._originalName:
                self.name.setText(self._originalName)
            return False
        
        if name == 'none':
            self.setCurrentPage(self.firstPage)
            self.name.setFocus()
            KMessageBox.error(self, i18n(
                "Please do not use the name '%1'.", "none"))
            return False
        
        if '&' in name:
            self.setCurrentPage(self.firstPage)
            self.name.setFocus()
            KMessageBox.error(self, i18n(
                "Please do not use the ampersand (&) character "
                "in a session name."))
            return False
            
        if self._originalName != name and name in self.sm.names():
            self.setCurrentPage(self.firstPage)
            self.name.setFocus()
            if KMessageBox.warningContinueCancel(self, i18n(
                "Another session with the name %1 exists already.\n\n"
                "Do you want to overwrite it?", name), None,
                KStandardGuiItem.overwrite(), KStandardGuiItem.cancel(),
                "session_overwrite") == KMessageBox.Cancel:
                return False
            
        return True
    
    def loadSessionDefaults(self):
        """Implement to set defaults for your new session."""
        pass
    
    def loadSessionConfig(self, conf):
        """Implement to load settings from the config group for this session."""
        pass
    
    def saveSessionConfig(self, conf):
        """Implement to save settings to the config group for this session."""
        pass
예제 #21
0
class NotificationWidget(QWidget):
    """Widget for notification phone numbers"""
    def __init__(self, name, default, parent=None):
        """
        Initialise layout.

        Arguments:
        name - Name of the widget
        default - Default value for the widget
        parent - Parent widget

        Returns:
        None
        """
        super(NotificationWidget, self).__init__(parent)

        # Global content
        self.name = name
        self.default = default
        if self.default == 'choose':
            self.edit = QComboBox(self)
        else:
            self.edit = QLineEdit(self.name, self)
            self.edit.setReadOnly(True)
        self.check_box = QCheckBox(self.name, self)

        # Event
        self.check_box.stateChanged.connect(self._change_state)

        # Layout
        layout = QHBoxLayout(self)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self.check_box)
        layout.addWidget(self.edit)
        self.edit.setEnabled(False)

        # Default
        if self.default == 'choose':
            pass
        else:
            self.edit.setText(default)

        # Object name
        self.edit.setObjectName('noti_edit')
        self.check_box.setObjectName('noti_check')
        self.exceptions = []

    @pyqtSlot()
    def _change_state(self):
        """
        Change enable state of the edit

        Arguments:
        None

        Returns:
        None
        """
        self.edit.setEnabled(self.check_box.isChecked())

    def add_exceptions(self, name):
        """
        Add a person to the exception list and dont send notification anymore.

        Arguments:
        name - Name of the person

        Returns:
        None
        """
        self.exceptions.append(name)

    def update_combo_email(self, users):
        """
        Update the combo boxes.

        Arguments:
        users - User dictionary

        Returns:
        None
        """
        if self.default == 'choose':
            items = [
                '@ {0}'.format(key) for key in users
                if '@ {0}'.format(key) not in self.exceptions
            ]
            self.edit.addItems(sorted(items))

    def update_combo_telegram(self, users):
        """
        Update the combo boxes.

        Arguments:
        users - User dictionary

        Returns:
        None
        """
        if self.default == 'choose':
            items = [
                'T {0}'.format(key) for key in users
                if 'T {0}'.format(key) not in self.exceptions
            ]
            self.edit.addItems(sorted(items))

    def clear_combo(self):
        """
        Remove all users from the combo box.

        Arguments:
        None

        Returns:
        None
        """
        if self.default == 'choose':
            self.edit.clear()

    def get_settings(self):
        """
        Get text of the currently selected combo item.

        Arguments:
        None

        Returns:
        Settings dictionary
        """
        settings = {}
        if self.default == 'choose':
            settings[self.name] = '{0}\t{1}'.format(self.edit.currentText(),
                                                    self.check_box.isChecked())
        else:
            settings[self.name] = '{0}\t{1}'.format(self.edit.text(),
                                                    self.check_box.isChecked())
        return settings

    def set_settings(self, name, state):
        """
        Set currently selected combo item in text.

        Arguments:
        name - Name of the person that should be currently selected.
        state - State of the person (True/False;Enables/Disables)

        Returns:
        None
        """
        self.check_box.setChecked(bool(state == 'True'))
        if self.default == 'choose':
            index = self.edit.findText(name)
            self.edit.setCurrentIndex(index)
        else:
            self.edit.setText(name)
예제 #22
0
파일: tt2.py 프로젝트: ThePsyjo/myTools
class TplRow(QWidget):
	def __init__(self, parent = None, _id = 0):
		super(TplRow, self).__init__(parent)
		self.id = _id
		self.setLayout(QHBoxLayout())
		self.idLabel = QLabel(self)
		self.beginEdit = QDateTimeEdit(self)
		self.beginEdit.setCalendarPopup(True) 
		self.endEdit = QDateTimeEdit(self)
		self.endEdit.setCalendarPopup(True)
		self.timeDiff = ClickLabel(self)
		self.descriptionEdit = QLineEdit(self)
		self.noteEdit = QLineEdit(self)
		self.delButton = QPushButton(self)
		self.delButton.setText('X')
		
		self.layout().addWidget(self.idLabel)
		self.layout().addWidget(self.beginEdit)
		self.layout().addWidget(self.endEdit)
		self.layout().addWidget(self.timeDiff)
		self.layout().addWidget(self.descriptionEdit)
		self.layout().addWidget(self.noteEdit)
		self.layout().addWidget(self.delButton)

		self.layout().setContentsMargins(2,2,2,2)
		
		self.connect(self.descriptionEdit, SIGNAL('editingFinished ()'), self.notify)
		self.connect(self.noteEdit, SIGNAL('editingFinished ()'), self.notify)
		self.connect(self.beginEdit, SIGNAL('editingFinished ()'), self.notify)
		self.connect(self.endEdit, SIGNAL('editingFinished ()'), self.notify)
		self.connect(self.delButton, SIGNAL('clicked()'), self.delete)
		self.connect(self.timeDiff, SIGNAL('clicked()'), self.onTimeDiff)

	def set(self, tpl):
		self.idLabel.setText(str(tpl[0]))
		self.beginEdit.setDateTime(QDateTime.fromTime_t(tpl[1]))
		self.endEdit.setDateTime(QDateTime.fromTime_t(tpl[2]))
		self.timeDiff.setText( self.mkDiff( tpl[1], tpl[2] ) )
		self.descriptionEdit.setText(str(tpl[3]))
		self.noteEdit.setText(str(tpl[4]))
	
	def get(self):
		tpl = []
		tpl.append(int(self.idLabel.text()))
		tpl.append(self.beginEdit.dateTime().toTime_t())
		tpl.append(self.endEdit.dateTime().toTime_t())
		tpl.append(self.descriptionEdit.text())
		tpl.append(self.noteEdit.text())
		return tpl
	
	def clear(self):
		self.beginEdit.clear()
		self.endEdit.clear()
		self.timeDiff.clear()
		self.descriptionEdit.clear()
		self.noteEdit.clear()
		self.idLabel.clear()

	def mkDiff(self, begin, end):
		return '%4d' % ceil( float( end - begin ) / 60 )

	@pyqtSlot()
	def onTimeDiff(self):
		self.parent().parent().parent().statusBar.showMessage( '%s copied to clipboard.' % self.timeDiff.text() )
		self.parent().clipboard.setText( str(self.timeDiff.text()).strip() )

	@pyqtSlot()
	def delete(self):
		if self.idLabel.text():
			if QMessageBox.question(self, 'delete ?', 'really delete id %s ?' % self.idLabel.text(), QMessageBox.Yes|QMessageBox.No, QMessageBox.No) == QMessageBox.Yes:
				self.emit(SIGNAL('del(int)'), self.id)

	@pyqtSlot()
	def notify(self):
		if self.idLabel.text():
			self.timeDiff.setText( self.mkDiff( self.beginEdit.dateTime().toTime_t(), self.endEdit.dateTime().toTime_t() ) )
			self.emit(SIGNAL('valueChanged(int)'), self.id)
class ImageTab(QWidget):
    def __init__(self, parent):
        super(ImageTab, self).__init__(parent)
        self.parent = parent
        self.name = 'Images'

        self.formats = config.image_formats
        self.extra_img = config.image_extra_formats

        validator = QRegExpValidator(QRegExp(r'^[1-9]\d*'), self)

        converttoQL = QLabel(self.tr('Convert to:'))
        self.extQCB = QComboBox()
        self.extQCB.addItems(self.formats)
        commandQL = QLabel(self.tr('Extra options:'))
        self.commandQLE = QLineEdit()

        hlayout2 = utils.add_to_layout('h', converttoQL, self.extQCB,
                                       commandQL, self.commandQLE)

        sizeQL = QLabel('<html><p align="center">' + self.tr('Image Size:') +
                        '</p></html>')
        self.widthQLE = utils.create_LineEdit((50, 16777215), validator, 4)
        self.heightQLE = utils.create_LineEdit((50, 16777215), validator, 4)
        label = QLabel('<html><p align="center">x</p></html>')
        label.setMaximumWidth(25)

        hlayout1 = utils.add_to_layout('h', self.widthQLE, label,
                                       self.heightQLE)
        sizelayout = utils.add_to_layout('v', sizeQL, hlayout1)

        self.imgaspectQChB = QCheckBox(self.tr("Maintain aspect ratio"))
        self.autocropQChB = QCheckBox(self.tr("Auto-crop"))

        vlayout = utils.add_to_layout('v', self.imgaspectQChB,
                                      self.autocropQChB)

        rotateQL = QLabel("<html><div align='center'>" + self.tr("Rotate") +
                          ":</div><br>(" + self.tr("degrees - clockwise") +
                          ")</html>")
        self.rotateQLE = utils.create_LineEdit((100, 16777215), validator, 3)
        self.vflipQChB = QCheckBox(self.tr('Vertical flip'))
        self.hflipQChB = QCheckBox(self.tr('Horizontal flip'))

        vlayout2 = utils.add_to_layout('v', self.vflipQChB, self.hflipQChB)
        hlayout3 = utils.add_to_layout('h', sizelayout, vlayout, rotateQL,
                                       self.rotateQLE, vlayout2, None)

        final_layout = utils.add_to_layout('v', hlayout2, hlayout3)
        self.setLayout(final_layout)

    def clear(self):
        """Clear self.widthQLE and self.heightQLE."""
        self.widthQLE.clear()
        self.heightQLE.clear()
        self.commandQLE.clear()
        self.rotateQLE.clear()
        self.imgaspectQChB.setChecked(False)
        self.autocropQChB.setChecked(False)
        self.vflipQChB.setChecked(False)
        self.hflipQChB.setChecked(False)

    def fill_extension_combobox(self, extraformats):
        extraformats = [i for i in extraformats.split("\n")
                        ] if extraformats else []
        self.extQCB.clear()
        self.extQCB.addItems(sorted(self.formats + extraformats))

    def ok_to_continue(self):
        """
        Check if everything is ok with imagetab to continue conversion.

        Check if:
        - ImageMagick is missing.
        - Either none or both size lineEdits are active at a time.

        Return True if all tests pass, else False.
        """
        width = self.widthQLE.text()
        height = self.heightQLE.text()

        if not self.parent.imagemagick:
            QMessageBox.warning(
                self, 'FF Multi Converter - ' + self.tr('Error!'),
                self.
                tr('ImageMagick is not installed.\nYou will '
                   'not be able to convert image files until you install it.'))
            return False
        if (width and not height) or (not width and height):
            QMessageBox.warning(self,
                                'FF Multi Converter - ' + self.tr('Error!'),
                                self.tr('The size LineEdit may not be empty.'))
            if width and not height:
                self.heightQLE.setFocus()
            else:
                self.widthQLE.setFocus()
            return False
        return True

    def set_default_command(self):
        """Set the default value to self.commandQLE."""
        self.clear()
        self.commandQLE.setText(self.parent.default_command_image)
예제 #24
0
class ShowPresets(QDialog):
    def __init__(self, parent=None):
        super(ShowPresets, self).__init__(parent)
        self.original_presets_file = '/usr/share/ffmulticonverter/presets.xml'
        self.config_folder = os.getenv('HOME') + '/.config/ffmulticonverter/'
        self.current_presets_file = self.config_folder + 'presets.xml'

        self.presListWidget = QListWidget()
        labelLabel = QLabel(self.tr('Preset label'))
        self.labelLineEdit = QLineEdit()
        self.labelLineEdit.setReadOnly(True)
        commandLabel = QLabel(self.tr('Preset command line parameters'))
        self.commandLineEdit = QLineEdit()
        self.commandLineEdit.setReadOnly(True)
        extLabel = QLabel(self.tr('Output file extension'))
        self.extLineEdit = QLineEdit()
        self.extLineEdit.setReadOnly(True)
        addButton = QPushButton(self.tr('Add'))
        self.deleteButton = QPushButton(self.tr('Delete'))
        self.delete_allButton = QPushButton(self.tr('Delete all'))
        self.editButton = QPushButton(self.tr('Edit'))
        okButton = QPushButton(self.tr('OK'))
        okButton.setDefault(True)

        spc1 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
        spc2 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)

        grid = pyqttools.add_to_grid(QGridLayout(),
                          [self.delete_allButton, addButton, spc1, None],
                          [self.deleteButton, self.editButton, spc2, okButton])

        final_layout = pyqttools.add_to_layout(QVBoxLayout(),
                                               self.presListWidget, labelLabel,
                                               self.labelLineEdit, commandLabel,
                                               self.commandLineEdit, extLabel,
                                               self.extLineEdit, grid)

        self.setLayout(final_layout)

        okButton.clicked.connect(self.accept)
        self.presListWidget.currentRowChanged.connect(self.show_preset)
        addButton.clicked.connect(self.add_preset)
        self.deleteButton.clicked.connect(self.delete_preset)
        self.delete_allButton.clicked.connect(self.delete_all_presets)
        self.editButton.clicked.connect(self.edit_preset)

        self.resize(410, 410)
        self.setWindowTitle(self.tr('Edit Presets'))

        QTimer.singleShot(0, self.load_xml)
        QTimer.singleShot(0, self.fill_presListWidget)

    def load_xml(self):
        """Load xml tree and set xml root."""
        try:
            self.tree = etree.parse(self.current_presets_file)
        except (etree.ParseError, IOError):
            try:
                self.tree = etree.parse(self.original_presets_file)
            except IOError:
                # when program is not installed
                self.tree = etree.parse('../share/presets.xml')
            if not os.path.exists(self.config_folder):
                os.makedirs(self.config_folder)
        self.root = self.tree.getroot()

    def set_buttons_clear_lineEdits(self):
        """Enable or disable button's and clear lineEdits."""
        enable = bool(self.presListWidget)
        self.editButton.setEnabled(enable)
        self.deleteButton.setEnabled(enable)
        self.delete_allButton.setEnabled(enable)
        if not enable:
            self.labelLineEdit.clear()
            self.commandLineEdit.clear()
            self.extLineEdit.clear()

    def fill_presListWidget(self):
        """Clear self.presListWidget and to it presets' tags."""
        self.presListWidget.clear()
        for i in sorted([y.tag for y in self.root]):
            elem = self.root.find(i)
            self.presListWidget.addItem(MyListItem(i, elem))
            self.presListWidget.setCurrentRow(0)
        self.set_buttons_clear_lineEdits()

    def show_preset(self):
        """Fill LineEdits with current xml element's values."""
        try:
            xml_elem = self.presListWidget.currentItem().xml_element
        except AttributeError:
            return

        self.labelLineEdit.setText(xml_elem[0].text)
        self.commandLineEdit.setText(xml_elem[1].text)
        self.commandLineEdit.home(False)
        self.extLineEdit.setText(xml_elem[2].text)

    def add_preset(self):
        """Open AddorEditPreset() dialog and add a preset xml root."""
        dialog = AddorEditPreset(None, False, self)
        if dialog.exec_():
            element = etree.Element(dialog.name_text)
            label = etree.Element('label')
            label.text = dialog.label_text
            command = etree.Element('params')
            command.text = dialog.command_text
            ext = etree.Element('extension')
            ext.text = dialog.ext_text
            category = etree.Element('category')
            category.text = 'Scattered'

            for num, elem in enumerate([label, command, ext, category]):
                element.insert(num, elem)
            index = sorted([i.tag for i in self.root] + [dialog.name_text])\
                    .index(dialog.name_text)
            self.root.insert(index, element)
            self.save_tree()
            self.fill_presListWidget()

    def delete_preset(self):
        """
        Ask user wether he wants to delete the selected preset.
        If so, delete the preset from xml root.
        """
        try:
            xml_elem = self.presListWidget.currentItem().xml_element
        except AttributeError:
            return

        reply = QMessageBox.question(self, 'FF Multi Converter - ' + self.tr(
            'Delete Preset'), self.tr('Are you sure that you want to delete '
            'the %1 preset?').arg(xml_elem.tag),
            QMessageBox.Yes|QMessageBox.Cancel)
        if reply == QMessageBox.Yes:
            self.root.remove(xml_elem)
            self.save_tree()
            self.fill_presListWidget()

    def delete_all_presets(self):
        """
        Ask user if he wants to delete all presets.
        If so, clear xml root.
        """
        reply = QMessageBox.question(self, 'FF Multi Converter - ' + self.tr(
            'Delete Preset'), self.tr('Are you sure that you want to delete '
            'all presets?'), QMessageBox.Yes|QMessageBox.Cancel)
        if reply == QMessageBox.Yes:
            self.root.clear()
            self.save_tree()
            self.fill_presListWidget()

    def edit_preset(self):
        """Call the AddorEditPreset() dialog and update xml element's values."""
        elem = self.presListWidget.currentItem().xml_element
        dialog = AddorEditPreset(elem, True)

        if dialog.exec_():
            elem.tag = dialog.name_text
            elem[0].text = dialog.label_text
            elem[1].text = dialog.command_text
            elem[2].text = dialog.ext_text
            self.save_tree()
            self.fill_presListWidget()

    def save_tree(self):
        """Save xml tree."""
        with open(self.current_presets_file, 'w') as _file:
            try:
                etree.ElementTree(self.root).write(_file)
            except:
                pass

    def import_presets(self):
        """Import an xml tree."""
        title = 'FF Multi Converter - Import'
        reply = QMessageBox.question(self, title, self.tr('All current '
                'presets will be deleted.\nAre you sure that you want to '
                'continue?'), QMessageBox.Yes|QMessageBox.Cancel)
        if reply == QMessageBox.Yes:
            fname = QFileDialog.getOpenFileName(self, title)
            if fname:
                msg = 'Succesful import!'
                try:
                    self.tree = etree.parse(fname)
                except:
                    msg = 'Import failed!'
                else:
                    self.root = self.tree.getroot()
                    self.save_tree()
                QMessageBox.information(self, title, msg)

    def export_presets(self):
        """Export the xml tree."""
        fname = QFileDialog.getSaveFileName(self,
                                  'FF Multi Converter - Export presets','.xml')
        if fname:
            self.load_xml()
            with open(fname, 'w') as _file:
                try:
                    etree.ElementTree(self.root).write(_file)
                except:
                    pass

    def reset(self):
        """Import the default xml tree."""
        reply = QMessageBox.question(self, 'FF Multi Converter - ' + self.tr(
            'Delete Preset'), self.tr('Are you sure that you want to restore '
            'the default presets?'), QMessageBox.Yes|QMessageBox.Cancel)
        if reply == QMessageBox.Yes:
            if os.path.exists(self.current_presets_file):
                os.remove(self.current_presets_file)

    def accept(self):
        """
        Save current xml element's values in order to be used from
        main program and close (accept) dialog.
        """
        self.the_command = None
        if self.presListWidget:
            self.the_command = self.presListWidget.currentItem()\
                               .xml_element[1].text
            self.the_extension = self.presListWidget.currentItem()\
                                 .xml_element[2].text
        QDialog.accept(self)
예제 #25
0
class ExportCSVDialog(QDialog):
    def __init__(self, parent, nodes, selectedAttributes):  #current column
        QDialog.__init__(self, parent)
        self.nodes = nodes
        self.exportPath = os.path.join(os.path.expanduser("~"), "dff.csv")
        self.attributes = selectedAttributes
        self.split = False

        self.dialogLayout = QVBoxLayout()
        self.setLayout(self.dialogLayout)
        self.setPathEdit()
        self.setAttributesSelection()
        self.setSplitCheckBox()
        self.setButtons()

    def setButtons(self):
        self.dialogButtonsLayout = QHBoxLayout()
        self.dialogButtonsBox = QDialogButtonBox()
        self.dialogButtonsBox.setStandardButtons(QDialogButtonBox.Ok
                                                 | QDialogButtonBox.Cancel)
        self.connect(self.dialogButtonsBox, SIGNAL("accepted()"), self.accept)
        self.connect(self.dialogButtonsBox, SIGNAL("rejected()"), self.reject)
        self.dialogButtonsLayout.addWidget(self.dialogButtonsBox)
        self.dialogLayout.addLayout(self.dialogButtonsLayout)

    def setSplitCheckBox(self):
        self.splitCheckBox = QCheckBox("Split file every 65536 lines")
        self.connect(self.splitCheckBox, SIGNAL("stateChanged(int)"),
                     self.setSplit)
        self.dialogLayout.addWidget(self.splitCheckBox)

    def setSplit(self, state):
        if state:
            self.split = True
        else:
            self.split = False

    def setAttributesSelection(self):
        self.attributesSelectionLayout = QHBoxLayout()
        self.attributesSelectionLabel = QLabel(self.tr("Choose CSV column :"))
        attributesSelectionButton = QPushButton("...")
        self.attributesSelectionLayout.addWidget(self.attributesSelectionLabel)
        self.attributesSelectionLayout.addWidget(attributesSelectionButton)
        self.dialogLayout.addLayout(self.attributesSelectionLayout)
        self.connect(attributesSelectionButton, SIGNAL("clicked()"),
                     self.askColumn)

    def askColumn(self):
        #if timeline node
        selectAttributesWizard = SelectAttributesWizard(
            self.parent().model(), self.attributes,
            self.parent().model().defaultAttributes()
        )  # need model by default for list check and defalt atributs, 'current selected file as steel a meaning' rather always parse list ? , use attribute selector ?
        if selectAttributesWizard.exec_(
        ) == 1:  #get choosen attribtes iand set to list
            #    if iret == 1:
            self.attributes = selectAttributesWizard.getSelectedAttributes()

    def setPathEdit(self):
        self.exportPathLayout = QHBoxLayout()
        self.exportPathLabel = QLabel(self.tr("Path of csv file:"))
        self.exportPathLineEdit = QLineEdit(self.exportPath)
        self.exportPathLineEdit.setReadOnly(True)
        exportPathButton = QPushButton("...")

        self.exportPathLayout.addWidget(self.exportPathLabel)
        self.exportPathLayout.addWidget(self.exportPathLineEdit)
        self.exportPathLayout.addWidget(exportPathButton)
        self.dialogLayout.addLayout(self.exportPathLayout)
        self.connect(exportPathButton, SIGNAL("clicked()"), self.askExportPath)

    def askExportPath(self):
        newPath = QFileDialog().getSaveFileName(self, self.tr("CSV path"),
                                                self.exportPath)
        if len(newPath):
            self.exportPath = unicode(newPath.toUtf8(), 'utf-8')
            self.exportPathLineEdit.clear()
            self.exportPathLineEdit.insert(self.exportPath)

    def accept(self):
        #XXX thread me
        self.exportCSV()
        QDialog.accept(self)
        #show advancement in widget (next)

    def exportCSV(self):
        try:
            csv = CSV()
            ##if not self.timeLineButton.isChecked():
            csv.exportNodes(self.exportPath, self.nodes, self.attributes,
                            self.split)
        except Exception as e:
            msg = QMessageBox(self)
            msg.setWindowTitle(self.tr("Export to CSV error"))
            msg.setText(self.tr("An issue occured while exporting to CSV"))
            msg.setIcon(QMessageBox.Warning)
            msg.setDetailedText(str(e))
            msg.setStandardButtons(QMessageBox.Ok)
            ret = msg.exec_()
예제 #26
0
class PasswordEnter(QDialog):
	def __init__(self, title = '', parent = None, mode = 1):
		QDialog.__init__(self, parent)
		self.prnt = parent
		self.mode = mode
		self.tr = self.prnt.tr
		self.Sound = self.prnt.Parent.sound
		self.Keyring = self.prnt.Keyring
		self.title = QLabel(self.tr._translate(title))
		self.title.setAlignment(Qt.AlignHCenter)
		self.passwrd = QLineEdit()
		self.passwrd.setMaxLength(BLOCK_SIZE)
		self.passwrd.setPlaceholderText(self.tr._translate("Enter Password"))
		self.passwrd.setEchoMode(QLineEdit.Password)
		self.passwrd.setToolTip(self.tr._translate("Enter Password"))
		if self.mode :
			self.confirm = QLineEdit()
			self.confirm.setMaxLength(BLOCK_SIZE)
			self.confirm.setPlaceholderText(self.tr._translate("Confirm Password"))
			self.confirm.setEchoMode(QLineEdit.Password)
			self.confirm.setToolTip(self.tr._translate("Confirm it"))

		self._layout = QVBoxLayout()
		self._layout.addWidget(self.title)
		self._layout.addWidget(self.passwrd)
		if self.mode :
			self._layout.addWidget(self.confirm)
		self.ok = QPushButton(QIcon.fromTheme("dialog-ok"), "", self)
		self.cancel = QPushButton(QIcon.fromTheme("dialog-cancel"), "", self)
		self.buttonLayout = QHBoxLayout()
		self.buttonLayout.addWidget(self.ok)
		self.buttonLayout.addWidget(self.cancel)
		self._layout.addItem(self.buttonLayout)
		self.setLayout(self._layout)
		if self.mode :
			self.ok.clicked.connect(self.checkCorrectOfPassword)
		else :
			self.ok.clicked.connect(self.returnPassword)
		self.cancel.clicked.connect(self.clearEnterFields)
		QTimer.singleShot(100, self.moveToTrayIcon)

	def moveToTrayIcon(self):
		self.move(self.prnt.Parent.mapToGlobal(self.prnt.Parent.trayIconMenu.pos()))

	def checkCorrectOfPassword(self):
		if self.confirm.text() == self.passwrd.text() and \
				not self.confirm.text().isEmpty() :
			self.Keyring.create_Keyring(self.passwrd.text())
			self.Sound.Complete.play()
			QMessageBox.information(self, \
					self.tr._translate("Create Keyring"), \
					self.tr._translate("Keyring created."), \
					1)
			self.clearEnterFields()
			self.prnt.saveData()
			self.close()
		else :
			self.Sound.Attention.play()
			QMessageBox.information(self, \
					self.tr._translate("Create Keyring"), \
					self.tr._translate("Passwords mismatch or empty"), \
					1)
			self.clearEnterFields()

	def clearEnterFields(self):
		self.passwrd.clear()
		if self.mode :
			self.confirm.clear()

	def returnPassword(self):
		if not self.passwrd.text().isEmpty() :
			self.prnt.Keyring.password = to_unicode(self.passwrd.text())
			self.clearEnterFields()
			self.close()
		else :
			self.Sound.Attention.play()
			QMessageBox.information(self, \
					self.tr._translate("Enter Password"), \
					self.tr._translate("Passwords empty"), \
					1)

	def closeEvent(self, ev):
		ev.ignore()
		if not self.prnt.Parent.isVisible() :
			self.prnt.Parent.show()
			self.prnt.Parent.autoHide(3)
		if self.prnt.Parent.isMinimized() :
			self.prnt.Parent.showNormal()
		self.done(0)
예제 #27
0
class GroupsModify(PyDialog):
    """
    +--------------------------+
    |     Groups : Modify      |
    +--------------------------+
    |                          |
    |  Name        xxx Default |
    |  Coords      xxx Default |
    |  Elements    xxx Default |
    |  Color       xxx Default |
    |  Add         xxx Add     |
    |  Remove      xxx Remove  |
    |                          |
    |      Set  OK Cancel      |
    +--------------------------+
    """
    def __init__(self, data, win_parent=None, group_active='main'):
        self.win_parent = win_parent
        PyDialog.__init__(self, data, win_parent)
        #QDialog.__init__(self, win_parent)

        #self.win_parent = win_parent
        #self.out_data = data

        #print(data)
        self.keys = [group.name for key, group in sorted(iteritems(data))]
        self.active_key = self.keys.index(group_active)

        group_obj = data[self.active_key]
        name = group_obj.name

        self.imain = 0
        self.nrows = len(self.keys)

        self._default_name = group_obj.name
        self._default_elements = group_obj.element_str
        self.elements_pound = group_obj.elements_pound

        self.table = QListWidget(parent=None)
        self.table.clear()
        self.table.addItems(self.keys)

        # table
        self.setWindowTitle('Groups: Modify')
        self.create_widgets()
        self.create_layout()
        self.set_connections()

        self.on_set_as_main()
        #self.show()

    def create_widgets(self):
        # Name
        self.name = QLabel("Name:")
        self.name_set = QPushButton("Set")
        self.name_edit = QLineEdit(str(self._default_name).strip())
        self.name_button = QPushButton("Default")

        # elements
        self.elements = QLabel("Element IDs:")
        self.elements_edit = QLineEdit(str(self._default_elements).strip())
        self.elements_button = QPushButton("Default")

        # add
        self.add = QLabel("Add:")
        self.add_edit = QLineEdit(str(''))
        self.add_button = QPushButton("Add")

        # remove
        self.remove = QLabel("Remove:")
        self.remove_edit = QLineEdit(str(''))
        self.remove_button = QPushButton("Remove")

        # applies a unique implicitly
        self.eids = parse_patran_syntax(str(self._default_elements),
                                        pound=self.elements_pound)

        # closing
        #self.apply_button = QPushButton("Apply")
        self.ok_button = QPushButton("Close")
        #self.cancel_button = QPushButton("Cancel")

        self.set_as_main_button = QPushButton("Set As Main")
        self.create_group_button = QPushButton('Create New Group')
        self.delete_group_button = QPushButton('Delete Group')

        self.name.setEnabled(False)
        self.name_set.setEnabled(False)
        self.name_edit.setEnabled(False)
        self.name_button.setEnabled(False)
        self.elements.setEnabled(False)
        self.elements_button.setEnabled(False)
        self.elements_edit.setEnabled(False)
        self.add.setEnabled(False)
        self.add_button.setEnabled(False)
        self.add_edit.setEnabled(False)
        self.remove.setEnabled(False)
        self.remove_button.setEnabled(False)
        self.remove_edit.setEnabled(False)
        self.delete_group_button.setEnabled(False)
        #self.apply_button.setEnabled(False)
        #self.ok_button.setEnabled(False)

    def create_layout(self):
        grid = QGridLayout()
        grid.addWidget(self.name, 0, 0)
        grid.addWidget(self.name_edit, 0, 1)
        grid.addWidget(self.name_set, 0, 2)
        grid.addWidget(self.name_button, 0, 3)

        grid.addWidget(self.elements, 2, 0)
        grid.addWidget(self.elements_edit, 2, 1)
        grid.addWidget(self.elements_button, 2, 2)

        grid.addWidget(self.add, 4, 0)
        grid.addWidget(self.add_edit, 4, 1)
        grid.addWidget(self.add_button, 4, 2)

        grid.addWidget(self.remove, 5, 0)
        grid.addWidget(self.remove_edit, 5, 1)
        grid.addWidget(self.remove_button, 5, 2)

        ok_cancel_box = QHBoxLayout()
        #ok_cancel_box.addWidget(self.apply_button)
        ok_cancel_box.addWidget(self.ok_button)
        #ok_cancel_box.addWidget(self.cancel_button)

        main_create_delete = QHBoxLayout()
        main_create_delete.addWidget(self.set_as_main_button)
        main_create_delete.addWidget(self.create_group_button)
        main_create_delete.addWidget(self.delete_group_button)

        vbox = QVBoxLayout()
        vbox.addWidget(self.table)
        vbox.addLayout(grid)
        vbox.addLayout(main_create_delete)
        vbox.addStretch()
        vbox.addLayout(ok_cancel_box)
        self.setLayout(vbox)

    def on_set_name(self):
        name = str(self.name_edit.text()).strip()
        if name not in self.keys:
            self.name_edit.setStyleSheet("QLineEdit{background: white;}")
            group = self.out_data[self.active_key]
            group.name = name
            self.keys[self.active_key] = name
            self.recreate_table()
        elif name != self.keys[self.active_key]:
            self.name_edit.setStyleSheet("QLineEdit{background: red;}")
        elif name == self.keys[self.active_key]:
            self.name_edit.setStyleSheet("QLineEdit{background: white;}")

    def set_connections(self):
        self.name_set.clicked.connect(self.on_set_name)
        self.name_button.clicked.connect(self.on_default_name)
        self.elements_button.clicked.connect(self.on_default_elements)

        self.add_button.clicked.connect(self.on_add)
        self.remove_button.clicked.connect(self.on_remove)
        self.table.itemClicked.connect(self.on_update_active_key)
        self.ok_button.clicked.connect(self.on_ok)

        self.set_as_main_button.clicked.connect(self.on_set_as_main)
        self.create_group_button.clicked.connect(self.on_create_group)
        self.delete_group_button.clicked.connect(self.on_delete_group)

    def on_create_group(self):
        irow = self.nrows
        new_key = 'Group %s' % irow
        while new_key in self.keys:
            irow += 1
            new_key = 'Group %s' % irow
        irow = self.nrows

        self.keys.append(new_key)
        group = Group(new_key,
                      element_str='',
                      elements_pound=self.elements_pound,
                      editable=True)
        self.out_data[irow] = group

        self.table.reset()
        self.table.addItems(self.keys)
        self.nrows += 1

        #----------------------------------
        # update internal parameters
        #self.out_data = items
        if self.imain > self.active_key:
            self.imain += 1

        #make the new group the default
        self.active_key = self.nrows - 1

        self.keys = [
            group.name for key, group in sorted(iteritems(self.out_data))
        ]
        self.recreate_table()

    def recreate_table(self):
        # update gui
        self.table.clear()
        self.table.addItems(self.keys)
        item = self.table.item(self.imain)

        bold = QtGui.QFont()
        bold.setBold(True)
        bold.setItalic(True)
        item.setFont(bold)
        self.table.update()

        # update key
        name = self.keys[self.active_key]
        self._update_active_key_by_name(name)

    def on_delete_group(self):
        if self.active_key == 0:
            return

        #self.deleted_groups.add(self.imain)
        items = {}
        j = 0
        for i, key in sorted(iteritems(self.out_data)):
            if i != self.active_key:
                items[j] = key
                j += 1

        # update internal parameters
        self.out_data = items
        if self.imain >= self.active_key:
            self.imain = max(0, self.imain - 1)
        self.active_key = max(0, self.active_key - 1)
        self.nrows -= 1
        self.keys = [group.name for key, group in sorted(iteritems(items))]

        self.recreate_table()

        # update key
        name = self.keys[self.active_key]
        self._update_active_key_by_name(name)

    def on_set_as_main(self):
        bold = QtGui.QFont()
        bold.setBold(True)
        bold.setItalic(True)

        normal = QtGui.QFont()
        normal.setBold(False)
        normal.setItalic(False)

        obj = self.table.item(self.imain)
        obj.setFont(normal)

        self.imain = self.active_key
        obj = self.table.item(self.imain)
        obj.setFont(bold)
        group = self.out_data[self.imain]
        self._default_elements = group.element_str
        self._default_name = group.name
        if self.win_parent is not None:
            # we're not testing the menu
            self.win_parent.post_group(group)

    def closeEvent(self, event):
        self.out_data['close'] = True
        event.accept()

    def on_add(self):
        eids, is_valid = self.check_patran_syntax(self.add_edit,
                                                  pound=self.elements_pound)
        #adict, is_valid = self.check_patran_syntax_dict(self.add_edit)
        if not is_valid:
            #self.add_edit.setStyleSheet("QLineEdit{background: red;}")
            return

        self.eids = unique(hstack([self.eids, eids]))
        #self.eids = _add(adict, ['e', 'elem', 'element'], self.eids)
        #self.cids = _add(adict, ['c', 'cid', 'coord'], self.cids)
        self._apply_cids_eids()

        self.add_edit.clear()
        self.add_edit.setStyleSheet("QLineEdit{background: white;}")

    def _apply_cids_eids(self):
        #ctext = _get_collapsed_text(self.cids)
        etext = _get_collapsed_text(self.eids)

        #self.coords_edit.setText(str(ctext.lstrip()))
        self.elements_edit.setText(str(etext.lstrip()))
        self.out_data[self.active_key].element_ids = self.eids

    def on_remove(self):
        eids, is_valid = self.check_patran_syntax(self.remove_edit)
        #adict, is_valid = self.check_patran_syntax_dict(self.remove_edit)
        if not is_valid:
            #self.remove_edit.setStyleSheet("QLineEdit{background: red;}")
            return

        #self.eids = _remove(adict, ['e', 'elem', 'element'], self.eids)
        #self.cids = _remove(adict, ['c', 'cid', 'coord'], self.cids)
        self.eids = setdiff1d(self.eids, eids)
        self._apply_cids_eids()

        self.remove_edit.clear()
        self.remove_edit.setStyleSheet("QLineEdit{background: white;}")

    def on_default_name(self):
        name = str(self._default_name)
        self.name_edit.setText(name)
        self.name_edit.setStyleSheet("QLineEdit{background: white;}")

    def on_default_elements(self):
        element_str = str(self._default_elements)
        self.elements_edit.setText(element_str)
        self.elements_edit.setStyleSheet("QLineEdit{background: white;}")
        group = self.out_data[self.active_key]
        group.element_str = element_str

    @staticmethod
    def check_name(cell):
        text = str(cell.text()).strip()
        if len(text):
            cell.setStyleSheet("QLineEdit{background: white;}")
            return text, True
        else:
            cell.setStyleSheet("QLineEdit{background: red;}")
            return None, False

        if self._default_name != text:
            if self._default_name in self.out_data:
                cell.setStyleSheet("QLineEdit{background: white;}")
                return text, True
            else:
                cell.setStyleSheet("QLineEdit{background: red;}")
                return None, False

    def on_validate(self):
        name, flag0 = self.check_name(self.name_edit)
        elements, flag1 = self.check_patran_syntax(self.elements_edit,
                                                   pound=self.elements_pound)
        #coords_value, flag2 = self.check_patran_syntax(self.coords_edit,
        #pound=self.coords_pound)

        if flag0 and flag1:
            self._default_name = name
            self._default_elements = self.eids
            self.out_data['clicked_ok'] = True
            self.out_data['close'] = True
            return True
        return False

    def on_apply(self, force=False):
        passed = self.on_validate()
        if passed or force:
            self.win_parent.on_modify_group(self.out_data)

    def on_ok(self):
        passed = self.on_validate()
        if passed:
            self.out_data['close'] = True
            self.out_data['clicked_ok'] = True
            self.out_data['clicked_cancel'] = False
            self.close()
            #self.destroy()

    def on_cancel(self):
        self.out_data['close'] = True
        self.out_data['clicked_cancel'] = True
        self.close()

    def on_update_active_key(self, index):
        self.update_active_key(index)
        #str(index.text())

    def update_active_key(self, index):
        #old_obj = self.out_data[self.imain]
        name = str(index.text())
        self._update_active_key_by_name(name)

    def _update_active_key_by_name(self, name):
        if name in self.keys:
            self.active_key = self.keys.index(name)
        else:
            # we (hopefully) just removed a row
            #self.active_key = self.keys[self.active_key]
            pass

        self.name_edit.setText(name)
        obj = self.out_data[self.active_key]

        self.eids = parse_patran_syntax(obj.element_str,
                                        pound=obj.elements_pound)
        self._default_elements = obj.element_str
        self._default_name = name
        self._apply_cids_eids()

        self.set_as_main_button.setEnabled(True)
        if name in ['main', 'anti-main']:
            self.name.setEnabled(False)
            self.name_set.setEnabled(False)
            self.name_edit.setEnabled(False)
            self.name_button.setEnabled(False)
            self.elements.setEnabled(False)
            self.elements_button.setEnabled(False)
            self.elements_edit.setEnabled(False)
            self.add.setEnabled(False)
            self.add_button.setEnabled(False)
            self.add_edit.setEnabled(False)
            self.remove.setEnabled(False)
            self.remove_button.setEnabled(False)
            self.remove_edit.setEnabled(False)
            self.delete_group_button.setEnabled(False)
            if name == 'anti-main':
                self.set_as_main_button.setEnabled(False)
            #self.apply_button.setEnabled(False)
            #self.ok_button.setEnabled(False)
        else:
            self.name.setEnabled(True)
            self.name_set.setEnabled(True)
            self.name_edit.setEnabled(True)
            self.name_button.setEnabled(True)
            self.elements.setEnabled(True)
            self.elements_button.setEnabled(True)

            self.add.setEnabled(True)
            self.add_button.setEnabled(True)
            self.add_edit.setEnabled(True)
            self.remove.setEnabled(True)
            self.remove_button.setEnabled(True)
            self.remove_edit.setEnabled(True)
            self.delete_group_button.setEnabled(True)
예제 #28
0
class ShowPresets(QDialog):
    def __init__(self, parent=None):
        super(ShowPresets, self).__init__(parent)
        self.original_presets_file = '/usr/share/ffmulticonverter/presets.xml'
        self.config_folder = os.getenv('HOME') + '/.config/ffmulticonverter/'
        self.current_presets_file = self.config_folder + 'presets.xml'

        self.presListWidget = QListWidget()
        labelLabel = QLabel(self.tr('Preset label'))
        self.labelLineEdit = QLineEdit()
        self.labelLineEdit.setReadOnly(True)
        commandLabel = QLabel(self.tr('Preset command line parameters'))
        self.commandLineEdit = QLineEdit()
        self.commandLineEdit.setReadOnly(True)
        extLabel = QLabel(self.tr('Output file extension'))
        self.extLineEdit = QLineEdit()
        self.extLineEdit.setReadOnly(True)
        addButton = QPushButton(self.tr('Add'))
        self.deleteButton = QPushButton(self.tr('Delete'))
        self.delete_allButton = QPushButton(self.tr('Delete all'))
        self.editButton = QPushButton(self.tr('Edit'))
        searchLabel = QLabel(self.tr('Search'))
        self.searchLineEdit = QLineEdit()
        okButton = QPushButton(self.tr('OK'))
        okButton.setDefault(True)

        spc1 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
        spc2 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
        spc3 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)

        grid = pyqttools.add_to_grid(
            QGridLayout(), [self.delete_allButton, addButton, spc1],
            [self.deleteButton, self.editButton, spc2])

        hlayout = pyqttools.add_to_layout(QHBoxLayout(), searchLabel,
                                          self.searchLineEdit, None, okButton)

        final_layout = pyqttools.add_to_layout(
            QVBoxLayout(), self.presListWidget, labelLabel, self.labelLineEdit,
            commandLabel, self.commandLineEdit, extLabel, self.extLineEdit,
            grid, spc3, hlayout)

        self.setLayout(final_layout)

        okButton.clicked.connect(self.accept)
        self.presListWidget.currentRowChanged.connect(self.show_preset)
        addButton.clicked.connect(self.add_preset)
        self.deleteButton.clicked.connect(self.delete_preset)
        self.delete_allButton.clicked.connect(self.delete_all_presets)
        self.editButton.clicked.connect(self.edit_preset)
        self.searchLineEdit.textEdited.connect(self.search)

        del_shortcut = QShortcut(self)
        del_shortcut.setKey(Qt.Key_Delete)
        del_shortcut.activated.connect(self.delete_preset)

        self.resize(430, 480)
        self.setWindowTitle(self.tr('Edit Presets'))

        QTimer.singleShot(0, self.load_xml)
        QTimer.singleShot(0, self.fill_presListWidget)

    def load_xml(self):
        """Load xml tree and set xml root."""
        try:
            self.tree = etree.parse(self.current_presets_file)
        except (etree.ParseError, IOError):
            try:
                self.tree = etree.parse(self.original_presets_file)
            except IOError:
                # when program is not installed
                self.tree = etree.parse('../share/presets.xml')
            if not os.path.exists(self.config_folder):
                os.makedirs(self.config_folder)
        self.root = self.tree.getroot()

    def set_buttons_clear_lineEdits(self):
        """Enable or disable button's and clear lineEdits."""
        enable = bool(self.presListWidget)
        self.editButton.setEnabled(enable)
        self.deleteButton.setEnabled(enable)
        self.delete_allButton.setEnabled(enable)
        if not enable:
            self.labelLineEdit.clear()
            self.commandLineEdit.clear()
            self.extLineEdit.clear()

    def fill_presListWidget(self):
        """Clear self.presListWidget and to it presets' tags."""
        self.presListWidget.clear()
        for i in sorted([y.tag for y in self.root]):
            elem = self.root.find(i)
            self.presListWidget.addItem(MyListItem(i, elem))

        self.presListWidget.setCurrentRow(0)
        self.set_buttons_clear_lineEdits()
        self.searchLineEdit.clear()

    def show_preset(self):
        """Fill LineEdits with current xml element's values."""
        try:
            xml_elem = self.presListWidget.currentItem().xml_element
        except AttributeError:
            return

        self.labelLineEdit.setText(xml_elem[0].text)
        self.commandLineEdit.setText(xml_elem[1].text)
        self.commandLineEdit.home(False)
        self.extLineEdit.setText(xml_elem[2].text)

    def add_preset(self):
        """Open AddorEditPreset() dialog and add a preset xml root."""
        dialog = AddorEditPreset(None, False, self)
        if dialog.exec_():
            element = etree.Element(dialog.name_text)
            label = etree.Element('label')
            label.text = dialog.label_text
            command = etree.Element('params')
            command.text = dialog.command_text
            ext = etree.Element('extension')
            ext.text = dialog.ext_text
            category = etree.Element('category')
            category.text = 'Scattered'

            for num, elem in enumerate([label, command, ext, category]):
                element.insert(num, elem)
            index = sorted([i.tag for i in self.root] + [dialog.name_text])\
                    .index(dialog.name_text)
            self.root.insert(index, element)
            self.save_tree()
            self.fill_presListWidget()

    def delete_preset(self):
        """
        Ask user wether he wants to delete the selected preset.
        If so, delete the preset from xml root.
        """
        try:
            xml_elem = self.presListWidget.currentItem().xml_element
        except AttributeError:
            return

        reply = QMessageBox.question(
            self, 'FF Multi Converter - ' + self.tr('Delete Preset'),
            self.tr('Are you sure that you want to delete '
                    'the %1 preset?').arg(xml_elem.tag),
            QMessageBox.Yes | QMessageBox.Cancel)
        if reply == QMessageBox.Yes:
            self.root.remove(xml_elem)
            self.save_tree()
            self.fill_presListWidget()

    def delete_all_presets(self):
        """
        Ask user if he wants to delete all presets.
        If so, clear xml root.
        """
        reply = QMessageBox.question(
            self, 'FF Multi Converter - ' + self.tr('Delete Preset'),
            self.tr('Are you sure that you want to delete '
                    'all presets?'), QMessageBox.Yes | QMessageBox.Cancel)
        if reply == QMessageBox.Yes:
            self.root.clear()
            self.save_tree()
            self.fill_presListWidget()

    def edit_preset(self):
        """Call the AddorEditPreset() dialog and update xml element's values."""
        elem = self.presListWidget.currentItem().xml_element
        dialog = AddorEditPreset(elem, True)

        if dialog.exec_():
            elem.tag = dialog.name_text
            elem[0].text = dialog.label_text
            elem[1].text = dialog.command_text
            elem[2].text = dialog.ext_text
            self.save_tree()
            self.fill_presListWidget()

    def search(self):
        """
        Search for keywords in presets data.

        Show a preset only if its tag, label or extension matches any of
        search string's tokens.
        """
        txt = str(self.searchLineEdit.text()).strip().lower()
        if not txt:
            self.fill_presListWidget()
            return

        self.presListWidget.clear()
        for i in txt.split(' '):
            for p in sorted([y.tag for y in self.root]):
                elem = self.root.find(p)
                if (i.strip() and
                    (i in elem.tag.lower() or i in elem[0].text.lower()
                     or i in elem[2].text.lower())):
                    self.presListWidget.addItem(MyListItem(p, elem))

        self.presListWidget.setCurrentRow(0)
        self.set_buttons_clear_lineEdits()

    def save_tree(self):
        """Save xml tree."""
        with open(self.current_presets_file, 'w') as _file:
            try:
                etree.ElementTree(self.root).write(_file)
            except:
                pass

    def import_presets(self):
        """Import an xml tree."""
        title = 'FF Multi Converter - Import'
        reply = QMessageBox.question(
            self, title,
            self.tr('All current '
                    'presets will be deleted.\nAre you sure that you want to '
                    'continue?'), QMessageBox.Yes | QMessageBox.Cancel)
        if reply == QMessageBox.Yes:
            fname = QFileDialog.getOpenFileName(self, title)
            if fname:
                msg = self.tr('Succesful import!')
                try:
                    self.tree = etree.parse(fname)
                except:
                    msg = self.tr('Import failed!')
                else:
                    self.root = self.tree.getroot()
                    self.save_tree()
                QMessageBox.information(self, title, msg)

    def export_presets(self):
        """Export the xml tree."""
        fname = QFileDialog.getSaveFileName(
            self, 'FF Multi Converter - Export presets', '.xml')
        if fname:
            self.load_xml()
            with open(fname, 'w') as _file:
                try:
                    etree.ElementTree(self.root).write(_file)
                except:
                    pass

    def reset(self):
        """Import the default xml tree."""
        reply = QMessageBox.question(
            self, 'FF Multi Converter - ' + self.tr('Delete Preset'),
            self.tr('Are you sure that you want to restore '
                    'the default presets?'),
            QMessageBox.Yes | QMessageBox.Cancel)
        if reply == QMessageBox.Yes:
            if os.path.exists(self.current_presets_file):
                os.remove(self.current_presets_file)

    def synchronize(self):
        """
        Synchronize current presets with default presets.

        For each preset in default presets:
        - if not contained in current presets, add it to current presets
        - if has the same name with some preset in current presets but
          different attributes, then add this preset to current presets and
          add an '__OLD' suffix to matching preset's name
        """
        reply = QMessageBox.question(
            self, 'FF Multi Converter - ' + self.tr('Presets Synchronization'),
            self.
            tr('Current presets and default '
               'presets will be merged. Are you sure that you want to continue?'
               ), QMessageBox.Yes | QMessageBox.Cancel)
        if not reply == QMessageBox.Yes:
            return

        def_tree = etree.parse(self.original_presets_file)
        def_root = def_tree.getroot()
        self.load_xml()

        for i in def_root:
            for n, y in enumerate(self.root):
                if i.tag == y.tag:
                    if not (i[0].text == y[0].text and i[1].text == y[1].text
                            and i[2].text == y[2].text):
                        # copy element and change its name
                        elem = etree.Element(y.tag)
                        label = etree.Element('label')
                        label.text = i[0].text
                        command = etree.Element('params')
                        command.text = i[1].text
                        ext = etree.Element('extension')
                        ext.text = i[2].text
                        elem.insert(0, label)
                        elem.insert(1, command)
                        elem.insert(2, ext)

                        y.tag = y.tag + '__OLD'
                        self.root.insert(n + 1, elem)
                    break
            else:
                # preset not found
                index = sorted([x.tag
                                for x in self.root] + [i.tag]).index(i.tag)
                self.root.insert(index, i)
        self.save_tree()

    def remove_old(self):
        """Remove those xml elements which their tags has an __OLD prefix."""
        reply = QMessageBox.question(
            self, 'FF Multi Converter - ' + self.tr('Remove old presets'),
            self.tr(
                'All presets with an __OLD prefix '
                'will be deleted. Are you sure that you want to continue?'),
            QMessageBox.Yes | QMessageBox.Cancel)
        if not reply == QMessageBox.Yes:
            return

        self.load_xml()
        for i in self.root:
            if i.tag.endswith('__OLD'):
                self.root.remove(i)
        self.save_tree()

    def accept(self):
        """
        Save current xml element's values in order to be used from
        main program and close (accept) dialog.
        """
        self.the_command = None
        if self.presListWidget:
            self.the_command = self.presListWidget.currentItem()\
                               .xml_element[1].text
            self.the_extension = self.presListWidget.currentItem()\
                                 .xml_element[2].text
        QDialog.accept(self)
예제 #29
0
class SessionEditor(QDialog):
    def __init__(self, parent=None):
        super(SessionEditor, self).__init__(parent)
        self.setWindowModality(Qt.WindowModal)

        layout = QVBoxLayout()
        self.setLayout(layout)

        grid = QGridLayout()
        layout.addLayout(grid)

        self.name = QLineEdit()
        self.nameLabel = l = QLabel()
        l.setBuddy(self.name)
        grid.addWidget(l, 0, 0)
        grid.addWidget(self.name, 0, 1)

        self.autosave = QCheckBox()
        grid.addWidget(self.autosave, 1, 1)

        self.basedir = widgets.urlrequester.UrlRequester()
        self.basedirLabel = l = QLabel()
        l.setBuddy(self.basedir)
        grid.addWidget(l, 2, 0)
        grid.addWidget(self.basedir, 2, 1)

        layout.addWidget(widgets.Separator())
        self.buttons = b = QDialogButtonBox(self)
        layout.addWidget(b)
        b.setStandardButtons(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        b.accepted.connect(self.accept)
        b.rejected.connect(self.reject)
        userguide.addButton(b, "sessions")
        app.translateUI(self)

    def translateUI(self):
        self.nameLabel.setText(_("Name:"))
        self.autosave.setText(
            _("Always save the list of documents in this session"))
        self.basedirLabel.setText(_("Base directory:"))

    def load(self, name):
        settings = sessions.sessionGroup(name)
        self.autosave.setChecked(settings.value("autosave", True, bool))
        self.basedir.setPath(settings.value("basedir", "", type("")))
        # more settings here

    def save(self, name):
        settings = sessions.sessionGroup(name)
        settings.setValue("autosave", self.autosave.isChecked())
        settings.setValue("basedir", self.basedir.path())
        # more settings here

    def defaults(self):
        self.autosave.setChecked(True)
        self.basedir.setPath('')
        # more defaults here

    def edit(self, name=None):
        self._originalName = name
        if name:
            caption = _("Edit session: {name}").format(name=name)
            self.name.setText(name)
            self.load(name)
        else:
            caption = _("Edit new session")
            self.name.clear()
            self.name.setFocus()
            self.defaults()
        self.setWindowTitle(app.caption(caption))
        if self.exec_():
            # name changed?
            name = self.name.text()
            if self._originalName and name != self._originalName:
                sessions.renameSession(self._originalName, name)
            self.save(name)
            return name

    def done(self, result):
        if not result or self.validate():
            super(SessionEditor, self).done(result)

    def validate(self):
        """Checks if the input is acceptable.
        
        If this method returns True, the dialog is accepted when OK is clicked.
        Otherwise a messagebox could be displayed, and the dialog will remain
        visible.
        """
        name = self.name.text().strip()
        self.name.setText(name)
        if not name:
            self.name.setFocus()
            QMessageBox.warning(self, app.caption(_("Warning")),
                                _("Please enter a session name."))
            if self._originalName:
                self.name.setText(self._originalName)
            return False

        elif name == '-':
            self.name.setFocus()
            QMessageBox.warning(
                self, app.caption(_("Warning")),
                _("Please do not use the name '{name}'.".format(name="-")))
            return False

        elif self._originalName != name and name in sessions.sessionNames():
            self.name.setFocus()
            box = QMessageBox(
                QMessageBox.Warning, app.caption(_("Warning")),
                _("Another session with the name {name} already exists.\n\n"
                  "Do you want to overwrite it?").format(name=name),
                QMessageBox.Discard | QMessageBox.Cancel, self)
            box.button(QMessageBox.Discard).setText(_("Overwrite"))
            result = box.exec_()
            if result != QMessageBox.Discard:
                return False

        return True
예제 #30
0
파일: linkInput.py 프로젝트: ThePsyjo/PyWv
class LinkInput(QDialog):
	def __init__(self, cfg, parent = None):
		QDialog.__init__(self)
		self.setParent(parent)
		self.setWindowFlags(Qt.Dialog)
		self.setWindowTitle(self.tr('manage links'))
		self.setModal(1)

		self.config = cfg

		self.modified = []

		self.links = self.config.loadLinks()

		self.typeSelect = QComboBox(self)
		self.plugins = classdirPlugins()
		plugs = self.plugins.classes()
		self.typeSelect.addItems(['generic'] + plugs)

		self.nameSelect = QComboBox(self)
		self.nameSelect.addItems([l for l in self.links])

		self.connect(self.nameSelect, SIGNAL('currentIndexChanged(int)'), self.onNameSelectChange)

		self.lUserName   = QLabel(self.tr('userName'), self)
		self.lPass       = QLabel(self.tr('password'), self)
		self.lUrl	= QLabel(self.tr('Url'), self)
		self.lType       = QLabel(self.tr('widgetType'), self)
		self.lWidgetName = QLabel(self.tr('widgetName'), self)

		self.name    = QLineEdit(self)
		self.urlEdit = QLineEdit()
		self.passwd  = QLineEdit(self)
		self.passwd.setEchoMode(QLineEdit.Password)

		self.connect(self.typeSelect , SIGNAL('activated(int)')      , self.onChange)
		self.connect(self.urlEdit    , SIGNAL('textEdited(QString)') , self.onChange)
		self.connect(self.name       , SIGNAL('textEdited(QString)') , self.onChange)
		self.connect(self.passwd     , SIGNAL('textEdited(QString)') , self.onChange)

		self.newButton = QPushButton(self.tr('&new'), self)
		self.delButton = QPushButton(self.tr('&del'), self)
		self.savButton = QPushButton(self.tr('&save'), self)
		self.finButton = QPushButton(self.tr('&finish'), self)

		self.defFont = QFont()

		self.connect(self.newButton, SIGNAL('clicked()'), self.onNewClick)
		self.connect(self.delButton, SIGNAL('clicked()'), self.onDelClick)
		self.connect(self.savButton, SIGNAL('clicked()'), self.onSavClick)
		self.connect(self.finButton, SIGNAL('clicked()'), self.onFinClick)

		self.layout = QGridLayout(self)

		self.layout.addWidget(self.lWidgetName , 0 , 0)
		self.layout.addWidget(self.lType       , 2 , 0)
		self.layout.addWidget(self.lUrl	, 3 , 0)
		self.layout.addWidget(self.lUserName   , 4 , 0)
		self.layout.addWidget(self.lPass       , 5 , 0)

		self.layout.addWidget(self.nameSelect  , 0 , 1)
		self.layout.addWidget(self.typeSelect  , 2 , 1)
		self.layout.addWidget(self.urlEdit     , 3 , 1)
		self.layout.addWidget(self.name	, 4 , 1)
		self.layout.addWidget(self.passwd      , 5 , 1)

		self.layout.addWidget(self.newButton   , 1 , 2)
		self.layout.addWidget(self.delButton   , 2 , 2)
		self.layout.addWidget(self.savButton   , 3 , 2)
		self.layout.addWidget(self.finButton   , 4 , 2)

		self.setMinimumWidth(500)

		self.nameSelect.setCurrentIndex(self.nameSelect.count()-1)

	def onChange(self):
		self.savButton.setFont(QFont(self.defFont.defaultFamily(), -1, QFont.Bold))

	def onSavClick(self):
		if self.urlEdit.text().isEmpty():
			self.urlEdit.setText(self.tr("insert URL here"))
			self.urlEdit.selectAll()
		else:
			u = QUrl()
			u.setUrl(self.urlEdit.text())
			if not u.scheme():
				u.setScheme('http')
			u.setUserName(self.name.text())
			u.setPassword(self.passwd.text())

			self.config.saveLink(self.nameSelect.currentText(), { 'type' : self.typeSelect.currentText(), 'data' : u.toString()})

			#self.links = self.config.loadLinks()
			self.savButton.setFont(QFont())

			self.modified.append(str(self.nameSelect.currentText()))


	def onNewClick(self):
		inp = StringInput([l for l in self.links], self)
		if inp.exec_():
			self.name.clear()
			self.passwd.clear()
			self.urlEdit.clear()
			self.nameSelect.addItem(inp.getVal())
			self.nameSelect.setCurrentIndex(self.nameSelect.findText(inp.getVal()))

	def onDelClick(self):
		if QMessageBox(    QMessageBox.Question,
				self.tr('del_link'),
				self.tr('ask_del_link %1 ?').arg(self.nameSelect.currentText()),
				QMessageBox.Yes | QMessageBox.No,
				self).exec_() == QMessageBox.Yes:
			if not self.config.delLink(self.nameSelect.currentText()):
				print(('link "%s" not deleted !' % self.nameSelect.currentText()))
			self.links = self.config.loadLinks()
			self.nameSelect.removeItem(self.nameSelect.currentIndex())

	def onFinClick(self):
		self.accept()

	def onNameSelectChange(self):
		try:
			l = self.links[str(self.nameSelect.currentText())]
			u = QUrl(l['data'])

			self.name.setText(u.userName())
			self.passwd.setText(u.password())
			self.urlEdit.setText(u.toString(QUrl.RemoveUserInfo))
			self.typeSelect.setCurrentIndex(self.typeSelect.findText(l['type']))
		except Exception as e:
			#print e
			pass

	def modifiedWidgets(self):
		return set(self.modified)
예제 #31
0
class ImageTab(QWidget):
    def __init__(self, parent):
        super(ImageTab, self).__init__(parent)
        self.parent = parent
        self.name = 'Images'
        self.formats = [
                'bmp', 'cgm', 'dpx', 'emf', 'eps', 'fpx', 'gif', 'jbig', 'jng',
                'jpeg', 'mrsid', 'p7', 'pdf', 'picon', 'png', 'ppm', 'psd',
                'rad', 'tga', 'tif','webp', 'xpm'
                ]

        self.extra_img = [
                'bmp2', 'bmp3', 'dib', 'epdf', 'epi', 'eps2', 'eps3', 'epsf',
                'epsi', 'icon', 'jpe', 'jpg', 'pgm', 'png24', 'png32', 'pnm',
                'ps', 'ps2', 'ps3', 'sid', 'tiff'
                ]

        validator = QRegExpValidator(QRegExp(r'^[1-9]\d*'), self)

        converttoQL = QLabel(self.tr('Convert to:'))
        self.extQCB = QComboBox()
        self.extQCB.addItems(self.formats)
        commandQL = QLabel(self.tr('Extra options:'))
        self.commandQLE = QLineEdit()

        hlayout2 = utils.add_to_layout(
                'h', converttoQL, self.extQCB, commandQL, self.commandQLE)

        sizeQL = QLabel(
                '<html><p align="center">' + self.tr('Image Size:') +
                '</p></html>')
        self.widthQLE = utils.create_LineEdit((50, 16777215), validator, 4)
        self.heightQLE = utils.create_LineEdit((50, 16777215), validator, 4)
        label = QLabel('<html><p align="center">x</p></html>')
        label.setMaximumWidth(25)

        hlayout1 = utils.add_to_layout('h', self.widthQLE, label,self.heightQLE)
        sizelayout = utils.add_to_layout('v', sizeQL, hlayout1)

        self.imgaspectQChB = QCheckBox(self.tr("Maintain aspect ratio"))
        self.autocropQChB = QCheckBox(self.tr("Auto-crop"))

        vlayout = utils.add_to_layout('v', self.imgaspectQChB,self.autocropQChB)

        rotateQL = QLabel(
                "<html><div align='center'>" + self.tr("Rotate") +
                ":</div><br>(" + self.tr("degrees - clockwise") + ")</html>")
        self.rotateQLE = utils.create_LineEdit((100, 16777215), validator, 3)
        self.vflipQChB = QCheckBox("Vertical flip")
        self.hflipQChB = QCheckBox("Horizontal flip")

        vlayout2 = utils.add_to_layout('v', self.vflipQChB, self.hflipQChB)
        hlayout3 = utils.add_to_layout(
                'h', sizelayout, vlayout, rotateQL, self.rotateQLE,
                vlayout2, None)

        final_layout = utils.add_to_layout('v', hlayout2, hlayout3)
        self.setLayout(final_layout)

    def clear(self):
        """Clear self.widthQLE and self.heightQLE."""
        self.widthQLE.clear()
        self.heightQLE.clear()
        self.commandQLE.clear()
        self.rotateQLE.clear()
        self.imgaspectQChB.setChecked(False)
        self.autocropQChB.setChecked(False)
        self.vflipQChB.setChecked(False)
        self.hflipQChB.setChecked(False)

    def ok_to_continue(self):
        """
        Check if everything is ok with imagetab to continue conversion.

        Check if:
        - ImageMagick is missing.
        - Either none or both size lineEdits are active at a time.

        Return True if all tests pass, else False.
        """
        width = self.widthQLE.text()
        height = self.heightQLE.text()

        if not self.parent.imagemagick:
            QMessageBox.warning(self, 'FF Multi Converter - ' + self.tr(
                'Error!'), self.tr('ImageMagick is not installed.\nYou will '
                'not be able to convert image files until you install it.'))
            return False
        if (width and not height) or (not width and height):
            QMessageBox.warning(self, 'FF Multi Converter - ' + self.tr(
                     'Error!'), self.tr('The size LineEdit may not be empty.'))
            if width and not height:
                self.heightQLE.setFocus()
            else:
                self.widthQLE.setFocus()
            return False
        return True
예제 #32
0
파일: bookmark.py 프로젝트: halbbob/dff
class bookDiag(QDialog):
    def __init__(self, parent):
        QDialog.__init__(self)
        self.setWindowTitle("Add bookmark entry")
        self.init(parent)
        self.initShape()

    def init(self, parent):
        self.bookmark = parent
        self.heditor = self.bookmark.heditor

    def createButtons(self):
        self.buttonbox = QDialogButtonBox()
        self.buttonbox.setStandardButtons(QDialogButtonBox.Cancel|QDialogButtonBox.Ok)
        self.connect(self.buttonbox, SIGNAL("accepted()"),self.accept)
        self.connect(self.buttonbox, SIGNAL("rejected()"),self.reject)
        return self.buttonbox

    def initShape(self):
        self.grid = QGridLayout()

        decoration = self.createDecoration()
        wButton = self.createButtons()
        wInfos = self.createInformations()

        self.grid.addWidget(decoration, 0, 0)
        self.grid.addWidget(wInfos, 1, 0)
        self.grid.addWidget(wButton, 2, 0)

        self.setLayout(self.grid)

    def createDecoration(self):
        self.deco = QWidget()
        self.hdeco = QHBoxLayout()

        pixlabel = QLabel()
        pix = QPixmap(":bookmark.png")
        pixlabel.setPixmap(pix)

        booklabel = QLabel("Add a description to this entry")

        self.hdeco.addWidget(pixlabel)
        self.hdeco.addWidget(booklabel)

        self.deco.setLayout(self.hdeco)
        return self.deco

    def createInformations(self):
        self.info = QWidget()
        self.igrid = QGridLayout()

        addressLabel = QLabel("Address: ")
        self.address = QLineEdit()
        self.address.setReadOnly(True)

        lend = QLabel("Length (dec): ")
        self.lendec = QLineEdit()
        self.lendec.setReadOnly(True)

        lenh = QLabel("Length (hex): ")
        self.lenhex = QLineEdit()
        self.lenhex.setReadOnly(True)

        deslabel = QLabel("Description: ")
        self.description = QLineEdit()

        hvlabel = QLabel("Hex value:")
        self.hexvalue = QLineEdit()
        self.hexvalue.setReadOnly(True)

        avlabel = QLabel("Ascii value:")
        self.asciivalue = QLineEdit()
        self.asciivalue.setReadOnly(True)
        
        self.igrid.addWidget(addressLabel, 0, 0, Qt.AlignLeft)
        self.igrid.addWidget(self.address, 0, 1, Qt.AlignLeft)

        self.igrid.addWidget(lend, 1, 0, Qt.AlignLeft)
        self.igrid.addWidget(self.lendec, 1, 1, Qt.AlignLeft)

        self.igrid.addWidget(lenh, 2, 0, Qt.AlignLeft)
        self.igrid.addWidget(self.lenhex, 2, 1, Qt.AlignLeft)

        self.igrid.addWidget(hvlabel, 3, 0, Qt.AlignLeft)
        self.igrid.addWidget(self.hexvalue, 3, 1, Qt.AlignLeft)

        self.igrid.addWidget(avlabel, 4, 0, Qt.AlignLeft)
        self.igrid.addWidget(self.asciivalue, 4, 1, Qt.AlignLeft)


        self.igrid.addWidget(deslabel, 5, 0, Qt.AlignLeft)
        self.igrid.addWidget(self.description, 5, 1, Qt.AlignLeft)

        self.info.setLayout(self.igrid)

        return self.info

    def cleanInformations(self):
        self.address.clear()
        self.lendec.clear()
        self.lenhex.clear()
        self.hexvalue.clear()
        self.asciivalue.clear()
        self.description.clear()

    def setInformations(self):
        self.cleanInformations()

        if self.heditor.decimalview:
            add = "%.2d" % self.heditor.selection.startoffset
        else:
            add = "0x"
            add += "%.2x" % self.heditor.selection.startoffset
        self.address.insert(add)

        if self.heditor.selection.length > 0:
            len = self.heditor.selection.length
        else:
            len = 1
        tolendec = "%.1d" % len
        self.lendec.insert(tolendec)

        tolenhex = "0x"
        tolenhex += "%.1X" % len
        self.lenhex.insert(tolenhex)

        hval = self.heditor.readHexValue(self.heditor.selection.offset, len)
        self.hexvalue.insert(hval)

        aval = self.heditor.readAsciiValue(self.heditor.selection.offset, len)
        self.asciivalue.insert(aval)
예제 #33
0
class LoginDlg(QDialog):
    """login dialog for server"""
    def __init__(self):
        """self.servers is a list of tuples containing server and last playername"""
        QDialog.__init__(self, None)
        self.setWindowTitle(m18n('Login') + ' - Kajongg')
        self.setupUi()

        localName = m18nc('kajongg name for local game server',
                          Query.localServerName)
        self.servers = Query(
            'select url,lastname from server order by lasttime desc').records
        servers = [
            m18nc('kajongg name for local game server', x[0])
            for x in self.servers
        ]
        # the first server combobox item should be default: either the last used server
        # or localName for autoPlay
        if localName not in servers:
            servers.append(localName)
        if 'kajongg.org' not in servers:
            servers.append('kajongg.org')
            demoHost = Options.host or localName
            if demoHost in servers:
                servers.remove(
                    demoHost
                )  # we want a unique list, it will be re-used for all following games
            servers.insert(
                0, demoHost)  # in this process but they will not be autoPlay
        self.cbServer.addItems(servers)
        self.passwords = Query(
            'select url, p.name, passwords.password from passwords, player p '
            'where passwords.player=p.id').records
        Players.load()
        self.cbServer.editTextChanged.connect(self.serverChanged)
        self.cbUser.editTextChanged.connect(self.userChanged)
        self.serverChanged()
        StateSaver(self)

    def returns(self, dummyButton=None):
        """maybe we should return an class ServerConnection"""
        return (self.useSocket, self.url, self.username,
                self.__defineRuleset())

    def setupUi(self):
        """create all Ui elements but do not fill them"""
        buttonBox = KDialogButtonBox(self)
        buttonBox.setStandardButtons(QDialogButtonBox.Cancel
                                     | QDialogButtonBox.Ok)
        # Ubuntu 11.10 unity is a bit strange - without this, it sets focus on
        # the cancel button (which it shows on the left). I found no obvious
        # way to use setDefault and setAutoDefault for fixing this.
        buttonBox.button(QDialogButtonBox.Ok).setFocus(True)
        buttonBox.accepted.connect(self.accept)
        buttonBox.rejected.connect(self.reject)
        vbox = QVBoxLayout(self)
        self.grid = QFormLayout()
        self.cbServer = QComboBox()
        self.cbServer.setEditable(True)
        self.grid.addRow(m18n('Game server:'), self.cbServer)
        self.cbUser = QComboBox()
        self.cbUser.setEditable(True)
        self.grid.addRow(m18n('Username:'******'Password:'******'kajongg', 'Ruleset:'), self.cbRuleset)
        vbox.addLayout(self.grid)
        vbox.addWidget(buttonBox)
        pol = QSizePolicy()
        pol.setHorizontalPolicy(QSizePolicy.Expanding)
        self.cbUser.setSizePolicy(pol)

    def serverChanged(self, dummyText=None):
        """the user selected a different server"""
        records = Query(
            'select player.name from player, passwords '
            'where passwords.url=? and passwords.player = player.id',
            list([self.url])).records
        players = list(x[0] for x in records)
        preferPlayer = Options.player
        if preferPlayer:
            if preferPlayer in players:
                players.remove(preferPlayer)
            players.insert(0, preferPlayer)
        self.cbUser.clear()
        self.cbUser.addItems(players)
        if not self.cbUser.count():
            user = KUser() if os.name == 'nt' else KUser(os.geteuid())
            self.cbUser.addItem(user.fullName() or user.loginName())
        if not preferPlayer:
            userNames = [x[1] for x in self.servers if x[0] == self.url]
            if userNames:
                userIdx = self.cbUser.findText(userNames[0])
                if userIdx >= 0:
                    self.cbUser.setCurrentIndex(userIdx)
        showPW = self.url != Query.localServerName
        self.grid.labelForField(self.edPassword).setVisible(showPW)
        self.edPassword.setVisible(showPW)
        self.grid.labelForField(self.cbRuleset).setVisible(
            not showPW and not Options.ruleset)
        self.cbRuleset.setVisible(not showPW and not Options.ruleset)
        if not showPW:
            self.cbRuleset.clear()
            if Options.ruleset:
                self.cbRuleset.items = [Options.ruleset]
            else:
                self.cbRuleset.items = Ruleset.selectableRulesets(self.url)

    def __defineRuleset(self):
        """find out what ruleset to use"""
        if Options.ruleset:
            return Options.ruleset
        elif Internal.autoPlay or bool(Options.host):
            return Ruleset.selectableRulesets()[0]
        else:
            return self.cbRuleset.current

    def userChanged(self, text):
        """the username has been changed, lookup password"""
        if text == '':
            self.edPassword.clear()
            return
        passw = None
        for entry in self.passwords:
            if entry[0] == self.url and entry[1] == unicode(text):
                passw = entry[2]
        if passw:
            self.edPassword.setText(passw)
        else:
            self.edPassword.clear()

    @property
    def url(self):
        """abstracts the url of the dialog"""
        return english(unicode(self.cbServer.currentText()))

    @property
    def host(self):
        """abstracts the host of the dialog"""
        return self.url.partition(':')[0]

    @property
    def useSocket(self):
        """do we use socket for current host?"""
        return self.host == Query.localServerName

    @property
    def port(self):
        """abstracts the port of the dialog"""
        try:
            return int(self.url.partition(':')[2])
        except ValueError:
            return Options.defaultPort()

    @property
    def username(self):
        """abstracts the username of the dialog"""
        return unicode(self.cbUser.currentText())

    @property
    def password(self):
        """abstracts the password of the dialog"""
        return unicode(self.edPassword.text())

    @password.setter
    def password(self, password):
        """abstracts the password of the dialog"""
        self.edPassword.setText(password)

    def updateServerInfoInDatabase(self):
        """we are online. Update table server."""
        lasttime = datetime.datetime.now().replace(microsecond=0).isoformat()
        url = english(self.url)  # use unique name for Local Game
        with Transaction():
            serverKnown = Query(
                'update server set lastname=?,lasttime=? where url=?',
                list([self.username, lasttime, url])).rowcount() == 1
            if not serverKnown:
                Query(
                    'insert into server(url,lastname,lasttime) values(?,?,?)',
                    list([url, self.username, lasttime]))
        # needed if the server knows our name but our local data base does not:
        Players.createIfUnknown(self.username)
        playerId = Players.allIds[self.username]
        with Transaction():
            if Query(
                    'update passwords set password=? where url=? and player=?',
                    list([self.password, url, playerId])).rowcount() == 0:
                Query(
                    'insert into passwords(url,player,password) values(?,?,?)',
                    list([url, playerId, self.password]))
예제 #34
0
class ImageTab(QWidget):
    def __init__(self, parent):
        super(ImageTab, self).__init__(parent)
        self.parent = parent
        self.name = 'Images'

        self.formats = config.image_formats
        self.extra_img = config.image_extra_formats

        validator = QRegExpValidator(QRegExp(r'^[1-9]\d*'), self)

        converttoQL = QLabel(self.tr('Convert to:'))
        self.extQCB = QComboBox()
        self.extQCB.addItems(self.formats)
        commandQL = QLabel(self.tr('Extra options:'))
        self.commandQLE = QLineEdit()

        hlayout2 = utils.add_to_layout(
                'h', converttoQL, self.extQCB, commandQL, self.commandQLE)

        sizeQL = QLabel(
                '<html><p align="center">' + self.tr('Image Size:') +
                '</p></html>')
        self.widthQLE = utils.create_LineEdit((50, 16777215), validator, 4)
        self.heightQLE = utils.create_LineEdit((50, 16777215), validator, 4)
        label = QLabel('<html><p align="center">x</p></html>')
        label.setMaximumWidth(25)

        hlayout1 = utils.add_to_layout('h', self.widthQLE, label,self.heightQLE)
        sizelayout = utils.add_to_layout('v', sizeQL, hlayout1)

        self.imgaspectQChB = QCheckBox(self.tr("Maintain aspect ratio"))
        self.autocropQChB = QCheckBox(self.tr("Auto-crop"))

        vlayout = utils.add_to_layout('v', self.imgaspectQChB,self.autocropQChB)

        rotateQL = QLabel(
                "<html><div align='center'>" + self.tr("Rotate") +
                ":</div><br>(" + self.tr("degrees - clockwise") + ")</html>")
        self.rotateQLE = utils.create_LineEdit((100, 16777215), validator, 3)
        self.vflipQChB = QCheckBox(self.tr('Vertical flip'))
        self.hflipQChB = QCheckBox(self.tr('Horizontal flip'))

        vlayout2 = utils.add_to_layout('v', self.vflipQChB, self.hflipQChB)
        hlayout3 = utils.add_to_layout(
                'h', sizelayout, vlayout, rotateQL, self.rotateQLE,
                vlayout2, None)

        final_layout = utils.add_to_layout('v', hlayout2, hlayout3)
        self.setLayout(final_layout)

    def clear(self):
        """Clear self.widthQLE and self.heightQLE."""
        self.widthQLE.clear()
        self.heightQLE.clear()
        self.commandQLE.clear()
        self.rotateQLE.clear()
        self.imgaspectQChB.setChecked(False)
        self.autocropQChB.setChecked(False)
        self.vflipQChB.setChecked(False)
        self.hflipQChB.setChecked(False)

    def fill_extension_combobox(self, extraformats):
        extraformats = [i for i in extraformats.split("\n")] if extraformats else []
        self.extQCB.clear()
        self.extQCB.addItems(sorted(self.formats + extraformats))

    def ok_to_continue(self):
        """
        Check if everything is ok with imagetab to continue conversion.

        Check if:
        - ImageMagick is missing.
        - Either none or both size lineEdits are active at a time.

        Return True if all tests pass, else False.
        """
        width = self.widthQLE.text()
        height = self.heightQLE.text()

        if not self.parent.imagemagick:
            QMessageBox.warning(self, 'FF Multi Converter - ' + self.tr(
                'Error!'), self.tr('ImageMagick is not installed.\nYou will '
                'not be able to convert image files until you install it.'))
            return False
        if (width and not height) or (not width and height):
            QMessageBox.warning(self, 'FF Multi Converter - ' + self.tr(
                     'Error!'), self.tr('The size LineEdit may not be empty.'))
            if width and not height:
                self.heightQLE.setFocus()
            else:
                self.widthQLE.setFocus()
            return False
        return True

    def set_default_command(self):
        """Set the default value to self.commandQLE."""
        self.clear()
        self.commandQLE.setText(self.parent.default_command_image)
예제 #35
0
class ComboCheckBox(QComboBox):
    def __init__(self, itemdicts):  # items==[str,str...]
        super(ComboCheckBox, self).__init__()

        self.itemdict = itemdicts
        self.items = self.itemdict.keys()
        self.items.insert(0, u'全部')
        self.row_num = len(self.items)
        self.Selectedrow_num = 0
        self.qCheckBox = []
        self.qLineEdit = QLineEdit()
        self.qLineEdit.setReadOnly(True)
        self.qListWidget = QListWidget()
        self.addQCheckBox(0)
        self.qCheckBox[0].stateChanged.connect(self.All)
        for i in range(1, self.row_num):
            self.addQCheckBox(i)
            self.qCheckBox[i].stateChanged.connect(self.show)
        self.setModel(self.qListWidget.model())
        self.setView(self.qListWidget)
        self.setLineEdit(self.qLineEdit)
        self.show()

        # self.qListWidget.setAlternatingRowColors(True)
        # self.qLineEdit.setAlternatingRowColors(True)
        # self.qLineEdit.setStyleSheet("background-color:transparen ")
        # self.qListWidget.setStyleSheet("background-color:#ee3333 ")

    def addQCheckBox(self, i):
        self.qCheckBox.append(QCheckBox())
        qItem = QListWidgetItem(self.qListWidget)
        self.qCheckBox[i].setText(self.items[i])
        if i > 0 and self.itemdict[self.items[i]] == "1":
            self.qCheckBox[i].setChecked(True)
        self.qListWidget.setItemWidget(qItem, self.qCheckBox[i])

    def Selectlist(self):
        Outputlist = []
        for i in range(1, self.row_num):
            if self.qCheckBox[i].isChecked() == True:
                Outputlist.append(self.qCheckBox[i].text())
        self.Selectedrow_num = len(Outputlist)
        return Outputlist

    def show(self):
        show = ''
        Outputlist = self.Selectlist()
        self.qLineEdit.setReadOnly(False)
        self.qLineEdit.clear()
        for i in Outputlist:
            show += i + ';'
        if self.Selectedrow_num == 0:
            self.qCheckBox[0].setCheckState(0)
        elif self.Selectedrow_num == self.row_num - 1:
            self.qCheckBox[0].setCheckState(2)
        else:
            self.qCheckBox[0].setCheckState(1)
        self.qLineEdit.setText(show)
        self.qLineEdit.setReadOnly(True)

    def All(self, state):
        if state == 2:
            for i in range(1, self.row_num):
                self.qCheckBox[i].setChecked(True)
        elif state == 1:
            if self.Selectedrow_num == 0:
                self.qCheckBox[0].setCheckState(2)
        elif state == 0:
            self.clear()

    def clear(self):
        for i in range(self.row_num):
            self.qCheckBox[i].setChecked(False)
예제 #36
0
class CommandWindow(QFrame):
    """Miow main window
    """

    def __init__(self, parent=None):
        super(CommandWindow, self).__init__(parent)
        self.parent = parent
        self.setWindowFlags(QtCore.Qt.Popup)

        self.setFont(QFont("Monospace", 14))
        self.setMinimumWidth(400)
        self.setMinimumHeight(300)
        self.setGeometry(0, 0, 600, 300)


        # create widgets
        layout = QVBoxLayout(self)
        
        self.line_edit = QLineEdit(self)
        layout.addWidget(self.line_edit)

        self.list_widget = QListWidget(self)
        self.list_widget.currentItemChanged.connect(self.on_current_item_changed)
        layout.addWidget(self.list_widget)
        layout.setStretchFactor(self.list_widget, 15)

        layout.setMargin(0)
        layout.setSpacing(0)
        layout.setContentsMargins(0,0,0,0)
        self.setLayout(layout)
        self.line_edit.setFocus()

        self.full_command = QPlainTextEdit(self)
        self.full_command.setFont(QFont("Monospace", 8))
        size_policy = self.full_command.sizePolicy()
        size_policy.setVerticalPolicy(QSizePolicy.Ignored)
        self.full_command.setSizePolicy(size_policy)
        layout.addWidget(self.full_command)
        layout.setStretchFactor(self.full_command, 3)


        layout2 = QHBoxLayout(self)
        
        self.weight = QLabel(self)
        self.weight.setFont(QFont("Monospace", 8))
        size_policy = self.weight.sizePolicy()
        size_policy.setVerticalPolicy(QSizePolicy.Ignored)
        self.weight.setSizePolicy(size_policy)
        layout2.addWidget(self.weight)
        layout2.setStretchFactor(self.weight, 1)

        self.labels = QLabel(self)
        self.labels.setFont(QFont("Monospace", 8))
        size_policy = self.labels.sizePolicy()
        size_policy.setVerticalPolicy(QSizePolicy.Ignored)
        self.labels.setSizePolicy(size_policy)
        layout2.addWidget(self.labels)
        layout2.setStretchFactor(self.labels, 8)

        layout.addLayout(layout2)
        layout.setStretchFactor(layout2, 1)
        
        self.line_edit.textChanged.connect(self.on_text_changed)
        self.list_widget.itemDoubleClicked.connect(self.on_item_double_clicked)

        self.event_selected_command = Event()
        


    def show_hide(self, context):
        if self.isVisible() == False or context is not None:        
            self.command_list = self.parent.get_command_list(context)
            self.filter_commands("")
            self.show()
        else:
            self.hide()

    def showEvent(self, event):
        geom = self.frameGeometry()
        self.line_edit.setFocus()
        self.line_edit.clear()
        #parent_widget = self.parentWidget()
        if self.parent:
            geom.moveCenter(QtCore.QPoint(self.parent.pos().x()+self.parent.width()/2,
                                          self.parent.pos().y()+self.parent.height()/3))
            self.setGeometry(geom)
            super(QFrame, self).showEvent(event)

    def _get_command_from_text(self, text):
        for command_text, tags, weight, command in self.command_list:
            if command_text == text:
                return command
        return None

    def _get_full_command_from_text(self, text):
        for command_text, tags, weight, command in self.command_list:
            if command_text == text:
                return (command_text, tags, weight, command)
        return None
        
    def keyPressEvent(self, event):
        if event.type() == QEvent.KeyPress:
            key_event = QKeyEvent(event)
            if(key_event.key() == Qt.Key_Down
              or key_event.key() == Qt.Key_Up):
                return self.list_widget.keyPressEvent(event)
            elif((event.key() == Qt.Key_Enter  or  event.key() == Qt.Key_Return)
                    and self.list_widget.currentItem()>=0):
                self.hide()
                self.event_selected_command(str(self.full_command.toPlainText()))
        return super(CommandWindow, self).keyPressEvent(event)

    def on_item_double_clicked(self, item):
        self.hide()
        self.event_selected_command(str(self.full_command.toPlainText()))


    def on_current_item_changed(self, prev, current):
        if(self.list_widget.currentItem()):
            command_text, tags, weight, command = self._get_full_command_from_text(
                                        self.list_widget.currentItem().text())
            self.full_command.setPlainText(command)
            self.labels.setText(tags)
            self.weight.setText(str(weight))
        else:
            self.full_command.setPlainText("")
            self.labels.setText("")
            self.weight.setText("")


    def filter_commands(self, text):
        self.list_widget.clear()
        text = str(text).upper()

        def get_item_map_def0(_map, key):
            if(key in _map):
                return _map[key]
            else:
                return 0.

        def get_command_matches(command_list, words):
            result_map = {}
            for command, tags, _, _ in command_list:
                for word in words:
                    located_command_weight = 1
                    located_tag_weight = 0.3
                    if word == '':
                        located_command_weight = 0.
                        located_tag_weight = 0.
                    if command.upper().find(word) != -1:
                        result_map[command] = (get_item_map_def0(result_map,
                                                    command)
                                                    - located_command_weight)
                    for tag in tags.split(" "):
                        if tag.upper().find(word) != -1:
                            result_map[command] = (get_item_map_def0(result_map,
                                                    command)
                                                    - located_tag_weight)
            for command, _, current_weight, _ in command_list:
                if command in result_map:
                    result_map[command] -= current_weight
            return sorted(result_map, key=result_map.get)


        words = str(text).strip().split(" ")
        matches_map = get_command_matches(self.command_list, words)
        for command in matches_map:
            self.list_widget.addItem(command)
        self.list_widget.setCurrentRow(0)


    def on_text_changed(self, text):
        self.filter_commands(text)
예제 #37
0
class LigneCommande(QWidget):
    u"""Un TextCtrl muni d'un historique et associé à un bouton pour valider.

    On peut personnaliser le texte du bouton (via `texte="Mon texte"`),
    ou même directement le bouton, en utilisant `bouton=...`.
    """
    def __init__(self, parent, longueur = 500, texte = None, bouton = None,
                action = (lambda *args, **kw: True), afficher_bouton = True,
                legende = None):
        self.parent = parent
        self.action = action
        QWidget.__init__(self, parent)

        sizer = QHBoxLayout()
        self.texte = QLineEdit()
        self.texte.setMinimumWidth(longueur)
        if bouton is None:
            self.bouton = QPushButton('OK' if texte is None else texte)
        else:
            self.bouton = bouton
        self.bouton.setVisible(afficher_bouton)
        self.bouton.clicked.connect(self.valider)

        if legende is not None:
            sizer.addWidget(QLabel(legende, self))
        sizer.addWidget(self.texte)
        sizer.addWidget(self.bouton)
        self.setLayout(sizer)
        self.initialiser()


    def initialiser(self):
        self.historique = []
        self.position = None
        self.setFocus()
        self.clear()

    def text(self):
        return self.texte.text()

    def setText(self, value):
        self.texte.setText(value)

    def setFocus(self):
        self.texte.setFocus()

    def clear(self):
        self.texte.clear()

    def getSelection(self):
        if self.texte.hasSelectedText():
            start = self.texte.selectionStart()
            length = len(self.texte.selectedText())
            end = start + length
        else:
            start = end = self.texte.cursorPosition()
        return start, end

    def cursorPosition(self):
        return self.texte.cursorPosition()

    def setCursorPosition(self, num):
        return self.texte.setCursorPosition(num)

    def insert(self, texte):
        self.texte.insert(texte)

    def setSelection(self, deb, fin):
        self.texte.setSelection(deb, fin)

    def setToolTip(self, tip):
        self.texte.setToolTip(tip)

    def valider(self, **kw):
        # kw: shift|alt|meta|control=True|False'
        commande = unicode(self.text())
        self.position = None
        if commande:
            self.historique.append(commande)
        elif self.historique:
            # Appuyer une deuxième fois sur [Entrée] permet de répéter l'action précédente.
            commande = self.historique[-1]
        self.action(commande, **kw)


    def keyPressEvent(self, event):
        key = event.key()
        commande = self.text()

        if key == Qt.Key_Up and self.historique:
            # On remonte dans l'historique (-> entrées plus anciennes)
            if self.position is None:
                # cas d'une commande en cours d'édition :
                if commande:
                    if commande != self.historique[-1]:
                        # on enregistre la commande en cours
                        self.historique.append(commande)
                    self.position = len(self.historique) - 1
                else:
                    self.position = len(self.historique)
            if self.position > 0:
                self.position -= 1
                self.texte.setText(self.historique[self.position])

        elif key == Qt.Key_Down and self.historique:
            # On redescend dans l'historique (-> entrées plus récentes)
            if self.position is None or self.position == len(self.historique) - 1:
                if commande and commande != self.historique[-1]:
                    self.historique.append(commande)
                self.texte.clear()
                self.position = len(self.historique)
            elif self.position < len(self.historique) - 1:
                self.position += 1
                self.texte.setText(self.historique[self.position])
        elif key in (Qt.Key_Enter, Qt.Key_Return):
            modifiers = event.modifiers()
            kw = {'shift': modifiers & Qt.ShiftModifier,
                  'alt': modifiers & Qt.AltModifier,
                  'meta': modifiers & Qt.MetaModifier,
                  'control': modifiers & Qt.ControlModifier,
                      }
            self.valider(**kw)
        else:
            self.position = None
예제 #38
0
파일: main.py 프로젝트: xiaq/chat
class ChatWindow(QWidget):
    def __init__(self, socket, addr):
        super(ChatWindow, self).__init__()

        self.socket = socket
        self.addr = addr
        self.setupSocket()
        self.createUi()

    def setupSocket(self):
        self.socket.disconnected.connect(self.onDisconnected)
        self.socket.error.connect(self.onError)

    def createUi(self):
        vbox = QVBoxLayout()
        self.buf = TextBrowser(self.addr.toString())
        self.buf.setFontFamily('Monospace')
        self.buf.setFocusPolicy(Qt.NoFocus)
        vbox.addWidget(self.buf, 1)
        hbox_send = QHBoxLayout()
        self.send_text = QLineEdit()
        hbox_send.addWidget(self.send_text, 1)
        self.send_button = QPushButton("Send")
        self.send_file_button = QPushButton("Send File")
        hbox_send.addWidget(self.send_button)
        hbox_send.addWidget(self.send_file_button)
        vbox.addLayout(hbox_send)
        self.setLayout(vbox)

        self.send_text.returnPressed.connect(self.onSend)
        self.send_button.clicked.connect(self.onSend)
        self.send_file_button.clicked.connect(self.onSendFile)

    def onSend(self):
        text = unicode(self.send_text.text())
        encoded = text.encode(TEXT_ENCODING)
        header = 'T%d ' % len(encoded)
        payload = header + encoded
        if self.socket.write(payload) < len(payload):
            self.buf.error('Failed to send message %s' % urepr(text))
        self.send_text.clear()

    sendFileBufSize = 1024

    def onSendFile(self):
        path = str(QFileDialog.getOpenFileName())

        if not os.path.exists(path):
            if len(path) == 0:
                self.buf.info('File sending cancelled.')
            else:
                self.buf.error("File %s doesn't exist." % path)
            return

        size = os.path.getsize(path)
        bname = os.path.basename(path)[:512]
        header = 'F%d %s/' % (size, bname)
        if len(header) > self.sendFileBufSize:
            raise ChatException("Header too long, give up")

        with open(path, 'rb') as f:
            buf = header + f.read(self.sendFileBufSize - len(header))
            while len(buf) > 0:
                if self.socket.write(buf) < len(buf):
                    self.buf.error('Failed to send file %s' % bname)
                    break
                buf = f.read(self.sendFileBufSize)

    def onConnected(self):
        self.buf.info('Connected to peer %s.' % unicode(self.peer.toString()))

    def onDisconnected(self):
        self.buf.info('Peer went offline.')

    def onError(self):
        self.buf.error('Something went wrong with the connection.')
예제 #39
0
class ChatWindow(QWidget):
    """a widget for showing chat messages"""
    def __init__(self, table=None, game=None):
        super(ChatWindow, self).__init__(None)
        self.table = table or game.client.table
        self.table.chatWindow = self
        title = m18n('Chat on table %1 at %2', self.table.tableid,
                     self.table.client.connection.url)
        self.setObjectName('chatWindow')
        self.setWindowTitle(title + ' - kajongg')
        self.messageView = ChatView()
        self.messageView.setModel(ChatModel())
        self.messageView.setFocusPolicy(Qt.NoFocus)
        self.messageView.setShowGrid(False)
        self.messageView.setWordWrap(False)
        self.messageView.setSelectionMode(QAbstractItemView.NoSelection)
        if Debug.modelTest:
            self.debugModelTest = ModelTest(self.messageView.model(),
                                            self.messageView)
        self.edit = QLineEdit()
        layout = QVBoxLayout()
        layout.addWidget(self.messageView)
        layout.addWidget(self.edit)
        self.setLayout(layout)
        self.edit.returnPressed.connect(self.sendLine)
        self.edit.setFocus()
        self.show()
        StateSaver(self)

    def show(self):
        """not only show but also restore and raise"""
        self.activateWindow()
        self.setWindowState(self.windowState() & ~Qt.WindowMinimized)
        self.raise_()
        QWidget.show(self)

    def isVisible(self):
        """not only visible but also not minimized"""
        return QWidget.isVisible(
            self) and not self.windowState() & Qt.WindowMinimized

    def kill(self):
        """hide and null on table"""
        print('chat.kill for %s on table %s' % (self, self.table))
        self.hide()
        self.table.chatWindow = None

    def sendLine(self, line=None, isStatusMessage=False):
        """send line to others. Either the edited line or parameter line."""
        if line is None:
            line = unicode(self.edit.text())
            self.edit.clear()
        if line:
            if Debug.chat:
                logDebug('sending line %s to others' % line)
            msg = ChatMessage(self.table.tableid, self.table.client.name, line,
                              isStatusMessage)
            self.table.client.sendChat(msg).addErrback(self.chatError)

    def chatError(self, result):
        """tableList may already have gone away"""
        if self.table.client.tableList:
            self.table.client.tableList.tableError(result)

    def leave(self):
        """leaving the chat"""
        # TODO: send "left" message
        self.hide()

    def receiveLine(self, chatLine):
        """show a new line in protocol"""
        self.show()
        self.messageView.model().appendLines(chatLine)
        for row in range(self.messageView.model().rowCount()):
            self.messageView.setRowHeight(
                row,
                self.messageView.fontMetrics().height())
        self.messageView.resizeColumnsToContents()
        self.messageView.scrollToBottom()
class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        # main window dimensions
        self.main_width = 780
        self.main_height = 510
        self.main_fixed_height = 684
        self.default_command = config.default_ffmpeg_cmd

        self.fnames = list()  # list of file names to be converted
        self.docconv = False  # True when a documents conversion is running

        self.parse_cla()

        addQPB = QPushButton(self.tr('Add'))
        delQPB = QPushButton(self.tr('Delete'))
        clearQPB = QPushButton(self.tr('Clear'))
        vlayout1 = utils.add_to_layout('v', addQPB, delQPB, clearQPB, None)

        self.filesList = utils.FilesList()
        self.filesList.setSelectionMode(QAbstractItemView.ExtendedSelection)
        hlayout1 = utils.add_to_layout('h', self.filesList, vlayout1)

        outputQL = QLabel(self.tr('Output folder:'))
        self.toQLE = QLineEdit()
        self.toQLE.setReadOnly(True)
        self.toQTB = QToolButton()
        self.toQTB.setText('...')
        hlayout2 = utils.add_to_layout('h', outputQL, self.toQLE, self.toQTB)

        self.audiovideo_tab = AudioVideoTab(self)
        self.image_tab = ImageTab(self)
        self.document_tab = DocumentTab(self)

        self.tabs = [self.audiovideo_tab, self.image_tab, self.document_tab]
        tab_names = [self.tr('Audio/Video'), self.tr('Images'),
                     self.tr('Documents')]

        self.tabWidget = QTabWidget()
        for num, tab in enumerate(tab_names):
            self.tabWidget.addTab(self.tabs[num], tab)
        self.tabWidget.setCurrentIndex(0)

        self.origQCB = QCheckBox(
                self.tr('Save each file in the same\nfolder as input file'))
        self.deleteQCB = QCheckBox(self.tr('Delete original'))
        convertQPB = QPushButton(self.tr('&Convert'))

        hlayout3 = utils.add_to_layout('h', self.origQCB, self.deleteQCB, None)
        hlayout4 = utils.add_to_layout('h', None, convertQPB)
        final_layout = utils.add_to_layout(
                'v', hlayout1, self.tabWidget, hlayout2, hlayout3, hlayout4)

        self.dependenciesQL = QLabel()
        self.statusBar().addPermanentWidget(self.dependenciesQL, stretch=1)

        widget = QWidget()
        widget.setLayout(final_layout)
        self.setCentralWidget(widget)

        openAction = utils.create_action(
                self, self.tr('Open'), QKeySequence.Open, None,
                self.tr('Open a file'), self.add_files
                )
        convertAction = utils.create_action(
                self, self.tr('Convert'), 'Ctrl+C', None,
                self.tr('Convert files'), self.start_conversion
                )
        quitAction = utils.create_action(
                self, self.tr('Quit'), 'Ctrl+Q', None,
                self.tr('Quit'), self.close
                )
        edit_presetsAction = utils.create_action(
                self, self.tr('Edit Presets'), 'Ctrl+P', None,
                self.tr('Edit Presets'), self.presets
                )
        importAction = utils.create_action(
                self, self.tr('Import'), None, None,
                self.tr('Import presets'), self.import_presets
                )
        exportAction = utils.create_action(
                self, self.tr('Export'), None, None,
                self.tr('Export presets'), self.export_presets
                )
        resetAction = utils.create_action(
                self, self.tr('Reset'), None, None,
                self.tr('Reset presets'), self.reset_presets
                )
        syncAction = utils.create_action(
                self, self.tr('Synchronize'), None, None,
                self.tr('Synchronize presets'), self.sync_presets
                )
        removeoldAction = utils.create_action(
                self, self.tr('Remove old'), None, None,
                self.tr('Remove old presets'), self.removeold_presets
                )
        clearallAction = utils.create_action(
                self, self.tr('Clear All'), None, None,
                self.tr('Clear form'), self.clear_all
                )
        preferencesAction = utils.create_action(
                self, self.tr('Preferences'), 'Alt+Ctrl+P',
                None, self.tr('Preferences'), self.preferences
                )
        aboutAction = utils.create_action(
                self, self.tr('About'), 'Ctrl+?', None,
                self.tr('About'), self.about
                )

        fileMenu = self.menuBar().addMenu(self.tr('File'))
        editMenu = self.menuBar().addMenu(self.tr('Edit'))
        presetsMenu = self.menuBar().addMenu(self.tr('Presets'))
        helpMenu = self.menuBar().addMenu(self.tr('Help'))
        utils.add_actions(
                fileMenu, [openAction, convertAction, None, quitAction])
        utils.add_actions(
                presetsMenu,
                [edit_presetsAction, importAction, exportAction, resetAction,
                 None, syncAction, removeoldAction]
                )
        utils.add_actions(editMenu, [clearallAction, None, preferencesAction])
        utils.add_actions(helpMenu, [aboutAction])

        self.filesList.dropped.connect(self.url_dropped)
        addQPB.clicked.connect(self.add_files)
        delQPB.clicked.connect(self.delete_files)
        clearQPB.clicked.connect(self.clear_fileslist)
        self.tabWidget.currentChanged.connect(
                lambda: self.tabs[0].moreQPB.setChecked(False))
        self.origQCB.clicked.connect(
                lambda: self.toQLE.setEnabled(not self.origQCB.isChecked()))
        self.toQTB.clicked.connect(self.open_dir)
        convertQPB.clicked.connect(convertAction.triggered)

        del_shortcut = QShortcut(self)
        del_shortcut.setKey(Qt.Key_Delete)
        del_shortcut.activated.connect(self.delete_files)

        self.resize(self.main_width, self.main_height)
        self.setWindowTitle('FF Multi Converter')

        QTimer.singleShot(0, self.check_for_dependencies)
        QTimer.singleShot(0, self.load_settings)
        QTimer.singleShot(0, self.audiovideo_tab.set_default_command)
        QTimer.singleShot(0, self.update_filesList)

    def parse_cla(self):
        """Parse command line arguments."""
        for i in QCoreApplication.argv()[1:]:
            i = os.path.abspath(i)
            if os.path.isfile(i):
                self.fnames.append(i)
            else:
                print("ffmulticonverter: {0}: Not a file".format(i))

    def load_settings(self):
        """Load settings values."""
        def get_str_value(settings, name):
            value = settings.value(name)
            if value is not None:
                return value
            return ''

        settings = QSettings()
        self.overwrite_existing = utils.str_to_bool(
                get_str_value(settings, 'overwrite_existing'))
        self.avconv_prefered = utils.str_to_bool(
                get_str_value(settings, 'avconv_prefered'))
        self.default_output = get_str_value(settings, 'default_output')
        self.prefix = get_str_value(settings, 'prefix')
        self.suffix = get_str_value(settings, 'suffix')
        defcmd = get_str_value(settings, 'default_command')
        videocodecs = get_str_value(settings, 'videocodecs')
        audiocodecs = get_str_value(settings, 'audiocodecs')
        extraformats = get_str_value(settings, 'extraformats')

        if defcmd:
            self.default_command = defcmd

        self.toQLE.setText(self.default_output)
        self.audiovideo_tab.fill_video_comboboxes(
                videocodecs, audiocodecs, extraformats)

    def current_tab(self):
        """Return the corresponding object of the selected tab."""
        for i in self.tabs:
            if self.tabs.index(i) == self.tabWidget.currentIndex():
                return i

    def update_filesList(self):
        """Clear self.filesList and add to it all items of self.fname."""
        self.filesList.clear()
        for i in self.fnames:
            self.filesList.addItem(i)

    def url_dropped(self, links):
        """
        Append to self.fnames each file name that not already exists
        and update self.filesList.
        """
        for url in links:
            if os.path.isfile(url) and not url in self.fnames:
                self.fnames.append(url)
        self.update_filesList()

    def add_files(self):
        """
        Get file names using a standard Qt dialog.
        Append to self.fnames each file name that not already exists
        and update self.filesList.
        """
        # Create lists holding file formats extension.
        # To be passed in QFileDialog.getOpenFileNames().
        all_files = '*'
        audiovideo_files = ' '.join(
                ['*.'+i for i in self.audiovideo_tab.formats])
        img_formats = self.image_tab.formats[:]
        img_formats.extend(self.image_tab.extra_img)
        image_files = ' '.join(['*.'+i for i in img_formats])
        document_files = ' '.join(['*.'+i for i in self.document_tab.formats])
        formats = [all_files, audiovideo_files, image_files, document_files]
        strings = [self.tr('All Files'), self.tr('Audio/Video Files'),
                   self.tr('Image Files'), self.tr('Document Files')]

        filters = ''
        for string, extensions in zip(strings, formats):
            filters += string + ' ({0});;'.format(extensions)
        filters = filters[:-2] # remove last ';;'

        fnames = QFileDialog.getOpenFileNames(self, 'FF Multi Converter - ' +
                self.tr('Choose File'), config.home, filters)

        if fnames:
            for i in fnames:
                if not i in self.fnames:
                    self.fnames.append(i)
            self.update_filesList()

    def delete_files(self):
        """
        Get selectedItems of self.filesList, remove them from self.fnames and
        update the filesList.
        """
        items = self.filesList.selectedItems()
        if items:
            for i in items:
                self.fnames.remove(i.text())
            self.update_filesList()

    def clear_fileslist(self):
        """Make self.fnames empty and update self.filesList."""
        self.fnames = []
        self.update_filesList()

    def clear_all(self):
        """Clear all values of graphical widgets."""
        self.toQLE.clear()
        self.origQCB.setChecked(False)
        self.deleteQCB.setChecked(False)
        self.clear_fileslist()

        self.audiovideo_tab.clear()
        self.image_tab.clear()

    def open_dir(self):
        """
        Get a directory name using a standard QtDialog and update
        self.toQLE with dir's name.
        """
        if self.toQLE.isEnabled():
            output = QFileDialog.getExistingDirectory(
                    self, 'FF Multi Converter - ' +
                    self.tr('Choose output destination'),
                    config.home)
            if output:
                self.toQLE.setText(output)

    def preferences(self):
        """Open the preferences dialog."""
        dialog = preferences_dlg.Preferences(self)
        if dialog.exec_():
            self.load_settings()

    def presets(self):
        """Open the presets dialog."""
        dialog = presets_dlgs.ShowPresets(self)
        dialog.exec_()

    def import_presets(self):
        presets_dlgs.ShowPresets().import_presets()

    def export_presets(self):
        presets_dlgs.ShowPresets().export_presets()

    def reset_presets(self):
        presets_dlgs.ShowPresets().reset()

    def sync_presets(self):
        presets_dlgs.ShowPresets().synchronize()

    def removeold_presets(self):
        presets_dlgs.ShowPresets().remove_old()

    def ok_to_continue(self):
        """
        Check if everything is ok to continue with conversion.

        Check if:
        - At least one file has given for conversion.
        - An output folder has given.
        - Output folder exists.

        Return False if an error arises, else True.
        """
        try:
            if not self.fnames:
                raise ValidationError(
                        self.tr('You must add at least one file to convert!'))
            elif not self.origQCB.isChecked() and not self.toQLE.text():
                raise ValidationError(
                        self.tr('You must choose an output folder!'))
            elif (not self.origQCB.isChecked() and
                  not os.path.exists(self.toQLE.text())):
                raise ValidationError(self.tr('Output folder does not exists!'))
            if not self.current_tab().ok_to_continue():
                return False
            return True

        except ValidationError as e:
            QMessageBox.warning(
                    self, 'FF Multi Converter - ' + self.tr('Error!'), str(e))
            return False

    def output_ext(self):
        """Extract the desired output file extension from GUI and return it."""
        tab = self.current_tab()
        if tab.name == 'AudioVideo':
            ext_to = self.audiovideo_tab.extQCB.currentText()
        elif tab.name == 'Images':
            ext_to = tab.extQCB.currentText()
        else:
            ext_to = tab.convertQCB.currentText().split()[-1]

        return '.' + ext_to

    def start_conversion(self):
        """
        Extract the appropriate information from GUI and call the
        Progress dialog with the suitable argumens.
        """
        if not self.ok_to_continue():
            return

        ext_to = self.output_ext()
        _list = utils.create_paths_list(
                self.fnames, ext_to, self.prefix, self.suffix,
                self.toQLE.text(), self.origQCB.isChecked(),
                self.overwrite_existing
                )

        tab = self.current_tab()
        if tab.name == 'Documents':
            self.docconv = True

        dialog = progress.Progress(
                _list, tab, self.deleteQCB.isChecked(), self)
        dialog.show()

    def check_for_dependencies(self):
        """
        Check if each one of the program dependencies are installed and
        update self.dependenciesQL with the appropriate message.
        """
        self.ffmpeg = utils.is_installed('ffmpeg')
        self.avconv = utils.is_installed('avconv')
        self.unoconv = utils.is_installed('unoconv')
        self.imagemagick = utils.is_installed('convert')

        missing = []
        if not self.ffmpeg and not self.avconv:
            missing.append('ffmpeg/avconv')
        if not self.unoconv:
            missing.append('unoconv')
        if not self.imagemagick:
            missing.append('imagemagick')

        if missing:
            missing = ', '.join(missing)
            status = self.tr('Missing dependencies:') + ' ' + missing
            self.dependenciesQL.setText(status)

    def about(self):
        """Call the about dialog with the appropriate values."""
        msg = self.tr('Convert among several file types to other extensions')
        msg = textwrap.fill(msg, 54).replace('\n', '<br>')
        text = '''<b> FF Multi Converter {0} </b>
                 <p>{1}
                 <p><a href="{2}">FF Multi Converter - Home Page</a>
                 <p>Copyright &copy; 2011-2014 {3}
                 <br>License: {4}
                 <p>Python {5} - Qt {6} - PyQt {7} on {8}'''\
                 .format(ffmc.__version__, msg, ffmc.__url__, ffmc.__author__,
                         ffmc.__license__, platform.python_version()[:5],
                         QT_VERSION_STR, PYQT_VERSION_STR, platform.system())
        image = ':/ffmulticonverter.png'
        authors = '{0} <{1}>\n\n'.format(ffmc.__author__, ffmc.__author_email__)
        authors += 'Contributors:\nPanagiotis Mavrogiorgos'
        transl_list = [['[bg] Bulgarian', 'Vasil Blagoev'],
                       ['[cs] Czech', 'Petr Simacek'],
                       ['[de_DE] German (Germany)', 'Stefan Wilhelm'],
                       ['[el] Greek', 'Ilias Stamatis'],
                       ['[es] Spanish', 'Miguel Ángel Rodríguez Muíños'],
                       ['[fr] French', 'Rémi Mercier'
                                '\n     Lebarhon'],
                       ['[gl] Galician', 'Miguel Anxo Bouzada'],
                       ['[gl_ES] Galician (Spain)', 'Miguel Anxo Bouzada'],
                       ['[hu] Hungarian', 'Farkas Norbert'],
                       ['[it] Italian', 'Fabio Boccaletti'],
                       ['[ms_MY] Malay (Malaysia)', 'abuyop'],
                       ['[pl_PL] Polish (Poland)', 'Lukasz Koszy'
                                            '\n     Piotr Surdacki'],
                       ['[pt] Portuguese', 'Sérgio Marques'],
                       ['[pt_BR] Portuguese (Brasil)', 'José Humberto A Melo'],
                       ['[ro_RO] Romanian (Romania)', 'Angelescu Constantin'],
                       ['[ru] Russian', 'Andrew Lapshin'],
                       ['[tu] Turkish', 'Tayfun Kayha'],
                       ['[vi] Vietnamese', 'Anh Phan'],
                       ['[zh_CN] Chinese (China)', 'Dianjin Wang'],
                       ['[zh_TW] Chinese (Taiwan)', 'Taijuin Lee'],
                      ]
        translators = []
        for i in transl_list:
            translators.append('{0}\n     {1}'.format(i[0], i[1]))
        translators = '\n\n'.join(translators)

        dialog = about_dlg.AboutDialog(text, image, authors, translators, self)
        dialog.exec_()
예제 #41
0
class AudioVideoTab(QWidget):
    def __init__(self, parent):
        super(AudioVideoTab, self).__init__(parent)
        self.parent = parent
        self.name = 'AudioVideo'
        self.formats = ['3gp', 'aac', 'ac3', 'afc', 'aiff', 'amr', 'asf', 'au',
                        'avi', 'dvd', 'flac', 'flv', 'mka', 'mkv', 'mmf',
                        'mov', 'mp3', 'mp4', 'mpg', 'ogg', 'ogv', 'psp', 'rm',
                        'spx', 'vob', 'wav', 'webm', 'wma', 'wmv']
        self.extra_formats = ['aifc', 'm2t', 'm4a', 'm4v', 'mp2', 'mpeg',
                              'ra', 'ts']

        nochange = self.tr('No Change')
        frequency_values = [nochange, '22050', '44100', '48000']
        bitrate_values = [nochange, '32', '96', '112', '128', '160', '192',
                          '256', '320']
        pattern = QRegExp(r'^[1-9]\d*')
        validator = QRegExpValidator(pattern, self)

        converttoLabel = QLabel(self.tr('Convert to:'))
        self.extComboBox = QComboBox()
        self.extComboBox.addItems(self.formats + [self.tr('Other')])
        self.extComboBox.setMinimumWidth(130)
        self.extLineEdit = QLineEdit()
        self.extLineEdit.setMaximumWidth(85)
        self.extLineEdit.setEnabled(False)
        hlayout1 = pyqttools.add_to_layout(QHBoxLayout(), converttoLabel,
                                           None, self.extComboBox,
                                           self.extLineEdit)
        commandLabel = QLabel(self.tr('Command:'))
        self.commandLineEdit = QLineEdit()
        self.presetButton = QPushButton(self.tr('Preset'))
        self.defaultButton = QPushButton(self.tr('Default'))
        hlayout2 = pyqttools.add_to_layout(QHBoxLayout(), commandLabel,
                                       self.commandLineEdit, self.presetButton,
                                       self.defaultButton)

        sizeLabel = QLabel(self.tr('Video Size:'))
        aspectLabel = QLabel(self.tr('Aspect:'))
        frameLabel = QLabel(self.tr('Frame Rate (fps):'))
        bitrateLabel = QLabel(self.tr('Video Bitrate (kbps):'))

        self.widthLineEdit = pyqttools.create_LineEdit((50, 16777215),
                                                       validator, 4)
        self.heightLineEdit = pyqttools.create_LineEdit((50, 16777215),
                                                        validator,4)
        label = QLabel('x')
        layout1 = pyqttools.add_to_layout(QHBoxLayout(), self.widthLineEdit,
                                          label, self.heightLineEdit)
        self.aspect1LineEdit = pyqttools.create_LineEdit((35, 16777215),
                                                         validator,2)
        self.aspect2LineEdit = pyqttools.create_LineEdit((35, 16777215),
                                                         validator,2)
        label = QLabel(':')
        layout2 = pyqttools.add_to_layout(QHBoxLayout(), self.aspect1LineEdit,
                                          label, self.aspect2LineEdit)
        self.frameLineEdit = pyqttools.create_LineEdit(None, validator, 4)
        self.bitrateLineEdit = pyqttools.create_LineEdit(None, validator, 6)

        labels = [sizeLabel, aspectLabel, frameLabel, bitrateLabel]
        widgets = [layout1, layout2, self.frameLineEdit, self.bitrateLineEdit]

        videosettings_layout = QHBoxLayout()
        for a, b in zip(labels, widgets):
            text = a.text()
            a.setText('<html><p align="center">{0}</p></html>'.format(text))
            layout = pyqttools.add_to_layout(QVBoxLayout(), a, b)
            videosettings_layout.addLayout(layout)

        freqLabel = QLabel(self.tr('Frequency (Hz):'))
        chanLabel = QLabel(self.tr('Channels:'))
        bitrateLabel = QLabel(self.tr('Audio Bitrate (kbps):'))

        self.freqComboBox = QComboBox()
        self.freqComboBox.addItems(frequency_values)
        self.chan1RadioButton = QRadioButton('1')
        self.chan1RadioButton.setMaximumSize(QSize(51, 16777215))
        self.chan2RadioButton = QRadioButton('2')
        self.chan2RadioButton.setMaximumSize(QSize(51, 16777215))
        self.group = QButtonGroup()
        self.group.addButton(self.chan1RadioButton)
        self.group.addButton(self.chan2RadioButton)
        spcr1 = QSpacerItem(40, 20, QSizePolicy.Preferred, QSizePolicy.Minimum)
        spcr2 = QSpacerItem(40, 20, QSizePolicy.Preferred, QSizePolicy.Minimum)
        chanlayout = pyqttools.add_to_layout(QHBoxLayout(), spcr1,
                                             self.chan1RadioButton,
                                             self.chan2RadioButton, spcr2)
        self.audio_bitrateComboBox = QComboBox()
        self.audio_bitrateComboBox.addItems(bitrate_values)

        labels = [freqLabel, chanLabel, bitrateLabel]
        widgets = [self.freqComboBox, chanlayout, self.audio_bitrateComboBox]

        audiosettings_layout = QHBoxLayout()
        for a, b in zip(labels, widgets):
            text = a.text()
            a.setText('<html><p align="center">{0}</p></html>'.format(text))
            layout = pyqttools.add_to_layout(QVBoxLayout(), a, b)
            audiosettings_layout.addLayout(layout)

        hidden_layout = pyqttools.add_to_layout(QVBoxLayout(),
                                                videosettings_layout,
                                                audiosettings_layout)

        line = QFrame()
        line.setFrameShape(QFrame.HLine)
        line.setFrameShadow(QFrame.Sunken)
        self.moreButton = QPushButton(QApplication.translate('Tab', 'More'))
        self.moreButton.setSizePolicy(QSizePolicy(QSizePolicy.Fixed))
        self.moreButton.setCheckable(True)
        hlayout3 = pyqttools.add_to_layout(QHBoxLayout(), line, self.moreButton)

        self.frame = QFrame()
        self.frame.setLayout(hidden_layout)
        self.frame.hide()

        final_layout = pyqttools.add_to_layout(QVBoxLayout(), hlayout1,
                                               hlayout2, hlayout3, self.frame)
        self.setLayout(final_layout)


        self.presetButton.clicked.connect(self.choose_preset)
        self.defaultButton.clicked.connect(self.set_default_command)
        self.moreButton.toggled.connect(self.frame.setVisible)
        self.moreButton.toggled.connect(self.resize_parent)
        self.extComboBox.currentIndexChanged.connect(
                lambda: self.extLineEdit.setEnabled(
                self.extComboBox.currentIndex() == len(self.formats)))
        self.widthLineEdit.textChanged.connect(
                lambda: self.command_elements_change('size'))
        self.heightLineEdit.textChanged.connect(
                lambda: self.command_elements_change('size'))
        self.aspect1LineEdit.textChanged.connect(
                lambda: self.command_elements_change('aspect'))
        self.aspect2LineEdit.textChanged.connect(
                lambda: self.command_elements_change('aspect'))
        self.frameLineEdit.textChanged.connect(
                lambda: self.command_elements_change('frames'))
        self.bitrateLineEdit.textChanged.connect(
                lambda: self.command_elements_change('video_bitrate'))
        self.freqComboBox.currentIndexChanged.connect(
                lambda: self.command_elements_change('frequency'))
        self.audio_bitrateComboBox.currentIndexChanged.connect(
                lambda: self.command_elements_change('audio_bitrate'))
        self.chan1RadioButton.clicked.connect(
                lambda: self.command_elements_change('channels1'))
        self.chan2RadioButton.clicked.connect(
                lambda: self.command_elements_change('channels2'))

    def resize_parent(self):
        """Resize MainWindow."""
        height = MAIN_FIXED_HEIGHT if self.frame.isVisible() else MAIN_HEIGHT
        self.parent.setMinimumSize(MAIN_WIDTH, height)
        self.parent.resize(MAIN_WIDTH, height)

    def clear(self):
        """Clear all values of graphical widgets."""
        lines = [self.commandLineEdit, self.widthLineEdit, self.heightLineEdit,
                 self.aspect1LineEdit, self.aspect2LineEdit, self.frameLineEdit,
                 self.bitrateLineEdit, self.extLineEdit]
        for i in lines:
            i.clear()

        self.freqComboBox.setCurrentIndex(0)
        self.audio_bitrateComboBox.setCurrentIndex(0)
        self.group.setExclusive(False)
        self.chan1RadioButton.setChecked(False)
        self.chan2RadioButton.setChecked(False)
        self.group.setExclusive(True)
        # setExclusive(False) in order to be able to uncheck checkboxes and
        # then setExclusive(True) so only one radio button can be set

    def ok_to_continue(self):
        """
        Check if everything is ok with audiovideotab to continue conversion.

        Check if:
        - Either ffmpeg or avconv are installed.
        - Desired extension is valid.
        - self.commandLineEdit is empty.

        Return True if all tests pass, else False.
        """
        if not self.parent.ffmpeg and not self.parent.avconv:
            QMessageBox.warning(self, 'FF Multi Converter - ' + self.tr(
                'Error!'), self.tr('Neither ffmpeg nor avconv are installed.'
                '\nYou will not be able to convert audio/video files until you'
                ' install one of them.'))
            return False
        if self.extLineEdit.isEnabled():
            text = str(self.extLineEdit.text()).strip()
            if len(text.split()) != 1 or text[0] == '.':
                QMessageBox.warning(self, 'FF Multi Converter - ' + self.tr(
                    'Error!'), self.tr('Extension must be one word and must '
                    'not start with a dot.'))
                self.extLineEdit.selectAll()
                self.extLineEdit.setFocus()
                return False
        if not self.commandLineEdit.text():
            QMessageBox.warning(self, 'FF Multi Converter - ' + self.tr(
                  'Error!'), self.tr('The command LineEdit may not be empty.'))
            self.commandLineEdit.setFocus()
            return False
        return True

    def set_default_command(self):
        """Set the default value to self.commandLineEdit."""
        self.clear()
        self.commandLineEdit.setText(self.parent.default_command)

    def choose_preset(self):
        """
        Open the presets dialog and update self.commandLineEdit,
        self.extComboBox and self.extLineEdit with the appropriate values.
        """
        dialog = presets_dlgs.ShowPresets()
        if dialog.exec_() and dialog.the_command is not None:
            self.commandLineEdit.setText(dialog.the_command)
            self.commandLineEdit.home(False)
            find = self.extComboBox.findText(dialog.the_extension)
            if find >= 0:
                self.extComboBox.setCurrentIndex(find)
            else:
                self.extComboBox.setCurrentIndex(len(self.formats))
                self.extLineEdit.setText(dialog.the_extension)

    def remove_consecutive_spaces(self, string):
        """Remove any consecutive spaces from a string and return it."""
        temp = string
        string = ''
        for i in temp.split():
            if i:
                string += i + ' '
        return string[:-1]

    def command_elements_change(self, widget):
        """Fill self.commandLineEdit with the appropriate command parameters."""
        command = str(self.commandLineEdit.text())

        if widget == 'size':
            text1 = self.widthLineEdit.text()
            text2 = self.heightLineEdit.text()

            if (text1 or text2) and not (text1 and text2):
                return
            f = re.sub(r'^.*(-s\s+\d+x\d+).*$', r'\1', command)
            if re.match(r'^.*(-s\s+\d+x\d+).*$', f):
                command = command.replace(f, '').strip()
            if text1 and text2:
                command += ' -s {0}x{1}'.format(text1, text2)

        elif widget == 'aspect':
            text1 = self.aspect1LineEdit.text()
            text2 = self.aspect2LineEdit.text()

            if (text1 or text2) and not (text1 and text2):
                return
            f = re.sub(r'^.*(-aspect\s+\d+:\d+).*$', r'\1', command)
            if re.match(r'^.*(-aspect\s+\d+:\d+).*$', f):
                command = command.replace(f, '').strip()
            if text1 and text2:
                command += ' -aspect {0}:{1}'.format(text1, text2)

        elif widget == 'frames':
            text = self.frameLineEdit.text()
            f = re.sub(r'^.*(-r\s+\d+).*$', r'\1', command)
            if re.match(r'^.*(-r\s+\d+).*$', f):
                command = command.replace(f, '').strip()
            if text:
                command += ' -r {0}'.format(text)

        elif widget == 'video_bitrate':
            text = self.bitrateLineEdit.text()
            f = re.sub(r'^.*(-b\s+\d+k).*$', r'\1', command)
            if re.match(r'^.*(-b\s+\d+k).*$', f):
                command = command.replace(f, '')
            if text:
                command += ' -b {0}k'.format(text)
            command = command.replace('-sameq', '').strip()

        elif widget == 'frequency':
            text = self.freqComboBox.currentText()
            f = re.sub(r'^.*(-ar\s+\d+).*$', r'\1', command)
            if re.match(r'^.*(-ar\s+\d+).*$', f):
                command = command.replace(f, '').strip()
            if text != 'No Change':
                command += ' -ar {0}'.format(text)

        elif widget == 'audio_bitrate':
            text = self.audio_bitrateComboBox.currentText()
            f = re.sub(r'^.*(-ab\s+\d+k).*$', r'\1', command)
            if re.match(r'^.*(-ab\s+\d+k).*$', f):
                command = command.replace(f, '').strip()
            if text != 'No Change':
                command += ' -ab {0}k'.format(text)

        elif widget in ('channels1', 'channels2'):
            text = self.chan1RadioButton.text() if widget == 'channels1' \
                                            else self.chan2RadioButton.text()
            f = re.sub(r'^.*(-ac\s+\d+).*$', r'\1', command)
            if re.match(r'^.*(-ac\s+\d+).*$', f):
                command = command.replace(f, '').strip()
            command += ' -ac {0}'.format(text)

        self.commandLineEdit.clear()
        self.commandLineEdit.setText(self.remove_consecutive_spaces(command))
예제 #42
0
class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        self.home = os.getenv('HOME')
        self.fnames = list()  # list of file names to be converted
        self.docconv = False  # True when a documents conversion is running

        # parse command line arguments
        for i in QCoreApplication.argv()[1:]:
            i = codecs.utf_8_decode(os.path.abspath(i))[0]
            if os.path.isfile(i):
                self.fnames.append(i)
            else:
                print("ffmulticonverter: {0}: Not a file".format(i))

        addButton = QPushButton(self.tr('Add'))
        delButton = QPushButton(self.tr('Delete'))
        clearButton = QPushButton(self.tr('Clear'))
        vlayout1 = pyqttools.add_to_layout(QVBoxLayout(), addButton, delButton,
                                           clearButton, None)

        self.filesList = FilesList()
        self.filesList.setSelectionMode(QAbstractItemView.ExtendedSelection)
        hlayout1 = pyqttools.add_to_layout(QHBoxLayout(), self.filesList,
                                           vlayout1)

        output_label = QLabel(self.tr('Output folder:'))
        self.toLineEdit = QLineEdit()
        self.toLineEdit.setReadOnly(True)
        self.toToolButton = QToolButton()
        self.toToolButton.setText('...')
        hlayout2 = pyqttools.add_to_layout(QHBoxLayout(), output_label,
                                           self.toLineEdit, self.toToolButton)

        self.audiovideo_tab = AudioVideoTab(self)
        self.image_tab = ImageTab(self)
        self.document_tab = DocumentTab(self)

        self.tabs = [self.audiovideo_tab, self.image_tab, self.document_tab]
        tab_names = [self.tr('Audio/Video'), self.tr('Images'),
                     self.tr('Documents')]
        self.TabWidget = QTabWidget()
        for num, tab in enumerate(tab_names):
            self.TabWidget.addTab(self.tabs[num], tab)
        self.TabWidget.setCurrentIndex(0)

        self.origCheckBox = QCheckBox(
                   self.tr('Save each file in the same\nfolder as input file'))
        self.deleteCheckBox = QCheckBox(self.tr('Delete original'))
        self.convertPushButton = QPushButton(self.tr('&Convert'))

        hlayout3 = pyqttools.add_to_layout(QHBoxLayout(), self.origCheckBox,
                                           self.deleteCheckBox, None)
        hlayout4 = pyqttools.add_to_layout(QHBoxLayout(), None,
                                          self.convertPushButton)
        final_layout = pyqttools.add_to_layout(QVBoxLayout(), hlayout1,
                                               self.TabWidget, hlayout2,
                                               hlayout3, hlayout4)

        self.statusBar = self.statusBar()
        self.dependenciesLabel = QLabel()
        self.statusBar.addPermanentWidget(self.dependenciesLabel, stretch=1)

        Widget = QWidget()
        Widget.setLayout(final_layout)
        self.setCentralWidget(Widget)

        c_act = pyqttools.create_action
        openAction = c_act(self, self.tr('Open'), QKeySequence.Open, None,
                           self.tr('Open a file'), self.add_files)
        convertAction = c_act(self, self.tr('Convert'), 'Ctrl+C', None,
                              self.tr('Convert files'), self.start_conversion)
        quitAction = c_act(self, self.tr('Quit'), 'Ctrl+Q', None,
                           self.tr('Quit'), self.close)
        edit_presetsAction = c_act(self, self.tr('Edit Presets'), 'Ctrl+P',
                                   None, self.tr('Edit Presets'), self.presets)
        importAction = c_act(self, self.tr('Import'), None, None,
                             self.tr('Import presets'), self.import_presets)
        exportAction = c_act(self, self.tr('Export'), None, None,
                             self.tr('Export presets'), self.export_presets)
        resetAction = c_act(self, self.tr('Reset'), None, None,
                            self.tr('Reset presets'), self.reset_presets)
        syncAction = c_act(self, self.tr('Synchronize'), None, None,
                                  self.tr('Synchronize presets'),
                                  self.sync_presets)
        removeoldAction = c_act(self, self.tr('Remove old'), None, None,
                                self.tr('Remove old presets'),
                                self.removeold_presets)
        clearallAction = c_act(self, self.tr('Clear All'), None, None,
                               self.tr('Clear form'), self.clear_all)
        preferencesAction = c_act(self, self.tr('Preferences'), 'Alt+Ctrl+P',
                                  None, self.tr('Preferences'), self.preferences)
        aboutAction = c_act(self, self.tr('About'), 'Ctrl+?', None,
                            self.tr('About'), self.about)

        fileMenu = self.menuBar().addMenu(self.tr('File'))
        editMenu = self.menuBar().addMenu(self.tr('Edit'))
        presetsMenu = self.menuBar().addMenu(self.tr('Presets'))
        helpMenu = self.menuBar().addMenu(self.tr('Help'))
        pyqttools.add_actions(fileMenu,
                              [openAction, convertAction, None, quitAction])
        pyqttools.add_actions(presetsMenu, [edit_presetsAction, importAction,
                                            exportAction, resetAction, None,
                                            syncAction, removeoldAction])
        pyqttools.add_actions(editMenu,
                              [clearallAction, None, preferencesAction])
        pyqttools.add_actions(helpMenu, [aboutAction])

        self.filesList.dropped.connect(self.url_dropped)
        addButton.clicked.connect(self.add_files)
        delButton.clicked.connect(self.delete_files)
        clearButton.clicked.connect(self.clear_fileslist)
        self.TabWidget.currentChanged.connect(lambda:
                                     self.tabs[0].moreButton.setChecked(False))
        self.origCheckBox.clicked.connect(lambda:
                 self.toLineEdit.setEnabled(not self.origCheckBox.isChecked()))
        self.toToolButton.clicked.connect(self.open_dir)
        self.convertPushButton.clicked.connect(convertAction.triggered)

        del_shortcut = QShortcut(self)
        del_shortcut.setKey(Qt.Key_Delete)
        del_shortcut.activated.connect(self.delete_files)

        self.resize(MAIN_WIDTH, MAIN_HEIGHT)
        self.setWindowTitle('FF Multi Converter')

        QTimer.singleShot(0, self.check_for_dependencies)
        QTimer.singleShot(0, self.load_settings)
        QTimer.singleShot(0, self.audiovideo_tab.set_default_command)
        QTimer.singleShot(0, self.update_filesList)

    def load_settings(self):
        """Load settings values."""
        settings = QSettings()
        self.overwrite_existing = settings.value('overwrite_existing').toBool()
        self.default_output = unicode(
                                   settings.value('default_output').toString())
        self.prefix = unicode(settings.value('prefix').toString())
        self.suffix = unicode(settings.value('suffix').toString())
        self.avconv_prefered = settings.value('avconv_prefered').toBool()
        self.default_command = unicode(
                                  settings.value('default_command').toString())
        if not self.default_command:
            self.default_command = DEFAULT_COMMAND

        self.toLineEdit.setText(self.default_output)

    def current_tab(self):
        """Return the corresponding object of the selected tab."""
        for i in self.tabs:
            if self.tabs.index(i) == self.TabWidget.currentIndex():
                return i

    def update_filesList(self):
        """Clear self.filesList and add to it all items of self.fname."""
        self.filesList.clear()
        for i in self.fnames:
            self.filesList.addItem(i)

    def url_dropped(self, links):
        """
        Append to self.fnames each file name that not already exists
        and update self.filesList.
        """
        for url in links:
            if os.path.isfile(url) and not url in self.fnames:
                self.fnames.append(url)
        self.update_filesList()

    def add_files(self):
        """
        Get file names using a standard Qt dialog.
        Append to self.fnames each file name that not already exists
        and update self.filesList.
        """
        # Create lists holding file formats extension.
        # To be passed in QFileDialog.getOpenFileNames().
        all_files = '*'
        audiovideo_files = ' '.join(
                                 ['*.'+i for i in self.audiovideo_tab.formats])
        img_formats = self.image_tab.formats[:]
        img_formats.extend(self.image_tab.extra_img)
        image_files = ' '.join(['*.'+i for i in img_formats])
        document_files = ' '.join(['*.'+i for i in self.document_tab.formats])
        formats = [all_files, audiovideo_files, image_files, document_files]
        strings = [self.tr('All Files'), self.tr('Audio/Video Files'),
                   self.tr('Image Files'), self.tr('Document Files')]

        filters = ''
        for string, extensions in zip(strings, formats):
            filters += string + ' ({0});;'.format(extensions)
        filters = filters[:-2] # remove last ';;'

        fnames = QFileDialog.getOpenFileNames(self, 'FF Multi Converter - ' +
                                    self.tr('Choose File'), self.home, filters)

        if fnames:
            for i in fnames:
                if not i in self.fnames:
                    self.fnames.append(unicode(i))
            self.update_filesList()

    def delete_files(self):
        """
        Get selectedItems of self.filesList, remove them from self.fnames and
        update the filesList.
        """
        items = self.filesList.selectedItems()
        if items:
            for i in items:
                self.fnames.remove(unicode(i.text()))
            self.update_filesList()

    def clear_fileslist(self):
        """Make self.fnames empty and update self.filesList."""
        self.fnames = []
        self.update_filesList()

    def clear_all(self):
        """Clear all values of graphical widgets."""
        self.toLineEdit.clear()
        self.origCheckBox.setChecked(False)
        self.deleteCheckBox.setChecked(False)
        self.clear_fileslist()

        self.audiovideo_tab.clear()
        self.image_tab.clear()

    def open_dir(self):
        """
        Get a directory name using a standard QtDialog and update
        self.toLineEdit with dir's name.
        """
        if self.toLineEdit.isEnabled():
            output = QFileDialog.getExistingDirectory(self,
                'FF Multi Converter - ' + self.tr('Choose output destination'),
                self.home)
            #output = unicode(output)
            if output:
                self.toLineEdit.setText(output)

    def preferences(self):
        """Open the preferences dialog."""
        dialog = preferences_dlg.Preferences(self)
        if dialog.exec_():
            self.load_settings()

    def presets(self):
        """Open the presets dialog."""
        dialog = presets_dlgs.ShowPresets(self)
        dialog.exec_()

    def import_presets(self):
        presets_dlgs.ShowPresets().import_presets()

    def export_presets(self):
        presets_dlgs.ShowPresets().export_presets()

    def reset_presets(self):
        presets_dlgs.ShowPresets().reset()

    def sync_presets(self):
        presets_dlgs.ShowPresets().synchronize()

    def removeold_presets(self):
        presets_dlgs.ShowPresets().remove_old()

    def ok_to_continue(self):
        """
        Check if everything is ok to continue with conversion.

        Check if:
        - At least one file has given for conversion.
        - An output folder has given.
        - Output folder exists.

        Return False if an error arises, else True.
        """
        try:
            if not self.fnames:
                raise ValidationError(self.tr(
                                 'You must add at least one file to convert!'))
            elif not self.origCheckBox.isChecked() and not self.toLineEdit.text():
                raise ValidationError(self.tr(
                                      'You must choose an output folder!'))
            elif (not self.origCheckBox.isChecked() and
                  not os.path.exists(unicode(self.toLineEdit.text()))):
                raise ValidationError(self.tr('Output folder does not exists!'))
            if not self.current_tab().ok_to_continue():
                return False
            return True

        except ValidationError as e:
            QMessageBox.warning(self, 'FF Multi Converter - ' + \
                                self.tr('Error!'), unicode(e))
            return False

    def output_ext(self):
        """Extract the desired output file extension from GUI and return it."""
        tab = self.current_tab()
        if tab.name == 'AudioVideo':
            if self.audiovideo_tab.extLineEdit.isEnabled():
                ext_to = self.audiovideo_tab.extLineEdit.text()
            else:
                ext_to = self.audiovideo_tab.extComboBox.currentText()
        elif tab.name == 'Images':
            ext_to = tab.extComboBox.currentText()
        else:
            ext_to = str(tab.convertComboBox.currentText()).split()[-1]

        return str('.' + ext_to)

    def create_paths_list(self, files_list, ext_to, prefix, suffix, output,
                          orig_dir, overwrite_existing):
        """
        Keyword arguments:
        files_list -- list with files to be converted
        ext_to     -- the extension to which each file must be converted to
        prefix     -- string that will be added as a prefix to all filenames
        suffix     -- string that will be added as a suffix to all filenames
        output     -- the output folder
        orig_dir   -- if True, each file will be saved at its original directory
                      else, files will be saved at output
        overwrite_existing -- if False, a '~' will be added as prefix to
                              filenames

        Create and return a list with dicts.
        Each dict will have only one key and one corresponding value.
        Key will be a file to be converted and it's value will be the name
        of the new converted file.

        Example list:
        [{"/foo/bar.png" : "/foo/bar.bmp"}, {"/f/bar2.png" : "/f/bar2.bmp"}]
        """
        assert ext_to.startswith('.'), 'ext_to must start with a dot (.)'

        conversion_list = []
        dummy = []

        for _file in files_list:
            _dir, name = os.path.split(_file)
            y = prefix + os.path.splitext(name)[0] + suffix + ext_to

            if orig_dir:
                y = _dir + '/' + y
            else:
                y = output + '/' + y

            if not overwrite_existing:
                while os.path.exists(y) or y in dummy:
                    _dir2, _name2 = os.path.split(y)
                    y = _dir2 + '/~' + _name2

            dummy.append(y)
            # Add quotations to paths in order to avoid error in special
            # cases such as spaces or special characters.
            _file = '"' + _file + '"'
            y = '"' + y + '"'

            _dict = {}
            _dict[_file] = y
            conversion_list.append(_dict)

        return conversion_list

    def start_conversion(self):
        """
        Extract the appropriate information from GUI and call the
        Progress dialog with the suitable argumens.
        """
        if not self.ok_to_continue():
            return

        ext_to = self.output_ext()
        _list = self.create_paths_list(self.fnames, ext_to,
                                       self.prefix, self.suffix,
                                       unicode(self.toLineEdit.text()),
                                       self.origCheckBox.isChecked(),
                                       self.overwrite_existing)

        tab = self.current_tab()
        cmd = ''
        size = str('')
        mntaspect = False

        if tab.name == 'AudioVideo':
            cmd = tab.commandLineEdit.text()
        elif tab.name == 'Images':
            width = tab.widthLineEdit.text()
            if width:
                height = tab.heightLineEdit.text()
                size = str('{0}x{1}'.format(width, height))
                mntaspect = tab.aspectCheckBox.isChecked()
        else:
            self.docconv = True

        dialog = progress.Progress(_list, tab.name, cmd,
                                   not self.avconv_prefered, size, mntaspect,
                                   self.deleteCheckBox.isChecked(), self)
        dialog.show()

    def is_installed(self, program):
        """Return True if program appears in user's PATH var, else False."""
        for path in os.getenv('PATH').split(os.pathsep):
            fpath = os.path.join(path, program)
            if os.path.exists(fpath) and os.access(fpath, os.X_OK):
                return True
        return False

    def check_for_dependencies(self):
        """
        Check if each one of the program dependencies are installed and
        update self.dependenciesLabel with the appropriate message.
        """
        self.ffmpeg = self.is_installed('ffmpeg')
        self.avconv = self.is_installed('avconv')
        self.unoconv = self.is_installed('unoconv')
        self.pmagick = True
        try:
            # We tried to import PythonMagick earlier.
            # If that raises an error it means that PythonMagick is not
            # available on the system.
            PythonMagick
        except NameError:
            self.pmagick = False

        missing = []
        if not self.ffmpeg and not self.avconv:
            missing.append('FFmpeg/avconv')
        if not self.unoconv:
            missing.append('unoconv')
        if not self.pmagick:
            missing.append('PythonMagick')

        if missing:
            missing = ', '.join(missing)
            status = self.tr('Missing dependencies:') + ' ' + missing
            self.dependenciesLabel.setText(status)

    def about(self):
        """Call the about dialog with the appropriate values."""
        link = 'http://sites.google.com/site/ffmulticonverter/'
        msg = self.tr('Convert among several file types to other extensions')
        if len(msg) > 54:
            # break line if msg is too long to fit the window
            nmsg = ''
            for n, w in enumerate(msg.split(' ')):
                if len(nmsg) > 54:
                    break
                nmsg += w + ' '
            nmsg += '<br>' + msg[len(nmsg):]
            msg = nmsg
        text = '''<b> FF Multi Converter {0} </b>
                 <p>{1}
                 <p><a href="{2}">FF Multi Converter - Home Page</a>
                 <p>Copyright &copy; 2011-2013 Ilias Stamatis
                 <br>License: GNU GPL3
                 <p>Python {3} - Qt {4} - PyQt {5} on {6}'''\
                 .format(__version__, msg, link, platform.python_version()[:5],
                         QT_VERSION_STR, PYQT_VERSION_STR, platform.system())
        image = ':/ffmulticonverter.png'
        authors = 'Ilias Stamatis <*****@*****.**>\n\n'
        authors += 'Contributors:\nPanagiotis Mavrogiorgos'
        transl_list = [['[bg] Bulgarian', 'Vasil Blagoev'],
                       ['[cs] Czech', 'Petr Simacek'],
                       ['[de_DE] German (Germany)', 'Stefan Wilhelm'],
                       ['[el] Greek', 'Ilias Stamatis'],
                       ['[fr] French', 'Rémi Mercier'
                                '\n     Lebarhon'],
                       ['[hu] Hungarian', 'Farkas Norbert'],
                       ['[it] Italian', 'Fabio Boccaletti'],
                       ['[pl_PL] Polish (Poland)', 'Lukasz Koszy'
                                            '\n     Piotr Surdacki'],
                       ['[pt] Portuguese', 'Sérgio Marques'],
                       ['[pt_BR] Portuguese (Brasil)', 'José Humberto A Melo'],
                       ['[ru] Russian', 'Andrew Lapshin'],
                       ['[tu] Turkish', 'Tayfun Kayha'],
                       ['[zh_CN] Chinese (China)', 'Dianjin Wang']]
        translators = ''
        for i in transl_list:
            translators += '{0}\n     {1}\n\n'.format(i[0], i[1])
        translators = translators[:-2]

        dialog = about_dlg.AboutDialog(text, image, authors, translators, self)
        dialog.exec_()
예제 #43
0
class MyForm(QWidget):
    def __init__(self):
        QWidget.__init__(self)
        # setGeometry(x_pos, y_pos, width, height)
        self.setGeometry(100, 150, 500, 460)
        self.readSettings()
        self.setWindowTitle(APPNAME + ' ' + VERSION + " - " + self.chanells_path  )
        self.icon_path = get_icon_resource(imgdata_png_main)
#        self.icon_path = os.path.join(os.path.dirname(sys.argv[0]), 'chanchan.ico')
        self.icon = QIcon(self.icon_path)
        self.setWindowIcon(self.icon)
        self.chanells = None
        self.chanells_all = None
        self.num_channels = 0

        # the player subprocess process
        self.proc = None
        self.proc_sopcast = None
        self.is_sopcast = False
        self.is_playlist = False
        self.on_top = False
        self.cache_size = CACHE_SIZE_DEFAULT

        if not self.haveSeenFirstTime:
            copy_default_playlist()
            self.haveSeenFirstTime = True
            # saving settings should be done in closeEvent() instead!
#            settings = QSettings(QSettings.IniFormat, QSettings.UserScope, "xh", "chanchan")
#            settings.setValue("seen_first_time", QVariant(self.haveSeenFirstTime))
#            settings.sync()            

        # use a grid layout for the widgets
        grid = QGridLayout()

        # bind the button click to a function reference
        # new connect style, needs PyQt 4.5+
        ###btn_load.clicked.connect(self.load_channels_data)

        btn_play = QPushButton("&Play")
        btn_play.setToolTip("Click to play selected stream")

        btn_play.clicked.connect(self.on_button_play)
        btn_kill = QPushButton("&Stop")
        btn_kill.setToolTip("Click to stop current player")
        btn_kill.clicked.connect(self.kill_proc)

        self.listbox = QListWidget()
        # new connect style, needs PyQt 4.5+
        self.listbox.clicked.connect(self.on_select)

        self.listbox.doubleClicked.connect(self.on_double_click)

        # attach right-click handler
        self.listbox.setContextMenuPolicy(Qt.ActionsContextMenu)
        #self.listbox.setContextMenuPolicy(Qt.CustomContextMenu)
        #http://talk.maemo.org/showthread.php?t=64034
        self.actionCopyUrl = QAction("Copy URL", self.listbox)
        self.connect(self.actionCopyUrl, SIGNAL("triggered()"), self.copy_to_clipboard)
        self.actionPlay = QAction("Play", self.listbox)
        self.actionPlay.setShortcut("Ctrl+P")
        self.actionRestartPlayer = QAction("Restart SopPlayer", self.listbox)
        self.actionReloadChannels = QAction("Reload List", self.listbox)
        self.actionEditChannels = QAction("Edit Playlist", self.listbox)
        self.actionEditChannels.setShortcut("Ctrl+E")
        self.actionOpenChannelsFile = QAction("Open Playlist File", self.listbox)
        self.actionEditSource = QAction("Edit Source", self.listbox)
        self.actionAbout = QAction("About %s" % APPNAME, self.listbox)
        self.actionQuit = QAction("Quit", self)
        self.actionQuit.setShortcut("Ctrl+Q")
        self.search = QLineEdit()

        self.connect(self.search, SIGNAL("textChanged(QString)"), self.on_search_text_change)

        # clear button
        self.clear_button = QToolButton()
        self.clear_button.setIcon(get_icon_resource(imgdata_png_clear))
        self.clear_button.setIconSize(QSize(16, 16))
        self.clear_button.setCursor(Qt.ArrowCursor)
        self.clear_button.setAutoRaise(True)
        self.clear_button.setEnabled(False)
#        self.main_layout.addWidget(self.clear_button)
        self.connect(self.clear_button, SIGNAL("clicked()"), self.clear_search_text)

        self.listbox.addAction(self.actionPlay)
        self.listbox.addAction(self.actionRestartPlayer)
        self.listbox.addAction(self.actionCopyUrl)
        self.listbox.addAction(self.actionOpenChannelsFile)
        self.listbox.addAction(self.actionReloadChannels)
        self.listbox.addAction(self.actionEditChannels)
        self.listbox.addAction(self.actionEditSource)
        self.listbox.addAction(self.actionAbout)
        self.addAction(self.actionQuit)

        self.connect(self.actionPlay, SIGNAL("triggered()"), self.on_double_click)
        self.connect(self.actionRestartPlayer, SIGNAL("triggered()"), self.restart_sopplayer)
        self.connect(self.actionReloadChannels, SIGNAL("triggered()"), lambda: self.load_channels_data(self.chanells_path))
        self.connect(self.actionEditChannels, SIGNAL("triggered()"), lambda: self.edit_file(str(self.chanells_path)))
        self.connect(self.actionOpenChannelsFile, SIGNAL("triggered()"), lambda: self.load_channels_data())
        self.connect(self.actionEditSource, SIGNAL("triggered()"), lambda: self.edit_file(path=sys.argv[0], editor=EDITOR))
        self.connect(self.actionQuit, SIGNAL("triggered()"), self.close)
        self.connect(self.actionAbout, SIGNAL("triggered()"), lambda: QMessageBox.about(self, 'About %s' % APPNAME,
'''


<h4>%s version %s</h4>
<p>
Created by <i>%s</i></p>

<p><a href="mailto:%s">%s</a></p>
<p><a href="%s">chanchantv.googlecode.com</a></p>
''' % (APPNAME, VERSION, AUTHOR, EMAIL.decode('base64'), EMAIL, WEB)) #  warning(self, APPNAME, 'No playlist selected')
)


#        self.listbox.connect(self.listbox, SIGNAL("customContextMenuRequested(QPoint)"),
#                             self.on_right_click)

#        self.txtChanInfo = QLineEdit()
#        self.txtChanInfo.setReadOnly(True)

#        self.logWindow = QTextEdit()
#        self.logWindow.setSizePolicyx(QSizePolicy.)
        self.status = QLabel()
        self.status.setText('channels')
        # ADD BEVELED BORDER::self.status.setFrameStyle(QFrame.Panel | QFrame.Sunken)

        self.groupBox = QGroupBox("Engine")
        sizePolicy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.groupBox.sizePolicy().hasHeightForWidth())
        self.groupBox.setSizePolicy(sizePolicy)
#        self.groupBox.setAutoFillBackground(True)

        self.rbMplayer = QRadioButton('&Mplayer', self.groupBox)
        self.rbMplayer.setChecked(True)
        self.rbMplayer.setToolTip("Play with Mplayer")
        #self.rbGstreamer = QRadioButton('gst&123', self.groupBox)
        self.rbVlc = QRadioButton('&Vlc', self.groupBox)
        self.rbVlc.setToolTip("Play with VLC")
        self.rbTotem = QRadioButton('&Totem', self.groupBox)
        self.rbTotem.setToolTip("Play with Totem")
        self.rbBrowser = QRadioButton('&Browser', self.groupBox)
        self.rbBrowser.setToolTip("Open URL in web browser")
        self.hBoxTop = QHBoxLayout()
        self.hBoxTop.addWidget(self.rbMplayer)
        #self.hBoxTop.addWidget(self.rbGstreamer)
        self.hBoxTop.addWidget(self.rbVlc)
        self.hBoxTop.addWidget(self.rbTotem)
        self.hBoxTop.addWidget(self.rbBrowser)
        self.groupBox.setLayout(self.hBoxTop)

        self.cbPlaylistFlag = QCheckBox('Playlist')
        self.cbPlaylistFlag.setToolTip('Resource is a M3U, ASX or PLS playlist')

        self.cbFullScreen = QCheckBox('Full Screen')
        self.cbFullScreen.setToolTip('Start video in full screen')
        self.cbFullScreen.setChecked(self.is_full_screen)
        self.cbInhibitScreensaver = QCheckBox('Inhibit Screensaver')
        self.cbInhibitScreensaver.setToolTip('Disable screensaver while playing stream')
        self.cbInhibitScreensaver.setChecked(self.is_inhibit_screen)
#        addWidget(widget, row, column, rowSpan, columnSpan)
        grid.addWidget(self.groupBox, 0, 0, 1, 3)
        grid.addWidget(btn_play, 0, 4, 1, 1)
        grid.addWidget(btn_kill, 0, 5, 1, 1)
        grid.addWidget(self.search, 1, 0, 1, 4)
        grid.addWidget(self.clear_button, 1, 3, 1, 1)
        grid.addWidget(self.status, 1, 5, 1, 1)
        # listbox spans over 5 rows and 2 columns
        grid.addWidget(self.listbox, 2, 0, 5, 6)
        ## BAD grid.addWidget(self.hBoxFlags, 6, 0, 1, 1)
        grid.addWidget(self.cbPlaylistFlag, 7, 0, 1, 1)
        grid.addWidget(self.cbFullScreen, 7, 1, 1, 1)
        grid.addWidget(self.cbInhibitScreensaver, 7, 2, 1, 1)
#        grid.addWidget(self.txtChanInfo, 7, 0, 1, 6)
#        grid.addWidget(self.logWindow, 8, 0, 1, 6)
        self.setLayout(grid)
        self.search.setFocus()
        self.load_channels_data(self.chanells_path)

    def clear_search_text(self):
        print '------clear-search-text---------'
        self.search.clear()

    def on_search_text_change(self):
        if not self.chanells_all:  # only need to do this once
            self.chanells_all = list(self.chanells)
        text = str(self.search.text()).strip()

        print 'DBG', len(text), len(self.chanells_all)

        if len(text) > 1:
            self.clear_button.setEnabled(True)
            filtered_list = self.get_matching_items(text.lower(), self.chanells_all)
            if len(filtered_list):
                self.chanells = filtered_list
            else:
                self.chanells = []
        else:
            self.chanells = list(self.chanells_all)
            self.clear_button.setEnabled(False)
        self.load_channels_data(None, False)

    def get_matching_items(self, needle, haystack):
        'search for a substring in channel list'
        matches = []
        found_in_meta = False
        last_meta_item = None

        for ch in haystack:
            is_meta = ch.startswith('#')
            if is_meta and not needle in ch.lower():
                last_meta_item = ch
            if needle in ch.lower():
                if is_meta:
                    found_in_meta = True
                elif not found_in_meta and last_meta_item not in matches:
                    matches.append(last_meta_item)
                matches.append(ch)
            elif found_in_meta:
                if not is_meta:
                    matches.append(ch)
                else:
                    found_in_meta = False
        return matches

    def closeEvent(self, event):
        self.writeSettings()
        print 'closeEvent: Saving settings and exiting...'
        return
        quit_msg = "Are you sure you want to exit the program?"
        reply = QMessageBox.question(self, 'Message',
                                           quit_msg, QMessageBox.Yes, QMessageBox.No)

        if reply == QMessageBox.Yes:
            self.writeSettings()
            event.accept()
            QApplication.instance().quit()
        else:
            event.ignore()

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Escape:
            self.search.setFocus()
            self.search.selectAll()

    def copy_to_clipboard(self):
        clipboard = QApplication.clipboard()
        clipboard.setText(self.listbox.currentItem().text())

    def load_channels_data(self, new_path=None, read_from_file=True):
        MediaItem.num_items = 0
        if read_from_file:
            if not new_path:
                new_path = str(self.get_new_filename())
                if not new_path:
    #                QMessageBox.warning(self, APPNAME, 'No playlist selected')
                    return

            try:
                fh = codecs.open(new_path, 'r', 'utf8')
                self.chanells = [ch.strip() for ch in fh.readlines()]
            except Exception as e:
                show_gui_error(e, 'File not found', 'Error opening playlist "%s" \n\n%s' % (new_path, str(e)))
                return

            self.chanells_path = new_path
            self.chanells = [ch.strip() for ch in self.chanells]
            self.chanells_all = None
        self.listbox.clear()
        current_params = None

        for chan in self.chanells:
            if not len(chan) or chan.strip() == '#EXTM3U':
                continue
            item = MediaItem(chan, self.icon)
            if item.is_meta:
                '''if a metadata line, then store and apply to all the following
                non-metadata items
                '''
                current_params = item.params
            elif current_params:
                item.params = current_params

            item.setStatusTip(chan)
            self.listbox.addItem(item)
        self.setWindowTitle(APPNAME + ' ' + VERSION + ' - ' + self.chanells_path)
        self.status.setText(str(MediaItem.num_items) + ' channels')

    def edit_file(self, path, editor=EDITOR):
        if ' ' in editor:
            editor = editor.split(' ')
        subprocess.Popen([editor, path])

    def get_new_filename(self):
        return QFileDialog.getOpenFileName(self,
                       'Load Playlist file',
                       '',
                       "Playlist files (*.m3u);;All Files (*.*);")

    def on_button_play(self):
#        self.on_select()
        self.play_media()

    def on_select(self):
        """an item in the listbox has been clicked/selected"""
        current_item = self.listbox.currentItem()
        if not current_item:
            return
        current_channel = current_item and str(current_item.text()) or '<no channel>'
        self.is_playlist = current_channel[-4:].lower() in ['.m3u', '.asx', '.pls']

#        if current_channel.startswith('sop:'):
            #self.rbMplayer.setChecked(True)
#            self.cache_size = '1024'

        if current_item.params:
            'set params for current channel according to metadata line'
            myparams = current_item.params.keys()

            if 'player' in myparams:
                player = current_item.params['player'].lower()
                if player == 'totem':
                    self.rbTotem.setChecked(True)
                elif player == MPLAYER:
                    self.rbMplayer.setChecked(True)
                #elif player == 'gst123':
                #    self.rbGstreamer.setChecked(True)
                elif player == VLC:
                    self.rbVlc.setChecked(True)
                elif player in ('browser', 'web'):
                    self.rbBrowser.setChecked(True)

            if 'playlist' in myparams or 'pl' in myparams:
                self.is_playlist = current_item.params['playlist'].lower() in GOOD_VALUES

            if 'fullscreen' in myparams or 'fs' in myparams:
                self.is_full_screen = current_item.params['fullscreen'].lower() in GOOD_VALUES
            else:
                self.is_full_screen = IS_FULLSCREEN_DEFAULT

            if 'ontop' in myparams or 'top' in myparams:
                self.on_top = current_item.params['top'].lower() in GOOD_VALUES
            else:
                self.on_top = IS_ON_TOP_DEFAULT

            if 'cache' in myparams:
                self.cache_size = current_item.params['cache']
            else:
                self.cache_size = CACHE_SIZE_DEFAULT
                
            if 'exec' in myparams or 'shell' in myparams:
                # set shell options: console or no console
                self.exec_shell_command = current_item.params['exec']
#
#            if 'exec' in myparams:
#                self.executable_name = current_item.params['exec']


            self.cbPlaylistFlag.setChecked(self.is_playlist)
            
            # only setting True state
            if self.is_full_screen:
                self.cbFullScreen.setChecked(True)

    def on_double_click(self):
        self.play_media()
        """an item in the listbox has been double-clicked"""

    def restart_sopplayer(self):
        # if self.rbVlc.isChecked():
            # if vlc_remote_command('testing if vlc remote is running...'):
            #     vlc_remote_command('add %s' % SOPCAST_SERVER_URL)
            #     vlc_remote_command('volume 200')
        # else:
        self.play_media(start_sopcast_server=False)

    def play_media(self, start_sopcast_server=True):
        current_item = self.listbox.currentItem()
        if not current_item:
            return
        current_channel = str(current_item.text())

        if self.proc and self.proc.pid:
            self.kill_proc()

        args = []

        if self.cbInhibitScreensaver.isChecked():
            suspend_screensaver()

        ################ RUN SHELL COMMAND #############
        if 'exec' in current_item.params:
            show_console = current_item.params['exec'].lower() == 'console'
            if show_console:
                args += ['xterm', '-geometry', '45x8-20+400', '-e']
                args += [current_channel.strip()]
                self.proc = subprocess.Popen(args, stdout=subprocess.PIPE)
                print 'DBG:', self.proc
            else:
                args.insert(0, current_item.params['exec'])
                args += [current_channel.strip()]
                self.proc = subprocess.Popen(args, shell=True)
            return

        # don't use xterm for vlc, totem
        if (self.rbMplayer.isChecked()):
            if not is_win32 and not is_osx:
                args += ['xterm', '-geometry', '45x8-20+150', '-e']

        self.is_sopcast = current_channel.lower().startswith('sop://')

        if self.is_sopcast:
            if start_sopcast_server:
                # args_sopcast = ['xterm', '-geometry', '45x8-20+400', '-e', sopcast_binary, current_channel, SOPCAST_LISTEN_PORT, SOPCAST_SERVER_PORT]
                try:
                    print 'Waiting for sopcast server starup at %s ...' % current_channel
                    self.proc_sopcast = run_command_in_new_terminal(
                        sopcast_binary,
                        current_channel,
                        SOPCAST_LISTEN_PORT,
                        SOPCAST_SERVER_PORT)
                        #
                except Exception as e:
                    show_gui_error(e, """ERROR! Sopcast executable not found or other error:

To install sopcast support on Linux, run:

%s""" % (SOPCAST_INSTALL_HOWTO))
                    return

            current_channel = SOPCAST_SERVER_URL
            time.sleep(SOPCAST_SERVER_WAIT_SECS)

        if self.rbMplayer.isChecked():

            if is_win32:
                args = ['cmd', '/c', MPLAYER_PATH_WIN32, '-cache-min', CACHE_SIZE_MIN, '-cache', self.cache_size]
            else:
                args += [MPLAYER, '-cache-min', CACHE_SIZE_MIN, '-cache', self.cache_size]

            self.on_top and args.append('-ontop')
            self.cbFullScreen.isChecked() and args.append('-fs')
            self.cbPlaylistFlag.isChecked() and args.append('-playlist')

        #elif self.rbGstreamer.isChecked():
        #    args.append('gst123')
        #    if '.m3u' in current_channel:
        #        current_channel = getFirstUrl(current_channel)

        elif self.rbVlc.isChecked():
            if is_win32:
                if os.path.exists(VLC_PATH_WIN32):
                    args = [VLC_PATH_WIN32]
                elif os.path.exists(VLC_PATH_WIN32_CUSTOM):
                    args = [VLC_PATH_WIN32_CUSTOM]
            elif is_osx:
                args = [VLC_PATH_OSX]#, '--one-instance']
            else:
                args = ['vlc']#, '--one-instance']
            # if vlc_remote_command('testing if vlc remote is running...'):
            #     # print 'VLC Remote Control not running, starting new VLC instance...'
            #     vlc_remote_command('add %s' % current_channel)
            #     vlc_remote_command('volume 150')
            #     return
            # else:
            #     print 'VLC Remote Control not running, starting new VLC instance...'
            self.cbFullScreen.isChecked() and args.append('--fullscreen')
            args.append('--video-on-top')

        elif self.rbTotem.isChecked():
            args += ['totem', '--replace']
            # FIXME!!! totem segfaults when started with the --fullscreen switch
#            self.cbFullScreen.isChecked() and args.append('--fullscreen')

        elif self.rbBrowser.isChecked():
            open_webbrowser(current_channel)
            return

        args.append(current_channel)

        print args

        try:
            if is_win32:
                #self.proc = subprocess.Popen(args, creationflags=subprocess.STARTF_USESHOWWINDOW, cwd=os.path.dirname(sys.argv[0]))

## TODO: get right options on win32
#http://stackoverflow.com/questions/7006238/how-do-i-hide-the-console-when-i-use-os-system-or-subprocess-call
#startupinfo = subprocess.STARTUPINFO()
#startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
#subprocess.call('taskkill /F /IM exename.exe', startupinfo=startupinfo)

                self.proc = subprocess.Popen(args, shell=True, cwd=os.path.dirname(sys.argv[0]))
            else:
                self.proc = subprocess.Popen(args, stdout=subprocess.PIPE, stdin=subprocess.PIPE)
                print 'DBG:', type(self.proc), self.proc
#                console_data = self.proc.stdout.read()
#                self.logWindow.setText(console_data)


        except Exception as e:
            show_gui_error(e, "ERROR! Selected player not available:\n")

    def kill_proc(self):
        if self.cbInhibitScreensaver.isChecked():
            resume_screensaver()
        if self.proc and not self.rbVlc.isChecked():
            try:
                self.proc.kill()
            except:
                pass
        if self.is_sopcast and self.proc_sopcast:
            try:
                self.proc_sopcast.kill()
                os.system('killall sopcast')
            except:
                pass

    def readSettings(self):
        # store settings object
        self.settings = QSettings(QSettings.IniFormat, QSettings.UserScope, "xh", "chanchan")
        pos = self.settings.value("pos", QVariant(QPoint(200, 200))).toPoint()
        size = self.settings.value("size", QVariant(QSize(400, 400))).toSize()
        self.resize(size)
        self.move(pos)
        self.chanells_path = self.settings.contains('channels_file') and str(self.settings.value("channels_file").toString()) or get_default_channels_path()
        self.is_inhibit_screen = self.settings.contains('inhibit_screen') and self.settings.value("inhibit_screen").toBool()
        self.is_full_screen = self.settings.contains('fullscreen') and self.settings.value("fullscreen").toBool()
        self.haveSeenFirstTime = self.settings.contains('seen_first_time') and self.settings.value("seen_first_time").toBool()

    def writeSettings(self):
        settings = QSettings(QSettings.IniFormat, QSettings.UserScope, "xh", "chanchan")
        settings.setValue("pos", QVariant(self.pos()))
        settings.setValue("size", QVariant(self.size()))
        settings.setValue("channels_file", QVariant(self.chanells_path))
        settings.setValue("inhibit_screen", QVariant(self.cbInhibitScreensaver.isChecked()))
        settings.setValue("fullscreen", QVariant(self.cbFullScreen.isChecked()))
        settings.setValue("seen_first_time", QVariant(self.haveSeenFirstTime))
        settings.sync()
예제 #44
0
class AddWordWidget(QDialog):

    def __init__(self, parent=None):
        super(AddWordWidget, self).__init__(parent=parent)
        self.setWindowTitle('Add word')

        self.create_layout()
        self.create_connections()

    def create_layout(self):
        hbox = QHBoxLayout()

        vbox = QVBoxLayout()
        vbox.addWidget(QLabel("Dictionary"))
        vbox.addWidget(QLabel("Original"))
        vbox.addWidget(QLabel("Translation"))
        vbox.addWidget(QLabel("Phoneme"))
        vbox.addWidget(QLabel("Parts of Speech"))
        vbox.addWidget(QLabel("Synonyms"))
        vbox.addWidget(QLabel("Antonyms"))
        hbox.addLayout(vbox)

        vbox = QVBoxLayout()

        self.dictionaries = Dictionary.objects.all()
        self.dictionary = QComboBox()
        self.dictionary.addItems([d.name for d in self.dictionaries])
        vbox.addWidget(self.dictionary)

        self.original = QLineEdit()
        vbox.addWidget(self.original)

        self.translation = QLineEdit()
        vbox.addWidget(self.translation)

        self.phoneme = QLineEdit()
        vbox.addWidget(self.phoneme)

        self.pos = QComboBox()
        self.pos.addItems([p.strip() for p in
                           self.dictionaries[0].pos.split(',') if len(p) > 0])
        vbox.addWidget(self.pos)

        self.synonyms = QLineEdit()
        vbox.addWidget(self.synonyms)

        self.antonyms = QLineEdit()
        vbox.addWidget(self.antonyms)

        hbox.addLayout(vbox)

        vbox = QVBoxLayout()
        vbox.addLayout(hbox)

        vbox.addWidget(QLabel("Description"))
        self.description = QTextEdit()
        vbox.addWidget(self.description)

        self.add_button = QPushButton("&Add")
        self.close_button = QPushButton("&Close")
        hbox = QHBoxLayout()
        hbox.addStretch()
        hbox.addWidget(self.add_button)
        hbox.addWidget(self.close_button)
        vbox.addLayout(hbox)

        self.status = QLabel('Add a new word to a dictionary.')
        vbox.addWidget(self.status)

        self.setLayout(vbox)

    def create_connections(self):
        self.connect(self.dictionary, SIGNAL("currentIndexChanged(int)"),
                     self.change_pos)
        self.connect(self.close_button, SIGNAL("clicked()"), self.close)
        self.connect(self.add_button, SIGNAL("clicked()"), self.add_word)

    def change_pos(self, index):
        current_dict = self.dictionaries[index]
        self.pos.clear()
        self.pos.addItems([p.strip() for p in
                           current_dict.pos.split(',') if len(p) > 0])

    def get_texts(self):
        current_dict = self.dictionaries[self.dictionary.currentIndex()].abbrev
        original = unicode(self.original.text()).strip()
        translation = unicode(self.translation.text()).strip()
        phoneme = unicode(self.phoneme.text()).strip()
        pos = unicode(self.pos.currentText()).strip()
        synonyms = unicode(self.synonyms.text()).strip()
        antonyms = unicode(self.antonyms.text()).strip()
        description = unicode(self.description.toPlainText()).strip()

        if not all([original, translation, pos]):
            self.status.setText('There was an error inserting the word. Please'
                                ' try again.')
            QMessageBox.critical(self, "Error", "You must enter at least "
                                 "'Original', 'Translation' and 'Parts of "
                                 "Speech'.")
            return None

        return dict(dictionary=current_dict, original=original,
                    translation=translation, phoneme=phoneme, pos=pos,
                    synonyms=synonyms, antonyms=antonyms,
                    description=description)

    def clear_texts(self):
        self.translation.clear()
        self.phoneme.clear()
        self.synonyms.clear()
        self.antonyms.clear()
        self.description.clear()

        self.original.setFocus()

    def add_word(self):
        self.status.clear()

        texts = self.get_texts()
        if not texts:
            return

        word = Word(**texts)
        word.save()

        self.clear_texts()
        self.status.setText('Word %s has been added successfully.' %
                            word.original)
        self.words_widget.load_words()

    def save_word(self):
        self.status.clear()

        texts = self.get_texts()
        if not texts:
            return

        word = self.word
        word.dictionary = texts['dictionary']
        word.original = texts['original']
        word.translation = texts['translation']
        word.phoneme = texts['phoneme']
        word.pos = texts['pos']
        word.synonyms = texts['synonyms']
        word.antonyms = texts['antonyms']
        word.description = texts['description']
        word.save()

        self.status.setText('Word %s has been saved successfully' %
                            word.original)
        self.words_widget.load_words()

    def get_word(self):
        return self._word

    def set_word(self, word):
        self._word = word
        self.setWindowTitle("Edit %s" % word.original)
        self.add_button.setText("&Save")
        self.disconnect(self.add_button, SIGNAL("clicked()"), self.add_word)

        if word.exported:
            self.add_button.setEnabled(False)
            self.status.setText('This word has been exported already. '
                                'You cannot save the changes to it.')
        else:
            self.connect(self.add_button, SIGNAL("clicked()"), self.save_word)
            self.status.setText('Edit this word and save to your dictionary.')

        for i, d in enumerate(self.dictionaries):
            if d.abbrev == word.dictionary:
                self.dictionary.setCurrentIndex(i)
                break

        self.original.setText(word.original)
        self.translation.setText(word. translation)
        self.phoneme.setText(word.phoneme)
        self.synonyms.setText(word.synonyms)
        self.antonyms.setText(word.antonyms)
        self.description.setText(word.description)

        for i in range(self.pos.count()):
            if self.pos.itemText(i) == word.pos:
                self.pos.setCurrentIndex(i)
                break

    word = property(get_word, set_word)
예제 #45
0
class TagCompleterWidget(QObject):
    """
    widget in lineEdit-style with integrated qcompleter
    """ 
    def __init__(self, max_tags, expiry_prefix=None, tag_list=None, parent=None, separator=",", show_datestamp=False):
        
        QWidget.__init__(self, parent)
        
        self.__completer_active = False
        self.__max_tags = max_tags
        self.__tag_separator = separator
        self.__tag_list = tag_list
        self.__parent = parent
        self.__tag_line = QLineEdit(self.__parent)
        #self.__tag_line = TagLineEdit(self.__parent)
        self.__show_datestamp = show_datestamp
        self.__datestamp_format = TsConstants.DATESTAMP_FORMAT_DAY
        self.__expiry_prefix = expiry_prefix
        
        ## flag, if the line should be checked of emptiness
        self.__check_not_empty = False
        self.__check_tag_limit = False
        
        self.__restricted_vocabulary = False
        
        ## the latest activated suggestion 
        self.__activated_text = None
        # value of the actual datestamp
        self.__datestamp = None
        self.__datestamp_hidden = False
        
        self.__completer = QCompleter(self.__tag_list, self);
        self.__completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.__completer.setWidget(self.__tag_line)
        
        #self.__handle_datestamp()
        
        self.connect(self.__tag_line, SIGNAL("textChanged(QString)"), self.__text_changed_by_user)
        self.connect(self.__completer, SIGNAL("activated(QString)"), self.__text_activated)
        self.connect(self.__completer, SIGNAL("highlighted(QString)"), self.__text_highlighted)

    def __text_highlighted(self, item_name):
        """
        a suggestion has been selected in the dropdownbox
        """
        # set this variable to True just to know, that 
        # this value comes from the completer and not from the user 
        self.__completer_active = True
        self.__text_selected(item_name)
        self.__completer_active = False

    def __handle_datestamp(self, is_hidden):
        """
        if the show_datestamp flag is set to True, provide an automatic datestamp on the tagline 
        """
        if self.__show_datestamp:
            self.__datestamp = time.strftime(self.__datestamp_format)
            if not is_hidden:
                self.__tag_line.clear()
                self.__tag_line.setText(self.__datestamp)

    def set_datestamp_format(self, format, is_hidden):
        self.__datestamp_format = format
        self.__datestamp_hidden = is_hidden
        self.__handle_datestamp(is_hidden)
    
    def show_datestamp(self, show):
        self.__show_datestamp = show
        self.__handle_datestamp(show)

    def clear_line(self):
        """
        clear the tagline ... 
        if auto datestamp is set to "on" a fresh stamp will be placed into the tagline 
        """
        self.__tag_line.clear()
        if self.__show_datestamp:
            self.__handle_datestamp(self.__datestamp_hidden)
    def set_check_not_empty(self, check_necessary):
        """
        set this to True, if there should be sent a signal that indicates 
        that the tagline is not empty anymore 
        """
        self.__check_not_empty = True
    
    def set_restricted_vocabulary(self, is_restricted):
        """
        use True/False to turn the restricted function on/off
        """
        self.__restricted_vocabulary = is_restricted
    
    def select_line(self):
        """
        select the tagline ... 
        """
        self.__tag_line.selectAll()
        self.__tag_line.setFocus(QtCore.Qt.OtherFocusReason)

    def __text_changed_by_user(self, text):
        # create a QByteArray in utf8
        all_text = text.toUtf8()
        # make a python string out of it
        all_text = str(all_text)
        # convert the python string tu unicode utf-8
        all_text = unicode(all_text, "utf-8")
        if self.__check_not_empty:
            if all_text is not None and all_text != "":
                self.emit(QtCore.SIGNAL("line_empty"), False)
            else:
                self.emit(QtCore.SIGNAL("line_empty"), True)
        
        text = all_text[:self.__tag_line.cursorPosition()]
        
        ## remove whitespace and filter out duplicates by using a set
        tag_set = set([])
        for tag in all_text.split(self.__tag_separator):
            strip_tag = tag.strip()
            if strip_tag != "":
                tag_set.add(strip_tag)
        max_tags = self.__max_tags
        if self.__datestamp_hidden:
            max_tags = max_tags - 1;
        ## do not proceed if the max tag count is reached
        if len(tag_set) > max_tags:
            self.emit(QtCore.SIGNAL("tag_limit_reached"), True)
            self.__check_tag_limit = True
            return
        else:
            if self.__check_tag_limit:
                self.emit(QtCore.SIGNAL("tag_limit_reached"), False)
                self.__check_tag_limit = False
        
        prefix = text.split(self.__tag_separator)[-1].strip()
        if not self.__completer_active:
            self.__update_completer(tag_set, prefix)
    
    def __update_completer(self, tag_set, completion_prefix):
        if self.__tag_list is None:
            return
        tags = list(set(self.__tag_list).difference(tag_set))
        #tags = list(self.__tag_list)

        model = QStringListModel(tags, self)
        self.__completer.setModel(model)
        self.__completer.setCompletionPrefix(completion_prefix)
        
        if self.__restricted_vocabulary:
            self.__check_vocabulary(tag_set, completion_prefix)
            
        if completion_prefix.strip() != '':
            ## use the default completion algorithm
            self.__completer.complete()
    
    def __check_finished_tags(self, typed_tags_list):
        """
        use this method to control all typed tags. this means all tags terminated with a comma 
        """
        pass

    def __check_in_completion_list(self, tag):
        """
        if a written tag equals a tag of the completion list - the tag will be removed from the completion list
        so the completer will return a completion count of 0 for this tag.
        in this case there would be displayed an error message at the dialog (when controlled vocab is activated)
        so check manually, if the provided tag is contained in the suggestion_list
        """
        #for sug_tag in self.__tag_list:
        #    if sug_tag == tag:
        #        return True
        #return False
        return tag in self.__tag_list
    
    def __check_vocabulary(self, tag_set, completion_prefix):
        """
        have a look at the entered tag to be completed.
        if restricted vocabulary is turned on:
        datestamps do not have to be checked. 
        """
        
        not_allowed_tags_count = 0
        no_completion_found = False
        stripped_text = unicode(self.__tag_line.text()).strip()
        ##when a tag separator is on the last position, there should have been entered a new tag
        ##check this tag for its correctness
        if len(stripped_text) > 0:
            ##check if all written tags are allowed (incl. datestamps an expiry tags)
            for tag in tag_set:
                ## tag can be a datestamp -> OK
                if not SpecialCharHelper.is_datestamp(tag) and tag != "":
                    ## tag can be an expiry tag -> OK
#                    if self.__expiry_prefix is not None and not SpecialCharHelper.is_expiry_tag(self.__expiry_prefix, tag):
                    if self.__expiry_prefix is None or not SpecialCharHelper.is_partial_expiry_tag(self.__expiry_prefix, tag):
                        if unicode(tag) not in self.__tag_list:
                            not_allowed_tags_count += 1
                         
        if(completion_prefix.strip() == ""):
            ## if the prefix is an empty string - manually set the completion_count to 0
            ## because the completer would return the whole number of tags in its suggestion list
            completion_count = 0
        else:   
            completion_count = self.__completer.completionCount()
                            
        if self.__restricted_vocabulary and completion_count == 0:
            ## additionally check if the prefix equals a tag from the suggestion list
            ## this has to be done, because we do not get a completionCount > 0 if the prefix equals a given tag 
            #if completion_prefix not in self.__tag_list:
            if completion_prefix is not None and len(completion_prefix) > 0 and completion_prefix.strip() != "":
                ## just send the signal if the tag is no datestamp AND if it is no full tag
                if not SpecialCharHelper.is_datestamp(completion_prefix) and not self.__check_in_completion_list(completion_prefix):
                    if not SpecialCharHelper.is_partial_expiry_tag(self.__expiry_prefix, completion_prefix):
                        no_completion_found = True

        ## there are tags (terminated with comma) which are not in the allowed tag_list 
        if not_allowed_tags_count > 1:
            self.emit(QtCore.SIGNAL("no_completion_found"), True)
            return
            
            
        if not_allowed_tags_count > 0:
            ## in this case the user has entered a not allowed tag and terminated it with a comma to mark it as a tag
            ## the completion count is 0 because there is nothing after the last comma in the taglist 
            if completion_count == 0:
                self.emit(QtCore.SIGNAL("no_completion_found"), True)
                return
            ## it could be the case, that the user is still typing an allowed tag
            ## so check, if the completer has a possible completion
            ## if not -> send the signal 
            if no_completion_found:
                self.emit(QtCore.SIGNAL("no_completion_found"), True)
                return
        ## everytime there is no completion found, emit the signal
        elif no_completion_found:
            self.emit(QtCore.SIGNAL("no_completion_found"), True)
            return
        ## in this case everything is fine
        self.emit(QtCore.SIGNAL("no_completion_found"), False)
    
    def __text_selected(self, text):
        self.__activated_text = text
        
        cursor_pos = self.__tag_line.cursorPosition()
        before_text = unicode(self.__tag_line.text())[:cursor_pos]
        #after_text = unicode(self.__tag_line.text())[cursor_pos:]
        prefix_len = len(before_text.split(self.__tag_separator)[-1].strip())

        self.__tag_line.setText("%s%s" % (before_text[:cursor_pos - prefix_len], text))
        self.__tag_line.setCursorPosition(cursor_pos - prefix_len + len(text) + 2)
        
    def __text_activated(self, text):
        """
        a suggestion has been choosen by the user
        """
        self.__text_selected(text)
        self.emit(QtCore.SIGNAL("activated"))

    def get_tag_list(self):
        tag_string = unicode(self.__tag_line.text())
        result = set([])
        tag_list = tag_string.split(self.__tag_separator)
        for tag in tag_list:
            strip_tag = tag.strip()
            if strip_tag != "":
                result.add(strip_tag)
        # if the datestamp is hidden, add it manually to the taglist
        if self.__datestamp_hidden:
            result.add(self.__datestamp)
        return result
    
    def get_tag_line(self):
        return self.__tag_line
    
    def get_completer(self):
        return self.__completer
    
    def set_enabled(self, enable):
        self.__tag_line.setEnabled(enable)
        
    def set_text(self, text):
        self.__tag_line.setText(text)
    
    def set_tag_completion_list(self, tag_list):
        self.__tag_list = tag_list
        self.__completer.setModel(QtGui.QStringListModel(QtCore.QStringList(tag_list)))
        
    def get_tag_completion_list(self):
        return self.__tag_list

    def is_empty(self):
        if self.__tag_line.text() == "":
            return True
        else:
            return False
    
    def set_place_holder_text(self, text):
        self.__tag_line.setPlaceholderText(text)
예제 #46
0
파일: tt2.py 프로젝트: ThePsyjo/myTools
class MainWindow(QMainWindow):
	def __init__(self):
		QMainWindow.__init__(self)
		
		self.sync_delay = 5
		self.sync_active = False
		self.verbose = False

		self.timePattern = re.compile('\.[0-9]+$')
		
		self.setWindowTitle('%s %s' % (QApplication.applicationName(), QApplication.applicationVersion()));
		
		self.widget = QWidget()
		self.setCentralWidget(self.widget)

		self.statusBar = QStatusBar(self)
		self.setStatusBar(self.statusBar)

		self.mAction = self.menuBar().addMenu(self.tr("&Action"))
		#self.mAction.addAction(self.tr("&update"), self.updateTplTable(), QKeySequence('F5'))
		self.mAction.addAction(self.tr('&import records'), self.onImport, QKeySequence('F6'))
		self.mAction.addAction(self.tr('edit &settings'), self.onSettings, QKeySequence('F8'))
		self.mAction.addAction(self.tr("e&xit"), self.onExit, 'Ctrl+Q')

		self.mAbout = self.menuBar().addMenu(self.tr("&about"))
		self.mAbout.addAction(QApplication.applicationName(), self.onAboutAppAction)
		self.mAbout.addAction("Qt", self.onAboutQtAction)
		
		self.pageForwardButton = QPushButton(self)
		self.pageForwardButton.setText('>')
		self.connect(self.pageForwardButton, SIGNAL('clicked()'), self.pageForward)

		self.pageBackwardButton = QPushButton(self)
		self.pageBackwardButton.setText('<')
		self.connect(self.pageBackwardButton, SIGNAL('clicked()'), self.pageBackward)
		
		self.timer = QTimer(self)
		self.timer.setInterval(1000)
		self.connect(self.timer, SIGNAL('timeout()'), self, SLOT('onTimer()'))
		self.time_begin = datetime.now()
		self.time_end = datetime.now()

		self.db_path = os.path.join(os.path.dirname(sys.argv[0]) if os.name != 'posix' else os.path.expanduser('~'), '.tt2.db')
		self.db = sqlite3.connect(self.db_path)
		self.cursor = self.db.cursor()
		
		try:
			self.cursor.execute('SELECT id FROM tt LIMIT 1')
		except:
			self.createDb()
		
		self.settings = self.fetchSettings()
		self.syncer = Syncer(self.db_path, self)
		self.connect( self.syncer, SIGNAL('active'), self.setSyncerActive )
		self.connect( self.syncer, SIGNAL('message'), self.msg )
		self.connect( self.syncer, SIGNAL('newSettings'), self.fetchSettings )
		
		self.layout = QGridLayout(self.widget)
		
		self.descriptionLabel = QLabel(self.widget)
		self.descriptionLabel.setText('Beschreibung')
		self.descriptionLabel.setMaximumHeight( self.font().pointSize() * 2 )
		self.descriptionInput = QLineEdit(self.widget)
		self.updateDescriptionEditCompleter()				
		self.noteLabel = QLabel(self.widget)
		self.noteLabel.setText('Notiz')
		self.noteLabel.setMaximumHeight( self.font().pointSize() * 2 )
		self.noteInput = QLineEdit(self.widget)
		self.startStopButton = QPushButton(self.widget)
		self.startStopButton.setText('Start')
		
		self.tableView = TplTable(self, int( self.getSetting('displayrows', DEFAULTROWS) ) )

		self.pageForwardAction = QAction(self)
		self.pageForwardAction.setShortcut(QKeySequence('Right'))
		self.connect(self.pageForwardAction, SIGNAL('triggered()'), self.pageForward);
		self.pageForwardButton.addAction(self.pageForwardAction)

		self.pageBackwardAction = QAction(self)
		self.pageBackwardAction.setShortcut(QKeySequence('Left'))
		self.connect(self.pageBackwardAction, SIGNAL('triggered()'), self.pageBackward);
		self.pageBackwardButton.addAction(self.pageBackwardAction)

		self.updateTplTable()
			
		self.layout.addWidget(self.descriptionLabel, 0, 0, 1, 1)
		self.layout.addWidget(self.descriptionInput, 1, 0, 1, 1)
		self.layout.addWidget(self.noteLabel, 0, 1, 1, 1)
		self.layout.addWidget(self.noteInput, 1, 1, 1, 1)
		self.layout.addWidget(self.startStopButton, 2, 0, 1, 2)
		self.layout.addWidget(self.tableView, 3,0,1,2)
		self.layout.addWidget(self.pageBackwardButton, 4, 0, 1, 1)
		self.layout.addWidget(self.pageForwardButton, 4, 1, 1, 1)

		self.connect(self.descriptionInput, SIGNAL('returnPressed ()'), self.onStartStop )
		self.connect(self.noteInput, SIGNAL('returnPressed ()'), self.onStartStop )
		self.connect(self.startStopButton, SIGNAL('clicked()'), self.onStartStop )
		self.connect(self.tableView, SIGNAL('valueChanged(int)'), self.onValueChanged )
		self.connect(self.tableView, SIGNAL('del(int)'), self.onDelete )

		self.last_sync = datetime.now()
		self.sync()
	
	def __del__(self):
		pass

	def setSyncerActive(self, active):
		if not active:
			self.last_sync = datetime.now()
		self.sync_active = active

	def msg(self, msg, timeout = 0):
		#print(msg)
		self.statusBar.showMessage(msg, timeout)

	def sync(self):
		if self.getSetting('syncEnabled','False') == 'False':
			return

		# reset delay if still active
		if self.sync_active:
			self.last_sync = datetime.now()

		if datetime.now() < ( self.last_sync + timedelta( seconds = self.sync_delay ) ):
			try:
				#print 'cancel'
				self.t.cancel()
			except:
				pass
			#print 'start +',( self.last_sync + timedelta( seconds = self.sync_delay ) - datetime.now() ).seconds + 1
			self.t = Timer( ( self.last_sync + timedelta( seconds = self.sync_delay ) - datetime.now() ).seconds + 1 ,self.sync)
			self.t.start()
		else:
		#	print 'start syncer instance'
			Thread(target=self.syncer.do_sync).start()


	def createDb(self):
		try:
			self.q('''CREATE TABLE tt (
			id INTEGER PRIMARY KEY AUTOINCREMENT,
			remote_id INTEGER,
			time_begin INTEGER,
			time_end INTEGER,
			description STRING,
			note STRING DEFAULT "",
			is_new INTEGER DEFAULT 1,
			need_update INTEGER DEFAULT 0,
			is_delete INTEGER DEFAULT 0
			)''')
			self.q('''CREATE TABLE settings (
			key STRING UNIQUE,
			value STRING
			)''')
			self.q('CREATE INDEX idx_time_begin ON tt (time_begin)')
		except:
			self.statusBar.showMessage('error creating Database!')
		else:
			self.statusBar.showMessage('Table tt created successfully')
			
	def q(self, query):
		try:
			self.cursor.execute(query)
		except Exception as e:
			print( e )
			self.statusBar.showMessage('query execution failed "%s"' % query)
		else:
			self.db.commit()
	
	def updateTplTable(self):
		self.q('SELECT id,time_begin,time_end,description,note FROM tt WHERE is_delete != 1 ORDER BY time_begin DESC LIMIT %d' % ( int( self.getSetting( 'displayrows', DEFAULTROWS ) ) ) )
		self.tableView.set(self.cursor.fetchall())
		
	def updateDescriptionEditCompleter(self):
		self.q('SELECT DISTINCT description FROM tt WHERE is_delete != 1')
		#words = QStringList()
		words = []
		for word in self.cursor.fetchall():
			words.append(str(word[0]))
		self.descriptionInput.setCompleter(QCompleter(words, self))

	@pyqtSlot()
	def pageForward(self):
		self.q('SELECT MIN(time_begin) FROM tt')
		if not self.tableView.getLastTime() == self.cursor.fetchone()[0]:
			sql = 'SELECT id,time_begin,time_end,description,note FROM tt WHERE is_delete != 1 AND time_begin < %d ORDER BY time_begin DESC LIMIT %s' % ( self.tableView.getLastTime(), int( self.getSetting( 'displayrows', DEFAULTROWS ) ) )
			if self.verbose:
				print( sql )
			self.q( sql )
			self.tableView.set(self.cursor.fetchall())

	@pyqtSlot()
	def pageBackward(self):
		self.q('SELECT MAX(time_begin) FROM tt')
		if not self.tableView.getFirstTime() == self.cursor.fetchone()[0]:
			sql = 'SELECT * FROM ( SELECT id,time_begin,time_end,description,note FROM tt WHERE is_delete != 1 AND time_begin > %d ORDER BY time_begin LIMIT %s ) as tbl ORDER BY time_begin DESC' % ( self.tableView.getFirstTime(), int( self.getSetting( 'displayrows', DEFAULTROWS ) ) )
			if self.verbose:
				print( sql )
			self.q( sql )
			self.tableView.set(self.cursor.fetchall())
		
	@pyqtSlot()
	def onExit(self):
		QApplication.exit();

	@pyqtSlot()
	def onValueChanged(self, _id):
		if self.verbose:
			print('changed:', _id)
			print(self.tableView.get(_id))
		data = self.tableView.get(_id)
		self.q('''
				UPDATE tt
				SET time_begin = %d,
				time_end = %d,
				description = '%s',
				note = '%s',
				need_update = 1
				WHERE
				id = %d
				'''	% ( data[1], data[2], data[3], data[4], data[0] ))
		self.updateDescriptionEditCompleter()
		self.sync()

	@pyqtSlot()
	def onDelete(self, _id):
		if self.verbose:
			print('del:', _id,self.tableView.get(_id)[0])
		self.q('UPDATE tt SET is_delete = 1 WHERE id = %d' % self.tableView.get(_id)[0])
		self.updateTplTable()
		self.updateDescriptionEditCompleter()				
		self.sync()
		
	@pyqtSlot()
	def onTimer(self):
		self.startStopButton.setText('Stop (%s)' % self.timePattern.sub( '', str( datetime.now() - self.time_begin ) ) )

	@pyqtSlot()
	def onStartStop(self):
		if self.timer.isActive():
			self.timer.stop()
			self.time_end = datetime.now()
			self.q('''
				INSERT INTO tt
				(time_begin,time_end,description,note)
				VALUES
				('%d','%d','%s','%s')
				'''	% ( int(mktime(self.time_begin.timetuple())), int(mktime(self.time_end.timetuple())), self.descriptionInput.text(), self.noteInput.text() ))
			self.noteInput.clear()
			self.updateTplTable()
			self.updateDescriptionEditCompleter()				
			self.startStopButton.setText('Start')
			self.sync()
		else:
			self.time_begin = datetime.now()
			self.timer.start()
			self.onTimer()

	def onAboutAppAction(self):
		QMessageBox.about(self, self.tr("&about"), self.tr("%1 version %2").arg(QApplication.applicationName()).arg(QApplication.applicationVersion()))
		
	def onAboutQtAction(self):
		QMessageBox.aboutQt(self, self.tr("&about"))

	def checkSync(self):
		if self.sync_active:
			QMessageBox.information(self, 'Information', '''Sync is currently active. Please wait until it's finished''')
			return False
		else:
			return True

	def onSettings(self):
		if not self.checkSync():
			return
		settings = self.fetchSettings()

		inp = SettingsWidget(settings, self)
		if inp.exec_():
			for key in inp.data():
				if type( inp.data()[key] ) == bytes:
					value = inp.data()[key].decode( 'UTF-8' )
				else:
					value = inp.data()[key]
				self.q( '''REPLACE INTO settings VALUES ('%s','%s')''' % ( key, value ) )
			try: dr = settings['displayrows']
			except: dr = None
			if dr != inp.data()['displayrows']:
				QMessageBox.information(self, 'displayrows changed...', 'exiting now.')
				sys.exit(0)
		self.settings = self.fetchSettings()

	def onImport(self):
		if not self.checkSync():
			return
		ImportWidget( self.db_path, self ).exec_()
		self.updateTplTable()
		self.updateDescriptionEditCompleter()				

	def fetchSettings(self):
		s = {}
		self.q( 'SELECT key,value FROM settings' )
		for key,value in self.cursor.fetchall():
			s[key] = value
		return s

	def getSetting(self,key,default = None):
		try:
			v = self.settings[key]
		except:
			if default != None:
				v = default
			else:
				v = ''
		return v
예제 #47
0
class SVNPluginPropsDialog( QDialog ):
    " SVN plugin properties dialog "

    def __init__( self, plugin, client, path, parent = None ):
        QDialog.__init__( self, parent )

        self.__plugin = plugin
        self.__client = client
        self.__path = path

        self.__createLayout()
        self.setWindowTitle( "SVN Properties of " + path )
        self.__populate()
        self.__propsView.setFocus()
        return

    def __populate( self ):
        " Populate the properties list "
        # Get the currently selected name
        selectedName = None
        selected = list( self.__propsView.selectedItems() )
        if selected:
            selectedName = str( selected[ 0 ].text( 0 ) )

        self.__propsView.clear()
        properties = readProperties( self.__client, self.__path )
        if properties:
            for itemPath, itemProps in properties:
                if self.__path == itemPath or \
                   self.__path == itemPath + os.path.sep:
                    for name, value in itemProps.iteritems():
                        name = str( name ).strip()
                        value = str( value ).strip()
                        newItem = QTreeWidgetItem( [ name, value ] )
                        self.__propsView.addTopLevelItem( newItem )

        self.__resizePropsView()
        self.__sortPropsView()

        if selectedName:
            index = 0
            for index in xrange( 0, self.__propsView.topLevelItemCount() ):
                item = self.__propsView.topLevelItem( index )
                if selectedName == item.text( 0 ):
                    item.setSelected( True )
        return

    def __resizePropsView( self ):
        " Resizes the properties table "
        self.__propsView.header().setStretchLastSection( True )
        self.__propsView.header().resizeSections(
                                        QHeaderView.ResizeToContents )
        return

    def __sortPropsView( self ):
        " Sorts the properties table "
        self.__propsView.sortItems(
                    self.__propsView.sortColumn(),
                    self.__propsView.header().sortIndicatorOrder() )
        return

    def __createLayout( self ):
        " Creates the dialog layout "
        self.resize( 640, 480 )
        self.setSizeGripEnabled( True )

        vboxLayout = QVBoxLayout( self )

        hLayout = QHBoxLayout()
        self.__propsView = QTreeWidget()
        self.__propsView.setAlternatingRowColors( True )
        self.__propsView.setRootIsDecorated( False )
        self.__propsView.setItemsExpandable( False )
        self.__propsView.setSortingEnabled( True )
        self.__propsView.setItemDelegate( NoOutlineHeightDelegate( 4 ) )
        self.__propsView.itemSelectionChanged.connect( self.__propsSelectionChanged )

        propsViewHeader = QTreeWidgetItem( [ "Property Name", "Property Value" ] )
        self.__propsView.setHeaderItem( propsViewHeader )
        self.__propsView.header().setSortIndicator( 0, Qt.DescendingOrder )
        hLayout.addWidget( self.__propsView )

        self.__delButton = QToolButton()
        self.__delButton.setText( "Delete" )
        self.__delButton.setFocusPolicy( Qt.NoFocus )
        self.__delButton.setEnabled( False )
        self.__delButton.clicked.connect( self.__onDel )
        hLayout.addWidget( self.__delButton, 0, Qt.AlignBottom )
        vboxLayout.addLayout( hLayout )

        # Set property part
        setGroupbox = QGroupBox( self )
        setGroupbox.setTitle( "Set Property" )

        setLayout = QGridLayout( setGroupbox )
        setLayout.addWidget( QLabel( "Name" ), 0, 0, Qt.AlignTop | Qt.AlignRight )
        setLayout.addWidget( QLabel( "Value" ), 1, 0, Qt.AlignTop | Qt.AlignRight )

        self.__nameEdit = QLineEdit()
        self.__nameEdit.textChanged.connect( self.__nameChanged )
        setLayout.addWidget( self.__nameEdit, 0, 1 )

        self.__valueEdit = QTextEdit()
        self.__valueEdit.setAcceptRichText( False )
        self.__valueEdit.textChanged.connect( self.__valueChanged )
        metrics = QFontMetrics( self.__valueEdit.font() )
        rect = metrics.boundingRect( "X" )
        self.__valueEdit.setFixedHeight( rect.height() * 4 + 5 )
        setLayout.addWidget( self.__valueEdit, 1, 1 )

        self.__setButton = QToolButton()
        self.__setButton.setText( "Set" )
        self.__setButton.setFocusPolicy( Qt.NoFocus )
        self.__setButton.setEnabled( False )
        self.__setButton.clicked.connect( self.__onSet )
        setLayout.addWidget( self.__setButton, 1, 2, Qt.AlignBottom | Qt.AlignHCenter )
        
        sizePolicy = QSizePolicy( QSizePolicy.Expanding, QSizePolicy.Maximum )
        sizePolicy.setHorizontalStretch( 0 )
        sizePolicy.setVerticalStretch( 0 )
        sizePolicy.setHeightForWidth( setGroupbox.sizePolicy().hasHeightForWidth() )
        setGroupbox.setSizePolicy( sizePolicy )
        vboxLayout.addWidget( setGroupbox )

        # Buttons at the bottom
        buttonBox = QDialogButtonBox( self )
        buttonBox.setOrientation( Qt.Horizontal )
        buttonBox.setStandardButtons( QDialogButtonBox.Ok )
        buttonBox.button( QDialogButtonBox.Ok ).setDefault( True )
        buttonBox.accepted.connect( self.close )
        vboxLayout.addWidget( buttonBox )
        return

    def __onSet( self ):
        " Triggered when propery set is clicked "
        name = self.__nameEdit.text().strip()
        value = self.__valueEdit.toPlainText().strip()
        try:
            commitInfo = self.__client.propset( name, value, self.__path )
            if commitInfo:
                logging.info( str( commitInfo ) )
            self.__populate()
            self.__plugin.notifyPathChanged( self.__path )
            self.__nameEdit.clear()
            self.__valueEdit.clear()
            self.__propsView.setFocus()
        except pysvn.ClientError, exc:
            message = exc.args[ 0 ]
            logging.error( message )
            return
        except Exception, exc:
            logging.error( str( exc ) )
            return
class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        self.fnames = []  # list of file names to be converted
        self.office_listener_started = False

        self.parse_cla()

        addQPB = QPushButton(self.tr('Add'))
        delQPB = QPushButton(self.tr('Delete'))
        clearQPB = QPushButton(self.tr('Clear'))
        vlayout1 = utils.add_to_layout('v', addQPB, delQPB, clearQPB, None)

        self.filesList = utils.FilesList()
        self.filesList.setSelectionMode(QAbstractItemView.ExtendedSelection)
        hlayout1 = utils.add_to_layout('h', self.filesList, vlayout1)

        outputQL = QLabel(self.tr('Output folder:'))
        self.toQLE = QLineEdit()
        self.toQLE.setReadOnly(True)
        self.toQTB = QToolButton()
        self.toQTB.setText('...')
        hlayout2 = utils.add_to_layout('h', outputQL, self.toQLE, self.toQTB)

        self.audiovideo_tab = AudioVideoTab(self)
        self.image_tab = ImageTab(self)
        self.document_tab = DocumentTab(self)

        self.tabs = [self.audiovideo_tab, self.image_tab, self.document_tab]
        tab_names = [self.tr('Audio/Video'), self.tr('Images'),
                     self.tr('Documents')]

        self.tabWidget = QTabWidget()
        for num, tab in enumerate(tab_names):
            self.tabWidget.addTab(self.tabs[num], tab)
        self.tabWidget.setCurrentIndex(0)

        self.origQCB = QCheckBox(
                self.tr('Save each file in the same\nfolder as input file'))
        self.deleteQCB = QCheckBox(self.tr('Delete original'))
        convertQPB = QPushButton(self.tr('&Convert'))

        hlayout3 = utils.add_to_layout('h', self.origQCB, self.deleteQCB, None)
        hlayout4 = utils.add_to_layout('h', None, convertQPB)
        final_layout = utils.add_to_layout(
                'v', hlayout1, self.tabWidget, hlayout2, hlayout3, hlayout4)

        self.dependenciesQL = QLabel()
        self.statusBar().addPermanentWidget(self.dependenciesQL, stretch=1)

        widget = QWidget()
        widget.setLayout(final_layout)
        self.setCentralWidget(widget)

        openAction = utils.create_action(
                self, self.tr('Open'), QKeySequence.Open, None,
                self.tr('Open a file'), self.add_files
                )
        convertAction = utils.create_action(
                self, self.tr('Convert'), 'Ctrl+C', None,
                self.tr('Convert files'), self.start_conversion
                )
        quitAction = utils.create_action(
                self, self.tr('Quit'), 'Ctrl+Q', None,
                self.tr('Quit'), self.close
                )
        edit_presetsAction = utils.create_action(
                self, self.tr('Edit Presets'), 'Ctrl+P', None,
                self.tr('Edit Presets'), self.open_dialog_presets
                )
        importAction = utils.create_action(
                self, self.tr('Import'), None, None,
                self.tr('Import presets'), self.import_presets
                )
        exportAction = utils.create_action(
                self, self.tr('Export'), None, None,
                self.tr('Export presets'), self.export_presets
                )
        resetAction = utils.create_action(
                self, self.tr('Reset'), None, None,
                self.tr('Reset presets'), self.reset_presets
                )
        syncAction = utils.create_action(
                self, self.tr('Synchronize'), None, None,
                self.tr('Synchronize presets'), self.sync_presets
                )
        removeoldAction = utils.create_action(
                self, self.tr('Remove old'), None, None,
                self.tr('Remove old presets'), self.removeold_presets
                )
        clearallAction = utils.create_action(
                self, self.tr('Clear All'), None, None,
                self.tr('Clear form'), self.clear_all
                )
        preferencesAction = utils.create_action(
                self, self.tr('Preferences'), 'Alt+Ctrl+P',
                None, self.tr('Preferences'), self.open_dialog_preferences
                )
        trackerAction = utils.create_action(
                self, 'Issue tracker', None, None, None,
                lambda: webbrowser.open(
                    "https://github.com/Ilias95/FF-Multi-Converter/issues")
                )
        wikiAction = utils.create_action(
                self, 'Wiki', None, None, None,
                lambda: webbrowser.open(
                    "https://github.com/Ilias95/FF-Multi-Converter/wiki")
                )
        ffmpegdocAction = utils.create_action(
                self, 'FFmpeg ' + self.tr('documentation'), None, None, None,
                lambda: webbrowser.open(
                    "https://www.ffmpeg.org/documentation.html")
                )
        imagemagickdocAction = utils.create_action(
                self, 'ImageMagick ' + self.tr('documentation'), None, None,
                None, lambda: webbrowser.open(
                    "http://www.imagemagick.org/script/convert.php")
                )
        aboutAction = utils.create_action(
                self, self.tr('About'), 'Ctrl+?', None,
                self.tr('About'), self.open_dialog_about
                )

        fileMenu = self.menuBar().addMenu(self.tr('File'))
        editMenu = self.menuBar().addMenu(self.tr('Edit'))
        presetsMenu = self.menuBar().addMenu(self.tr('Presets'))
        helpMenu = self.menuBar().addMenu(self.tr('Help'))

        utils.add_actions(
                fileMenu, [openAction, convertAction, None, quitAction])
        utils.add_actions(
                presetsMenu,
                [edit_presetsAction, importAction, exportAction, resetAction,
                 None, syncAction, removeoldAction]
                )
        utils.add_actions(editMenu, [clearallAction, None, preferencesAction])
        utils.add_actions(
                helpMenu,
                [trackerAction, wikiAction, None, ffmpegdocAction,
                imagemagickdocAction, None, aboutAction]
                )

        self.filesList.dropped.connect(self.add_files_dropped)
        addQPB.clicked.connect(self.add_files)
        delQPB.clicked.connect(self.delete_files)
        clearQPB.clicked.connect(self.clear_fileslist)
        self.tabWidget.currentChanged.connect(
                lambda: self.tabs[0].moreQPB.setChecked(False))
        self.origQCB.toggled.connect(
                lambda: self.toQLE.setEnabled(not self.origQCB.isChecked()))
        self.toQTB.clicked.connect(self.open_dir)
        convertQPB.clicked.connect(convertAction.triggered)

        del_shortcut = QShortcut(self)
        del_shortcut.setKey(Qt.Key_Delete)
        del_shortcut.activated.connect(self.delete_files)

        self.setWindowTitle('FF Multi Converter')

        QTimer.singleShot(0, self.check_for_dependencies)
        QTimer.singleShot(0, self.load_settings)
        QTimer.singleShot(0, self.audiovideo_tab.set_default_command)
        QTimer.singleShot(0, self.update_filesList)

    def parse_cla(self):
        """Parse command line arguments."""
        for i in QCoreApplication.argv()[1:]:
            i = os.path.abspath(i)
            if os.path.isfile(i):
                self.fnames.append(i)
            else:
                print("ffmulticonverter: {0}: Not a file".format(i))

    def check_for_dependencies(self):
        """
        Check if each one of the program dependencies are installed and
        update self.dependenciesQL with the appropriate message.
        """
        self.vidconverter = None
        if utils.is_installed('ffmpeg'):
            self.vidconverter = 'ffmpeg'
        elif utils.is_installed('avconv'):
            self.vidconverter = 'avconv'
        self.unoconv = utils.is_installed('unoconv')
        self.imagemagick = utils.is_installed('convert')

        missing = []
        if self.vidconverter is None:
            missing.append('ffmpeg/avconv')
        if not self.unoconv:
            missing.append('unoconv')
        if not self.imagemagick:
            missing.append('imagemagick')

        if missing:
            missing = ', '.join(missing)
            status = self.tr('Missing dependencies:') + ' ' + missing
            self.dependenciesQL.setText(status)

    def load_settings(self, onstart=True):
        """
        Load settings values.

        onstart -- True means that this is the first time the method called,
                   usually when program beggins
        """
        def get_str_value(settings, name):
            value = settings.value(name)
            if value is not None:
                return value
            return ''

        settings = QSettings()
        self.overwrite_existing = utils.str_to_bool(
                get_str_value(settings, 'overwrite_existing'))
        self.default_output = get_str_value(settings, 'default_output')
        self.prefix = get_str_value(settings, 'prefix')
        self.suffix = get_str_value(settings, 'suffix')
        defcmd = get_str_value(settings, 'default_command')
        extraformats = get_str_value(settings, 'extraformats')
        videocodecs = settings.value('videocodecs')
        audiocodecs = settings.value('audiocodecs')

        if videocodecs is None:
            videocodecs = "\n".join(config.video_codecs)
            settings.setValue('videocodecs', videocodecs)
        if audiocodecs is None:
            audiocodecs = "\n".join(config.audio_codecs)
            settings.setValue('audiocodecs', audiocodecs)

        if defcmd:
            self.default_command = defcmd
        else:
            self.default_command = config.default_ffmpeg_cmd

        self.audiovideo_tab.fill_video_comboboxes(
                videocodecs, audiocodecs, extraformats)

        if onstart:
            self.toQLE.setText(self.default_output)

    def current_tab(self):
        """Return the corresponding object of the selected tab."""
        for i in self.tabs:
            if self.tabs.index(i) == self.tabWidget.currentIndex():
                return i

    def update_filesList(self):
        """Clear self.filesList and add to it all items of self.fname."""
        self.filesList.clear()
        for i in self.fnames:
            self.filesList.addItem(i)

    def add_files(self):
        """
        Get file names using a standard Qt dialog.
        Append to self.fnames each file name that not already exists
        and update self.filesList.
        """
        # Create lists holding file formats extension.
        # To be passed in QFileDialog.getOpenFileNames().
        all_files = '*'
        audiovideo_files = ' '.join(
                ['*.'+i for i in self.audiovideo_tab.formats])
        img_formats = self.image_tab.formats[:]
        img_formats.extend(self.image_tab.extra_img)
        image_files = ' '.join(['*.'+i for i in img_formats])
        document_files = ' '.join(['*.'+i for i in self.document_tab.formats])
        formats = [all_files, audiovideo_files, image_files, document_files]
        strings = [self.tr('All Files'), self.tr('Audio/Video Files'),
                   self.tr('Image Files'), self.tr('Document Files')]

        filters = ''
        for string, extensions in zip(strings, formats):
            filters += string + ' ({0});;'.format(extensions)
        filters = filters[:-2] # remove last ';;'

        fnames = QFileDialog.getOpenFileNames(self, 'FF Multi Converter - ' +
                self.tr('Choose File'), config.home, filters)

        if fnames:
            for i in fnames:
                if not i in self.fnames:
                    self.fnames.append(i)
            self.update_filesList()

    def add_files_dropped(self, links):
        """
        Append to self.fnames each file name that not already exists
        and update self.filesList.
        """
        for path in links:
            if os.path.isfile(path) and not path in self.fnames:
                self.fnames.append(path)
        self.update_filesList()

    def delete_files(self):
        """
        Get selectedItems of self.filesList, remove them from self.fnames and
        update the filesList.
        """
        items = self.filesList.selectedItems()
        if items:
            for i in items:
                self.fnames.remove(i.text())
            self.update_filesList()

    def clear_fileslist(self):
        """Make self.fnames empty and update self.filesList."""
        self.fnames = []
        self.update_filesList()

    def clear_all(self):
        """Clear all values of graphical widgets."""
        self.toQLE.clear()
        self.origQCB.setChecked(False)
        self.deleteQCB.setChecked(False)
        self.clear_fileslist()

        self.audiovideo_tab.clear()
        self.image_tab.clear()

    def open_dir(self):
        """
        Get a directory name using a standard QtDialog and update
        self.toQLE with dir's name.
        """
        if self.toQLE.isEnabled():
            output = QFileDialog.getExistingDirectory(
                    self, 'FF Multi Converter - ' +
                    self.tr('Choose output destination'),
                    config.home)
            if output:
                self.toQLE.setText(output)

    def import_presets(self):
        presets_dlgs.ShowPresets().import_presets()

    def export_presets(self):
        presets_dlgs.ShowPresets().export_presets()

    def reset_presets(self):
        presets_dlgs.ShowPresets().reset()

    def sync_presets(self):
        presets_dlgs.ShowPresets().synchronize()

    def removeold_presets(self):
        presets_dlgs.ShowPresets().remove_old()

    def ok_to_continue(self):
        """
        Check if everything is ok to continue with conversion.

        Check if:
        - At least one file has given for conversion.
        - An output folder has given.
        - Output folder exists.

        Return False if an error arises, else True.
        """
        try:
            if not self.fnames:
                raise ValidationError(
                        self.tr('You must add at least one file to convert!'))
            elif not self.origQCB.isChecked() and not self.toQLE.text():
                raise ValidationError(
                        self.tr('You must choose an output folder!'))
            elif (not self.origQCB.isChecked() and
                  not os.path.exists(self.toQLE.text())):
                raise ValidationError(self.tr('Output folder does not exists!'))
            if not self.current_tab().ok_to_continue():
                return False
            return True

        except ValidationError as e:
            QMessageBox.warning(
                    self, 'FF Multi Converter - ' + self.tr('Error!'), str(e))
            return False

    def get_output_extension(self):
        """Extract the desired output file extension from GUI and return it."""
        tab = self.current_tab()
        if tab.name == 'AudioVideo':
            ext_to = self.audiovideo_tab.extQCB.currentText()
        elif tab.name == 'Images':
            ext_to = tab.extQCB.currentText()
        else:
            ext_to = tab.convertQCB.currentText().split()[-1]

        return '.' + ext_to

    def start_conversion(self):
        """
        Extract the appropriate information from GUI and call the
        Progress dialog with the suitable argumens.
        """
        if not self.ok_to_continue():
            return

        tab = self.current_tab()
        if tab.name == 'Documents' and not self.office_listener_started:
            utils.start_office_listener()
            self.office_listener_started = True

        ext_to = self.get_output_extension()
        _list = utils.create_paths_list(
                self.fnames, ext_to, self.prefix, self.suffix,
                self.toQLE.text(), self.origQCB.isChecked(),
                self.overwrite_existing
                )

        dialog = progress.Progress(
                _list, tab, self.deleteQCB.isChecked(), self)
        dialog.show()

    def open_dialog_preferences(self):
        """Open the preferences dialog."""
        dialog = preferences_dlg.Preferences(self)
        if dialog.exec_():
            self.load_settings(onstart=False)

    def open_dialog_presets(self):
        """Open the presets dialog."""
        dialog = presets_dlgs.ShowPresets(self)
        dialog.exec_()

    def open_dialog_about(self):
        """Call the about dialog with the appropriate values."""
        msg = self.tr('Convert among several file types to other formats')
        msg = textwrap.fill(msg, 54).replace('\n', '<br>')
        text = '''<b> FF Multi Converter {0} </b>
                 <p>{1}
                 <p><a href="{2}">FF Multi Converter - Home Page</a>
                 <p>Copyright &copy; 2011-2015 {3}
                 <br>License: {4}
                 <p>Python {5} - Qt {6} - PyQt {7} on {8}'''\
                 .format(ffmc.__version__, msg, ffmc.__url__, ffmc.__author__,
                         ffmc.__license__, platform.python_version()[:5],
                         QT_VERSION_STR, PYQT_VERSION_STR, platform.system())
        image = ':/ffmulticonverter.png'
        authors = '{0} <{1}>\n\n'.format(ffmc.__author__, ffmc.__author_email__)
        authors += 'Contributors:\nPanagiotis Mavrogiorgos'
        translators = []
        for i in config.translators:
            translators.append('{0}\n     {1}'.format(i[0], i[1]))
        translators = '\n\n'.join(translators)

        dialog = about_dlg.AboutDialog(text, image, authors, translators, self)
        dialog.exec_()
예제 #49
0
class AudioVideoTab(QWidget):
    def __init__(self, parent):
        super(AudioVideoTab, self).__init__(parent)
        self.parent = parent
        self.name = 'AudioVideo'
        self.formats = [
            '3gp', 'aac', 'ac3', 'afc', 'aiff', 'amr', 'asf', 'au', 'avi',
            'dvd', 'flac', 'flv', 'mka', 'mkv', 'mmf', 'mov', 'mp3', 'mp4',
            'mpg', 'ogg', 'ogv', 'psp', 'rm', 'spx', 'vob', 'wav', 'webm',
            'wma', 'wmv'
        ]
        self.extra_formats = [
            'aifc', 'm2t', 'm4a', 'm4v', 'mp2', 'mpeg', 'ra', 'ts'
        ]

        nochange = self.tr('No Change')
        frequency_values = [nochange, '22050', '44100', '48000']
        bitrate_values = [
            nochange, '32', '96', '112', '128', '160', '192', '256', '320'
        ]
        pattern = QRegExp(r'^[1-9]\d*')
        validator = QRegExpValidator(pattern, self)

        converttoLabel = QLabel(self.tr('Convert to:'))
        self.extComboBox = QComboBox()
        self.extComboBox.addItems(self.formats + [self.tr('Other')])
        self.extComboBox.setMinimumWidth(130)
        self.extLineEdit = QLineEdit()
        self.extLineEdit.setMaximumWidth(85)
        self.extLineEdit.setEnabled(False)
        hlayout1 = pyqttools.add_to_layout(QHBoxLayout(), converttoLabel, None,
                                           self.extComboBox, self.extLineEdit)
        commandLabel = QLabel(self.tr('Command:'))
        self.commandLineEdit = QLineEdit()
        self.presetButton = QPushButton(self.tr('Preset'))
        self.defaultButton = QPushButton(self.tr('Default'))
        hlayout2 = pyqttools.add_to_layout(QHBoxLayout(), commandLabel,
                                           self.commandLineEdit,
                                           self.presetButton,
                                           self.defaultButton)

        sizeLabel = QLabel(self.tr('Video Size:'))
        aspectLabel = QLabel(self.tr('Aspect:'))
        frameLabel = QLabel(self.tr('Frame Rate (fps):'))
        bitrateLabel = QLabel(self.tr('Video Bitrate (kbps):'))

        self.widthLineEdit = pyqttools.create_LineEdit((50, 16777215),
                                                       validator, 4)
        self.heightLineEdit = pyqttools.create_LineEdit((50, 16777215),
                                                        validator, 4)
        label = QLabel('x')
        layout1 = pyqttools.add_to_layout(QHBoxLayout(), self.widthLineEdit,
                                          label, self.heightLineEdit)
        self.aspect1LineEdit = pyqttools.create_LineEdit((35, 16777215),
                                                         validator, 2)
        self.aspect2LineEdit = pyqttools.create_LineEdit((35, 16777215),
                                                         validator, 2)
        label = QLabel(':')
        layout2 = pyqttools.add_to_layout(QHBoxLayout(), self.aspect1LineEdit,
                                          label, self.aspect2LineEdit)
        self.frameLineEdit = pyqttools.create_LineEdit(None, validator, 4)
        self.bitrateLineEdit = pyqttools.create_LineEdit(None, validator, 6)

        labels = [sizeLabel, aspectLabel, frameLabel, bitrateLabel]
        widgets = [layout1, layout2, self.frameLineEdit, self.bitrateLineEdit]

        videosettings_layout = QHBoxLayout()
        for a, b in zip(labels, widgets):
            text = a.text()
            a.setText('<html><p align="center">{0}</p></html>'.format(text))
            layout = pyqttools.add_to_layout(QVBoxLayout(), a, b)
            videosettings_layout.addLayout(layout)

        freqLabel = QLabel(self.tr('Frequency (Hz):'))
        chanLabel = QLabel(self.tr('Channels:'))
        bitrateLabel = QLabel(self.tr('Audio Bitrate (kbps):'))

        self.freqComboBox = QComboBox()
        self.freqComboBox.addItems(frequency_values)
        self.chan1RadioButton = QRadioButton('1')
        self.chan1RadioButton.setMaximumSize(QSize(51, 16777215))
        self.chan2RadioButton = QRadioButton('2')
        self.chan2RadioButton.setMaximumSize(QSize(51, 16777215))
        self.group = QButtonGroup()
        self.group.addButton(self.chan1RadioButton)
        self.group.addButton(self.chan2RadioButton)
        spcr1 = QSpacerItem(40, 20, QSizePolicy.Preferred, QSizePolicy.Minimum)
        spcr2 = QSpacerItem(40, 20, QSizePolicy.Preferred, QSizePolicy.Minimum)
        chanlayout = pyqttools.add_to_layout(QHBoxLayout(), spcr1,
                                             self.chan1RadioButton,
                                             self.chan2RadioButton, spcr2)
        self.audio_bitrateComboBox = QComboBox()
        self.audio_bitrateComboBox.addItems(bitrate_values)

        labels = [freqLabel, chanLabel, bitrateLabel]
        widgets = [self.freqComboBox, chanlayout, self.audio_bitrateComboBox]

        audiosettings_layout = QHBoxLayout()
        for a, b in zip(labels, widgets):
            text = a.text()
            a.setText('<html><p align="center">{0}</p></html>'.format(text))
            layout = pyqttools.add_to_layout(QVBoxLayout(), a, b)
            audiosettings_layout.addLayout(layout)

        hidden_layout = pyqttools.add_to_layout(QVBoxLayout(),
                                                videosettings_layout,
                                                audiosettings_layout)

        line = QFrame()
        line.setFrameShape(QFrame.HLine)
        line.setFrameShadow(QFrame.Sunken)
        self.moreButton = QPushButton(QApplication.translate('Tab', 'More'))
        self.moreButton.setSizePolicy(QSizePolicy(QSizePolicy.Fixed))
        self.moreButton.setCheckable(True)
        hlayout3 = pyqttools.add_to_layout(QHBoxLayout(), line,
                                           self.moreButton)

        self.frame = QFrame()
        self.frame.setLayout(hidden_layout)
        self.frame.hide()

        final_layout = pyqttools.add_to_layout(QVBoxLayout(), hlayout1,
                                               hlayout2, hlayout3, self.frame)
        self.setLayout(final_layout)

        self.presetButton.clicked.connect(self.choose_preset)
        self.defaultButton.clicked.connect(self.set_default_command)
        self.moreButton.toggled.connect(self.frame.setVisible)
        self.moreButton.toggled.connect(self.resize_parent)
        self.extComboBox.currentIndexChanged.connect(
            lambda: self.extLineEdit.setEnabled(self.extComboBox.currentIndex(
            ) == len(self.formats)))
        self.widthLineEdit.textChanged.connect(
            lambda: self.command_elements_change('size'))
        self.heightLineEdit.textChanged.connect(
            lambda: self.command_elements_change('size'))
        self.aspect1LineEdit.textChanged.connect(
            lambda: self.command_elements_change('aspect'))
        self.aspect2LineEdit.textChanged.connect(
            lambda: self.command_elements_change('aspect'))
        self.frameLineEdit.textChanged.connect(
            lambda: self.command_elements_change('frames'))
        self.bitrateLineEdit.textChanged.connect(
            lambda: self.command_elements_change('video_bitrate'))
        self.freqComboBox.currentIndexChanged.connect(
            lambda: self.command_elements_change('frequency'))
        self.audio_bitrateComboBox.currentIndexChanged.connect(
            lambda: self.command_elements_change('audio_bitrate'))
        self.chan1RadioButton.clicked.connect(
            lambda: self.command_elements_change('channels1'))
        self.chan2RadioButton.clicked.connect(
            lambda: self.command_elements_change('channels2'))

    def resize_parent(self):
        """Resize MainWindow."""
        height = MAIN_FIXED_HEIGHT if self.frame.isVisible() else MAIN_HEIGHT
        self.parent.setMinimumSize(MAIN_WIDTH, height)
        self.parent.resize(MAIN_WIDTH, height)

    def clear(self):
        """Clear all values of graphical widgets."""
        lines = [
            self.commandLineEdit, self.widthLineEdit, self.heightLineEdit,
            self.aspect1LineEdit, self.aspect2LineEdit, self.frameLineEdit,
            self.bitrateLineEdit, self.extLineEdit
        ]
        for i in lines:
            i.clear()

        self.freqComboBox.setCurrentIndex(0)
        self.audio_bitrateComboBox.setCurrentIndex(0)
        self.group.setExclusive(False)
        self.chan1RadioButton.setChecked(False)
        self.chan2RadioButton.setChecked(False)
        self.group.setExclusive(True)
        # setExclusive(False) in order to be able to uncheck checkboxes and
        # then setExclusive(True) so only one radio button can be set

    def ok_to_continue(self):
        """
        Check if everything is ok with audiovideotab to continue conversion.

        Check if:
        - Either ffmpeg or avconv are installed.
        - Desired extension is valid.
        - self.commandLineEdit is empty.

        Return True if all tests pass, else False.
        """
        if not self.parent.ffmpeg and not self.parent.avconv:
            QMessageBox.warning(
                self, 'FF Multi Converter - ' + self.tr('Error!'),
                self.
                tr('Neither ffmpeg nor avconv are installed.'
                   '\nYou will not be able to convert audio/video files until you'
                   ' install one of them.'))
            return False
        if self.extLineEdit.isEnabled():
            text = str(self.extLineEdit.text()).strip()
            if len(text.split()) != 1 or text[0] == '.':
                QMessageBox.warning(
                    self, 'FF Multi Converter - ' + self.tr('Error!'),
                    self.tr('Extension must be one word and must '
                            'not start with a dot.'))
                self.extLineEdit.selectAll()
                self.extLineEdit.setFocus()
                return False
        if not self.commandLineEdit.text():
            QMessageBox.warning(
                self, 'FF Multi Converter - ' + self.tr('Error!'),
                self.tr('The command LineEdit may not be empty.'))
            self.commandLineEdit.setFocus()
            return False
        return True

    def set_default_command(self):
        """Set the default value to self.commandLineEdit."""
        self.clear()
        self.commandLineEdit.setText(self.parent.default_command)

    def choose_preset(self):
        """
        Open the presets dialog and update self.commandLineEdit,
        self.extComboBox and self.extLineEdit with the appropriate values.
        """
        dialog = presets_dlgs.ShowPresets()
        if dialog.exec_() and dialog.the_command is not None:
            self.commandLineEdit.setText(dialog.the_command)
            self.commandLineEdit.home(False)
            find = self.extComboBox.findText(dialog.the_extension)
            if find >= 0:
                self.extComboBox.setCurrentIndex(find)
            else:
                self.extComboBox.setCurrentIndex(len(self.formats))
                self.extLineEdit.setText(dialog.the_extension)

    def remove_consecutive_spaces(self, string):
        """Remove any consecutive spaces from a string and return it."""
        temp = string
        string = ''
        for i in temp.split():
            if i:
                string += i + ' '
        return string[:-1]

    def command_elements_change(self, widget):
        """Fill self.commandLineEdit with the appropriate command parameters."""
        command = str(self.commandLineEdit.text())

        if widget == 'size':
            text1 = self.widthLineEdit.text()
            text2 = self.heightLineEdit.text()

            if (text1 or text2) and not (text1 and text2):
                return
            f = re.sub(r'^.*(-s\s+\d+x\d+).*$', r'\1', command)
            if re.match(r'^.*(-s\s+\d+x\d+).*$', f):
                command = command.replace(f, '').strip()
            if text1 and text2:
                command += ' -s {0}x{1}'.format(text1, text2)

        elif widget == 'aspect':
            text1 = self.aspect1LineEdit.text()
            text2 = self.aspect2LineEdit.text()

            if (text1 or text2) and not (text1 and text2):
                return
            f = re.sub(r'^.*(-aspect\s+\d+:\d+).*$', r'\1', command)
            if re.match(r'^.*(-aspect\s+\d+:\d+).*$', f):
                command = command.replace(f, '').strip()
            if text1 and text2:
                command += ' -aspect {0}:{1}'.format(text1, text2)

        elif widget == 'frames':
            text = self.frameLineEdit.text()
            f = re.sub(r'^.*(-r\s+\d+).*$', r'\1', command)
            if re.match(r'^.*(-r\s+\d+).*$', f):
                command = command.replace(f, '').strip()
            if text:
                command += ' -r {0}'.format(text)

        elif widget == 'video_bitrate':
            text = self.bitrateLineEdit.text()
            f = re.sub(r'^.*(-b\s+\d+k).*$', r'\1', command)
            if re.match(r'^.*(-b\s+\d+k).*$', f):
                command = command.replace(f, '')
            if text:
                command += ' -b {0}k'.format(text)
            command = command.replace('-sameq', '').strip()

        elif widget == 'frequency':
            text = self.freqComboBox.currentText()
            f = re.sub(r'^.*(-ar\s+\d+).*$', r'\1', command)
            if re.match(r'^.*(-ar\s+\d+).*$', f):
                command = command.replace(f, '').strip()
            if text != 'No Change':
                command += ' -ar {0}'.format(text)

        elif widget == 'audio_bitrate':
            text = self.audio_bitrateComboBox.currentText()
            f = re.sub(r'^.*(-ab\s+\d+k).*$', r'\1', command)
            if re.match(r'^.*(-ab\s+\d+k).*$', f):
                command = command.replace(f, '').strip()
            if text != 'No Change':
                command += ' -ab {0}k'.format(text)

        elif widget in ('channels1', 'channels2'):
            text = self.chan1RadioButton.text() if widget == 'channels1' \
                                            else self.chan2RadioButton.text()
            f = re.sub(r'^.*(-ac\s+\d+).*$', r'\1', command)
            if re.match(r'^.*(-ac\s+\d+).*$', f):
                command = command.replace(f, '').strip()
            command += ' -ac {0}'.format(text)

        self.commandLineEdit.clear()
        self.commandLineEdit.setText(self.remove_consecutive_spaces(command))
예제 #50
0
class Search(QWidget, plugin.MainWindowPlugin):
    def __init__(self, mainwindow):
        super(Search, self).__init__(mainwindow)
        self._currentView = None
        self._positions = None
        self._replace = False  # are we in replace mode?
        
        mainwindow.currentViewChanged.connect(self.viewChanged)
        mainwindow.actionCollection.edit_find_next.triggered.connect(self.findNext)
        mainwindow.actionCollection.edit_find_previous.triggered.connect(self.findPrevious)
        
        # dont inherit looks from view
        self.setFont(QApplication.font())
        self.setPalette(QApplication.palette())
        
        grid = QGridLayout()
        grid.setContentsMargins(4, 0, 4, 0)
        grid.setVerticalSpacing(0)
        self.setLayout(grid)
        
        self.searchEntry = QLineEdit(textChanged=self.slotSearchChanged)
        self.searchLabel = QLabel()
        self.caseCheck = QCheckBox(checked=True, focusPolicy=Qt.NoFocus)
        self.regexCheck = QCheckBox(focusPolicy=Qt.NoFocus)
        self.countLabel = QLabel(alignment=Qt.AlignRight | Qt.AlignVCenter)
        self.countLabel.setMinimumWidth(QApplication.fontMetrics().width("9999"))
        self.closeButton = QToolButton(autoRaise=True, focusPolicy=Qt.NoFocus)
        self.hideAction = QAction(self, triggered=self.slotHide)
        self.hideAction.setShortcut(QKeySequence(Qt.Key_Escape))
        self.hideAction.setIcon(self.style().standardIcon(QStyle.SP_DialogCloseButton))
        self.closeButton.setDefaultAction(self.hideAction)
        
        grid.addWidget(self.searchLabel, 0, 0)
        grid.addWidget(self.searchEntry, 0, 1)
        grid.addWidget(self.caseCheck, 0, 2)
        grid.addWidget(self.regexCheck, 0, 3)
        grid.addWidget(self.countLabel, 0, 4)
        grid.addWidget(self.closeButton, 0, 5)
        
        self.caseCheck.toggled.connect(self.slotSearchChanged)
        self.regexCheck.toggled.connect(self.slotSearchChanged)
        
        self.replaceEntry = QLineEdit()
        self.replaceLabel = QLabel()
        self.replaceButton = QPushButton(clicked=self.slotReplace)
        self.replaceAllButton = QPushButton(clicked=self.slotReplaceAll)
        
        grid.addWidget(self.replaceLabel, 1, 0)
        grid.addWidget(self.replaceEntry, 1, 1)
        grid.addWidget(self.replaceButton, 1, 2)
        grid.addWidget(self.replaceAllButton, 1, 3)
        
        app.settingsChanged.connect(self.readSettings)
        self.readSettings()
        app.translateUI(self)
        
    def translateUI(self):
        self.searchLabel.setText(_("Search:"))
        self.caseCheck.setText(_("&Case"))
        self.caseCheck.setToolTip(_("Case Sensitive"))
        self.regexCheck.setText(_("&Regex"))
        self.regexCheck.setToolTip(_("Regular Expression"))
        self.countLabel.setToolTip(_("The total number of matches"))
        self.hideAction.setToolTip(_("Close"))
        self.replaceLabel.setText(_("Replace:"))
        self.replaceButton.setText(_("Re&place"))
        self.replaceButton.setToolTip(_("Replaces the next occurrence of the search term."))
        self.replaceAllButton.setText(_("&All"))
        self.replaceAllButton.setToolTip(_("Replaces all occurrences of the search term in the document or selection."))
    
    def readSettings(self):
        data = textformats.formatData('editor')
        self.searchEntry.setFont(data.font)
        self.replaceEntry.setFont(data.font)
        p = data.palette()
        self.searchEntry.setPalette(p)
        self.replaceEntry.setPalette(p)
         
    def currentView(self):
        return self._currentView and self._currentView()
    
    def setCurrentView(self, view):
        self._currentView = weakref.ref(view) if view else None
        
    def showWidget(self):
        if self.isVisible():
            self.hideWidget()
        view = self.window().currentView()
        self.setCurrentView(view)
        layout = widgets.borderlayout.BorderLayout.get(view)
        layout.addWidget(self, widgets.borderlayout.BOTTOM)
        self.show()
        
    def hideWidget(self):
        view = self.currentView()
        if view:
            viewhighlighter.highlighter(view).clear("search")
            self.hide()
            layout = widgets.borderlayout.BorderLayout.get(view)
            layout.removeWidget(self)
    
    def viewChanged(self, new):
        self.setParent(None)
        self.hideWidget()
        self.setCurrentView(new)
        self.updatePositions()
        
    def slotHide(self):
        view = self.currentView()
        if view:
            self.hideWidget()
            view.setFocus()
        
    def find(self):
        # hide replace stuff
        self.replaceLabel.hide()
        self.replaceEntry.hide()
        self.replaceButton.hide()
        self.replaceAllButton.hide()
        self._replace = False # we are not in replace mode
        visible = self.isVisible()
        if not visible:
            with qutil.signalsBlocked(self.searchEntry):
                self.searchEntry.clear()
        self.showWidget()
        if not visible and self.currentView():
            # pick current word
            cursor = self.currentView().textCursor()
            cursor.movePosition(QTextCursor.StartOfWord)
            cursor.movePosition(QTextCursor.EndOfWord, QTextCursor.KeepAnchor)
            word = cursor.selection().toPlainText()
            if not re.search(r'\w', word):
                word = ""
            self.searchEntry.setText(word)
            self.searchEntry.selectAll()
        else:
            self.slotSearchChanged()
        self.searchEntry.setFocus()
        
    def replace(self):
        # show replace stuff
        self.replaceLabel.show()
        self.replaceEntry.show()
        self.replaceButton.show()
        self.replaceAllButton.show()
        focus = self.replaceEntry if self.isVisible() and self.searchEntry.text() else self.searchEntry
        self._replace = True # we are in replace mode
        self.showWidget()
        self.slotSearchChanged()
        focus.setFocus()
        
    def slotSearchChanged(self):
        self.updatePositions()
        viewhighlighter.highlighter(self.currentView()).highlight("search", self._positions, 1)

    def updatePositions(self):
        search = self.searchEntry.text()
        view = self.currentView()
        document = view.document()
        self._positions = []
        if search:
            text = document.toPlainText()
            flags = re.MULTILINE | re.DOTALL
            if not self.caseCheck.isChecked():
                flags |= re.IGNORECASE
            if not self.regexCheck.isChecked():
                search = re.escape(search)
            try:
                matches = re.finditer(search, text, flags)
            except re.error:
                pass
            else:
                for m in matches:
                    c = QTextCursor(document)
                    c.setPosition(m.end())
                    c.setPosition(m.start(), QTextCursor.KeepAnchor)
                    self._positions.append(c)
        self.countLabel.setText(unicode(len(self._positions)))
        
    def findNext(self):
        view = self.currentView()
        if view and self._positions:
            positions = [c.position() for c in self._positions]
            index = bisect.bisect_right(positions, view.textCursor().position())
            if index < len(positions):
                view.setTextCursor(self._positions[index])
            else:
                view.setTextCursor(self._positions[0])
            view.ensureCursorVisible()

    def findPrevious(self):
        view = self.currentView()
        positions = [c.position() for c in self._positions]
        if view and positions:
            index = bisect.bisect_left(positions, view.textCursor().position()) - 1
            view.setTextCursor(self._positions[index])
            view.ensureCursorVisible()

    def keyPressEvent(self, ev):
        if ev.key() == Qt.Key_Tab:
            # prevent Tab from reaching the View widget
            self.window().focusNextChild()
            return
        # if in search mode, Up and Down jump between search results
        if not self._replace and self._positions and self.searchEntry.text() and not ev.modifiers():
            if ev.key() == Qt.Key_Up:
                self.findPrevious()
                return
            elif ev.key() ==  Qt.Key_Down:
                self.findNext()
                return
        # use enter or return for search next
        if ev.key() in (Qt.Key_Enter, Qt.Key_Return):
            self.findNext()
            return
        super(Search, self).keyPressEvent(ev)

    def doReplace(self, cursor):
        text = cursor.selection().toPlainText()
        search = self.searchEntry.text()
        replace = self.replaceEntry.text()
        ok = text == self.searchEntry.text()
        if self.regexCheck.isChecked():
            m = re.match(search, text)
            ok = False
            if m:
                try:
                    replace = m.expand(replace)
                    ok = True
                except re.error:
                    pass
        if ok:
            pos = cursor.position()
            cursor.insertText(replace)
            cursor.setPosition(pos, QTextCursor.KeepAnchor)
        return ok
        
    def slotReplace(self):
        view = self.currentView()
        if view and self._positions:
            positions = [c.position() for c in self._positions]
            index = bisect.bisect_left(positions, view.textCursor().position())
            if index >= len(positions):
                index = 0
            if self.doReplace(self._positions[index]):
                viewhighlighter.highlighter(view).highlight("search", self._positions, 1)
                if index < len(positions) - 1:
                    view.setTextCursor(self._positions[index+1])
                else:
                    view.setTextCursor(self._positions[0])
                view.ensureCursorVisible()
    
    def slotReplaceAll(self):
        view = self.currentView()
        if view:
            replaced = False
            cursors = self._positions
            if view.textCursor().hasSelection():
                cursors = [cursor for cursor in cursors if cursortools.contains(view.textCursor(), cursor)]
            view.textCursor().beginEditBlock()
            for cursor in cursors:
                if self.doReplace(cursor):
                    replaced = True
            view.textCursor().endEditBlock()
            if replaced:
                viewhighlighter.highlighter(view).highlight("search", self._positions, 1)
예제 #51
0
class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        self.home = os.getenv('HOME')
        self.fnames = list()  # list of file names to be converted
        self.docconv = False  # True when a documents conversion is running

        # parse command line arguments
        for i in QCoreApplication.argv()[1:]:
            i = codecs.utf_8_decode(os.path.abspath(i))[0]
            if os.path.isfile(i):
                self.fnames.append(i)
            else:
                print("ffmulticonverter: {0}: Not a file".format(i))

        addButton = QPushButton(self.tr('Add'))
        delButton = QPushButton(self.tr('Delete'))
        clearButton = QPushButton(self.tr('Clear'))
        vlayout1 = pyqttools.add_to_layout(QVBoxLayout(), addButton, delButton,
                                           clearButton, None)

        self.filesList = FilesList()
        self.filesList.setSelectionMode(QAbstractItemView.ExtendedSelection)
        hlayout1 = pyqttools.add_to_layout(QHBoxLayout(), self.filesList,
                                           vlayout1)

        output_label = QLabel(self.tr('Output folder:'))
        self.toLineEdit = QLineEdit()
        self.toLineEdit.setReadOnly(True)
        self.toToolButton = QToolButton()
        self.toToolButton.setText('...')
        hlayout2 = pyqttools.add_to_layout(QHBoxLayout(), output_label,
                                           self.toLineEdit, self.toToolButton)

        self.audiovideo_tab = AudioVideoTab(self)
        self.image_tab = ImageTab(self)
        self.document_tab = DocumentTab(self)

        self.tabs = [self.audiovideo_tab, self.image_tab, self.document_tab]
        tab_names = [
            self.tr('Audio/Video'),
            self.tr('Images'),
            self.tr('Documents')
        ]
        self.TabWidget = QTabWidget()
        for num, tab in enumerate(tab_names):
            self.TabWidget.addTab(self.tabs[num], tab)
        self.TabWidget.setCurrentIndex(0)

        self.origCheckBox = QCheckBox(
            self.tr('Save each file in the same\nfolder as input file'))
        self.deleteCheckBox = QCheckBox(self.tr('Delete original'))
        self.convertPushButton = QPushButton(self.tr('&Convert'))

        hlayout3 = pyqttools.add_to_layout(QHBoxLayout(), self.origCheckBox,
                                           self.deleteCheckBox, None)
        hlayout4 = pyqttools.add_to_layout(QHBoxLayout(), None,
                                           self.convertPushButton)
        final_layout = pyqttools.add_to_layout(QVBoxLayout(), hlayout1,
                                               self.TabWidget, hlayout2,
                                               hlayout3, hlayout4)

        self.statusBar = self.statusBar()
        self.dependenciesLabel = QLabel()
        self.statusBar.addPermanentWidget(self.dependenciesLabel, stretch=1)

        Widget = QWidget()
        Widget.setLayout(final_layout)
        self.setCentralWidget(Widget)

        c_act = pyqttools.create_action
        openAction = c_act(self, self.tr('Open'), QKeySequence.Open, None,
                           self.tr('Open a file'), self.add_files)
        convertAction = c_act(self, self.tr('Convert'), 'Ctrl+C', None,
                              self.tr('Convert files'), self.start_conversion)
        quitAction = c_act(self, self.tr('Quit'), 'Ctrl+Q', None,
                           self.tr('Quit'), self.close)
        edit_presetsAction = c_act(self, self.tr('Edit Presets'), 'Ctrl+P',
                                   None, self.tr('Edit Presets'), self.presets)
        importAction = c_act(self, self.tr('Import'), None, None,
                             self.tr('Import presets'), self.import_presets)
        exportAction = c_act(self, self.tr('Export'), None, None,
                             self.tr('Export presets'), self.export_presets)
        resetAction = c_act(self, self.tr('Reset'), None, None,
                            self.tr('Reset presets'), self.reset_presets)
        syncAction = c_act(self, self.tr('Synchronize'), None, None,
                           self.tr('Synchronize presets'), self.sync_presets)
        removeoldAction = c_act(self, self.tr('Remove old'), None, None,
                                self.tr('Remove old presets'),
                                self.removeold_presets)
        clearallAction = c_act(self, self.tr('Clear All'), None, None,
                               self.tr('Clear form'), self.clear_all)
        preferencesAction = c_act(self,
                                  self.tr('Preferences'), 'Alt+Ctrl+P', None,
                                  self.tr('Preferences'), self.preferences)
        aboutAction = c_act(self, self.tr('About'), 'Ctrl+?', None,
                            self.tr('About'), self.about)

        fileMenu = self.menuBar().addMenu(self.tr('File'))
        editMenu = self.menuBar().addMenu(self.tr('Edit'))
        presetsMenu = self.menuBar().addMenu(self.tr('Presets'))
        helpMenu = self.menuBar().addMenu(self.tr('Help'))
        pyqttools.add_actions(fileMenu,
                              [openAction, convertAction, None, quitAction])
        pyqttools.add_actions(presetsMenu, [
            edit_presetsAction, importAction, exportAction, resetAction, None,
            syncAction, removeoldAction
        ])
        pyqttools.add_actions(editMenu,
                              [clearallAction, None, preferencesAction])
        pyqttools.add_actions(helpMenu, [aboutAction])

        self.filesList.dropped.connect(self.url_dropped)
        addButton.clicked.connect(self.add_files)
        delButton.clicked.connect(self.delete_files)
        clearButton.clicked.connect(self.clear_fileslist)
        self.TabWidget.currentChanged.connect(
            lambda: self.tabs[0].moreButton.setChecked(False))
        self.origCheckBox.clicked.connect(lambda: self.toLineEdit.setEnabled(
            not self.origCheckBox.isChecked()))
        self.toToolButton.clicked.connect(self.open_dir)
        self.convertPushButton.clicked.connect(convertAction.triggered)

        del_shortcut = QShortcut(self)
        del_shortcut.setKey(Qt.Key_Delete)
        del_shortcut.activated.connect(self.delete_files)

        self.resize(MAIN_WIDTH, MAIN_HEIGHT)
        self.setWindowTitle('FF Multi Converter')

        QTimer.singleShot(0, self.check_for_dependencies)
        QTimer.singleShot(0, self.load_settings)
        QTimer.singleShot(0, self.audiovideo_tab.set_default_command)
        QTimer.singleShot(0, self.update_filesList)

    def load_settings(self):
        """Load settings values."""
        settings = QSettings()
        self.overwrite_existing = settings.value('overwrite_existing').toBool()
        self.default_output = unicode(
            settings.value('default_output').toString())
        self.prefix = unicode(settings.value('prefix').toString())
        self.suffix = unicode(settings.value('suffix').toString())
        self.avconv_prefered = settings.value('avconv_prefered').toBool()
        self.default_command = unicode(
            settings.value('default_command').toString())
        if not self.default_command:
            self.default_command = DEFAULT_COMMAND

        self.toLineEdit.setText(self.default_output)

    def current_tab(self):
        """Return the corresponding object of the selected tab."""
        for i in self.tabs:
            if self.tabs.index(i) == self.TabWidget.currentIndex():
                return i

    def update_filesList(self):
        """Clear self.filesList and add to it all items of self.fname."""
        self.filesList.clear()
        for i in self.fnames:
            self.filesList.addItem(i)

    def url_dropped(self, links):
        """
        Append to self.fnames each file name that not already exists
        and update self.filesList.
        """
        for url in links:
            if os.path.isfile(url) and not url in self.fnames:
                self.fnames.append(url)
        self.update_filesList()

    def add_files(self):
        """
        Get file names using a standard Qt dialog.
        Append to self.fnames each file name that not already exists
        and update self.filesList.
        """
        # Create lists holding file formats extension.
        # To be passed in QFileDialog.getOpenFileNames().
        all_files = '*'
        audiovideo_files = ' '.join(
            ['*.' + i for i in self.audiovideo_tab.formats])
        img_formats = self.image_tab.formats[:]
        img_formats.extend(self.image_tab.extra_img)
        image_files = ' '.join(['*.' + i for i in img_formats])
        document_files = ' '.join(
            ['*.' + i for i in self.document_tab.formats])
        formats = [all_files, audiovideo_files, image_files, document_files]
        strings = [
            self.tr('All Files'),
            self.tr('Audio/Video Files'),
            self.tr('Image Files'),
            self.tr('Document Files')
        ]

        filters = ''
        for string, extensions in zip(strings, formats):
            filters += string + ' ({0});;'.format(extensions)
        filters = filters[:-2]  # remove last ';;'

        fnames = QFileDialog.getOpenFileNames(
            self, 'FF Multi Converter - ' + self.tr('Choose File'), self.home,
            filters)

        if fnames:
            for i in fnames:
                if not i in self.fnames:
                    self.fnames.append(unicode(i))
            self.update_filesList()

    def delete_files(self):
        """
        Get selectedItems of self.filesList, remove them from self.fnames and
        update the filesList.
        """
        items = self.filesList.selectedItems()
        if items:
            for i in items:
                self.fnames.remove(unicode(i.text()))
            self.update_filesList()

    def clear_fileslist(self):
        """Make self.fnames empty and update self.filesList."""
        self.fnames = []
        self.update_filesList()

    def clear_all(self):
        """Clear all values of graphical widgets."""
        self.toLineEdit.clear()
        self.origCheckBox.setChecked(False)
        self.deleteCheckBox.setChecked(False)
        self.clear_fileslist()

        self.audiovideo_tab.clear()
        self.image_tab.clear()

    def open_dir(self):
        """
        Get a directory name using a standard QtDialog and update
        self.toLineEdit with dir's name.
        """
        if self.toLineEdit.isEnabled():
            output = QFileDialog.getExistingDirectory(
                self,
                'FF Multi Converter - ' + self.tr('Choose output destination'),
                self.home)
            #output = unicode(output)
            if output:
                self.toLineEdit.setText(output)

    def preferences(self):
        """Open the preferences dialog."""
        dialog = preferences_dlg.Preferences(self)
        if dialog.exec_():
            self.load_settings()

    def presets(self):
        """Open the presets dialog."""
        dialog = presets_dlgs.ShowPresets(self)
        dialog.exec_()

    def import_presets(self):
        presets_dlgs.ShowPresets().import_presets()

    def export_presets(self):
        presets_dlgs.ShowPresets().export_presets()

    def reset_presets(self):
        presets_dlgs.ShowPresets().reset()

    def sync_presets(self):
        presets_dlgs.ShowPresets().synchronize()

    def removeold_presets(self):
        presets_dlgs.ShowPresets().remove_old()

    def ok_to_continue(self):
        """
        Check if everything is ok to continue with conversion.

        Check if:
        - At least one file has given for conversion.
        - An output folder has given.
        - Output folder exists.

        Return False if an error arises, else True.
        """
        try:
            if not self.fnames:
                raise ValidationError(
                    self.tr('You must add at least one file to convert!'))
            elif not self.origCheckBox.isChecked(
            ) and not self.toLineEdit.text():
                raise ValidationError(
                    self.tr('You must choose an output folder!'))
            elif (not self.origCheckBox.isChecked()
                  and not os.path.exists(unicode(self.toLineEdit.text()))):
                raise ValidationError(
                    self.tr('Output folder does not exists!'))
            if not self.current_tab().ok_to_continue():
                return False
            return True

        except ValidationError as e:
            QMessageBox.warning(self, 'FF Multi Converter - ' + \
                                self.tr('Error!'), unicode(e))
            return False

    def output_ext(self):
        """Extract the desired output file extension from GUI and return it."""
        tab = self.current_tab()
        if tab.name == 'AudioVideo':
            if self.audiovideo_tab.extLineEdit.isEnabled():
                ext_to = self.audiovideo_tab.extLineEdit.text()
            else:
                ext_to = self.audiovideo_tab.extComboBox.currentText()
        elif tab.name == 'Images':
            ext_to = tab.extComboBox.currentText()
        else:
            ext_to = str(tab.convertComboBox.currentText()).split()[-1]

        return str('.' + ext_to)

    def create_paths_list(self, files_list, ext_to, prefix, suffix, output,
                          orig_dir, overwrite_existing):
        """
        Keyword arguments:
        files_list -- list with files to be converted
        ext_to     -- the extension to which each file must be converted to
        prefix     -- string that will be added as a prefix to all filenames
        suffix     -- string that will be added as a suffix to all filenames
        output     -- the output folder
        orig_dir   -- if True, each file will be saved at its original directory
                      else, files will be saved at output
        overwrite_existing -- if False, a '~' will be added as prefix to
                              filenames

        Create and return a list with dicts.
        Each dict will have only one key and one corresponding value.
        Key will be a file to be converted and it's value will be the name
        of the new converted file.

        Example list:
        [{"/foo/bar.png" : "/foo/bar.bmp"}, {"/f/bar2.png" : "/f/bar2.bmp"}]
        """
        assert ext_to.startswith('.'), 'ext_to must start with a dot (.)'

        conversion_list = []
        dummy = []

        for _file in files_list:
            _dir, name = os.path.split(_file)
            y = prefix + os.path.splitext(name)[0] + suffix + ext_to

            if orig_dir:
                y = _dir + '/' + y
            else:
                y = output + '/' + y

            if not overwrite_existing:
                while os.path.exists(y) or y in dummy:
                    _dir2, _name2 = os.path.split(y)
                    y = _dir2 + '/~' + _name2

            dummy.append(y)
            # Add quotations to paths in order to avoid error in special
            # cases such as spaces or special characters.
            _file = '"' + _file + '"'
            y = '"' + y + '"'

            _dict = {}
            _dict[_file] = y
            conversion_list.append(_dict)

        return conversion_list

    def start_conversion(self):
        """
        Extract the appropriate information from GUI and call the
        Progress dialog with the suitable argumens.
        """
        if not self.ok_to_continue():
            return

        ext_to = self.output_ext()
        _list = self.create_paths_list(self.fnames, ext_to, self.prefix,
                                       self.suffix,
                                       unicode(self.toLineEdit.text()),
                                       self.origCheckBox.isChecked(),
                                       self.overwrite_existing)

        tab = self.current_tab()
        cmd = ''
        size = str('')
        mntaspect = False

        if tab.name == 'AudioVideo':
            cmd = tab.commandLineEdit.text()
        elif tab.name == 'Images':
            width = tab.widthLineEdit.text()
            if width:
                height = tab.heightLineEdit.text()
                size = str('{0}x{1}'.format(width, height))
                mntaspect = tab.aspectCheckBox.isChecked()
        else:
            self.docconv = True

        dialog = progress.Progress(_list, tab.name, cmd,
                                   not self.avconv_prefered, size, mntaspect,
                                   self.deleteCheckBox.isChecked(), self)
        dialog.show()

    def is_installed(self, program):
        """Return True if program appears in user's PATH var, else False."""
        for path in os.getenv('PATH').split(os.pathsep):
            fpath = os.path.join(path, program)
            if os.path.exists(fpath) and os.access(fpath, os.X_OK):
                return True
        return False

    def check_for_dependencies(self):
        """
        Check if each one of the program dependencies are installed and
        update self.dependenciesLabel with the appropriate message.
        """
        self.ffmpeg = self.is_installed('ffmpeg')
        self.avconv = self.is_installed('avconv')
        self.unoconv = self.is_installed('unoconv')
        self.pmagick = True
        try:
            # We tried to import PythonMagick earlier.
            # If that raises an error it means that PythonMagick is not
            # available on the system.
            PythonMagick
        except NameError:
            self.pmagick = False

        missing = []
        if not self.ffmpeg and not self.avconv:
            missing.append('FFmpeg/avconv')
        if not self.unoconv:
            missing.append('unoconv')
        if not self.pmagick:
            missing.append('PythonMagick')

        if missing:
            missing = ', '.join(missing)
            status = self.tr('Missing dependencies:') + ' ' + missing
            self.dependenciesLabel.setText(status)

    def about(self):
        """Call the about dialog with the appropriate values."""
        link = 'http://sites.google.com/site/ffmulticonverter/'
        msg = self.tr('Convert among several file types to other extensions')
        if len(msg) > 54:
            # break line if msg is too long to fit the window
            nmsg = ''
            for n, w in enumerate(msg.split(' ')):
                if len(nmsg) > 54:
                    break
                nmsg += w + ' '
            nmsg += '<br>' + msg[len(nmsg):]
            msg = nmsg
        text = '''<b> FF Multi Converter {0} </b>
                 <p>{1}
                 <p><a href="{2}">FF Multi Converter - Home Page</a>
                 <p>Copyright &copy; 2011-2013 Ilias Stamatis
                 <br>License: GNU GPL3
                 <p>Python {3} - Qt {4} - PyQt {5} on {6}'''\
                 .format(__version__, msg, link, platform.python_version()[:5],
                         QT_VERSION_STR, PYQT_VERSION_STR, platform.system())
        image = ':/ffmulticonverter.png'
        authors = 'Ilias Stamatis <*****@*****.**>\n\n'
        authors += 'Contributors:\nPanagiotis Mavrogiorgos'
        transl_list = [['[bg] Bulgarian', 'Vasil Blagoev'],
                       ['[cs] Czech', 'Petr Simacek'],
                       ['[de_DE] German (Germany)', 'Stefan Wilhelm'],
                       ['[el] Greek', 'Ilias Stamatis'],
                       ['[fr] French', 'Rémi Mercier'
                        '\n     Lebarhon'],
                       ['[hu] Hungarian', 'Farkas Norbert'],
                       ['[it] Italian', 'Fabio Boccaletti'],
                       [
                           '[pl_PL] Polish (Poland)', 'Lukasz Koszy'
                           '\n     Piotr Surdacki'
                       ], ['[pt] Portuguese', 'Sérgio Marques'],
                       ['[pt_BR] Portuguese (Brasil)', 'José Humberto A Melo'],
                       ['[ru] Russian', 'Andrew Lapshin'],
                       ['[tu] Turkish', 'Tayfun Kayha'],
                       ['[zh_CN] Chinese (China)', 'Dianjin Wang']]
        translators = ''
        for i in transl_list:
            translators += '{0}\n     {1}\n\n'.format(i[0], i[1])
        translators = translators[:-2]

        dialog = about_dlg.AboutDialog(text, image, authors, translators, self)
        dialog.exec_()
예제 #52
0
class SessionEditor(QDialog):
    def __init__(self, parent=None):
        super(SessionEditor, self).__init__(parent)
        self.setWindowModality(Qt.WindowModal)
        
        layout = QVBoxLayout()
        self.setLayout(layout)
        
        grid = QGridLayout()
        layout.addLayout(grid)
        
        self.name = QLineEdit()
        self.nameLabel = l = QLabel()
        l.setBuddy(self.name)
        grid.addWidget(l, 0, 0)
        grid.addWidget(self.name, 0, 1)
        
        self.autosave = QCheckBox()
        grid.addWidget(self.autosave, 1, 1)
        
        self.basedir = widgets.urlrequester.UrlRequester()
        self.basedirLabel = l = QLabel()
        l.setBuddy(self.basedir)
        grid.addWidget(l, 2, 0)
        grid.addWidget(self.basedir, 2, 1)
        
        layout.addWidget(widgets.Separator())
        self.buttons = b = QDialogButtonBox(self)
        layout.addWidget(b)
        b.setStandardButtons(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        b.accepted.connect(self.accept)
        b.rejected.connect(self.reject)
        help.addButton(b, "sessions")
        app.translateUI(self)
        
    def translateUI(self):
        self.nameLabel.setText(_("Name:"))
        self.autosave.setText(_("Always save the list of documents in this session"))
        self.basedirLabel.setText(_("Base directory:"))
    
    def load(self, name):
        settings = sessions.sessionGroup(name)
        self.autosave.setChecked(settings.value("autosave", True, bool))
        self.basedir.setPath(settings.value("basedir", "", type("")))
        # more settings here
        
    def save(self, name):
        settings = sessions.sessionGroup(name)
        settings.setValue("autosave", self.autosave.isChecked())
        settings.setValue("basedir", self.basedir.path())
        # more settings here
        
    def defaults(self):
        self.autosave.setChecked(True)
        self.basedir.setPath('')
        # more defaults here
        
    def edit(self, name=None):
        self._originalName = name
        if name:
            caption = _("Edit session: {name}").format(name=name)
            self.name.setText(name)
            self.load(name)
        else:
            caption = _("Edit new session")
            self.name.clear()
            self.name.setFocus()
            self.defaults()
        self.setWindowTitle(app.caption(caption))
        if self.exec_():
            # name changed?
            name = self.name.text()
            if self._originalName and name != self._originalName:
                sessions.renameSession(self._originalName, name)
            self.save(name)
            return name

    def done(self, result):
        if not result or self.validate():
            super(SessionEditor, self).done(result)
        
    def validate(self):
        """Checks if the input is acceptable.
        
        If this method returns True, the dialog is accepted when OK is clicked.
        Otherwise a messagebox could be displayed, and the dialog will remain
        visible.
        """
        name = self.name.text().strip()
        self.name.setText(name)
        if not name:
            self.name.setFocus()
            QMessageBox.warning(self, app.caption(_("Warning")),
                _("Please enter a session name."))
            if self._originalName:
                self.name.setText(self._originalName)
            return False
        
        elif name == 'none':
            self.name.setFocus()
            QMessageBox.warning(self, app.caption(_("Warning")),
                _("Please do not use the name '{name}'.".format(name="none")))
            return False
        
        elif self._originalName != name and name in sessions.sessionNames():
            self.name.setFocus()
            box = QMessageBox(QMessageBox.Warning, app.caption(_("Warning")),
                _("Another session with the name {name} already exists.\n\n"
                  "Do you want to overwrite it?").format(name=name),
                QMessageBox.Discard | QMessageBox.Cancel, self)
            box.button(QMessageBox.Discard).setText(_("Overwrite"))
            result = box.exec_()
            if result != QMessageBox.Discard:
                return False
            
        return True
예제 #53
0
class NumberFormatDlg(QDialog):
    def __init__(self, format, callback, parent=None):
        super(NumberFormatDlg, self).__init__(parent)
        self.format = format
        self.callback = callback
        self.create_widgets()
        self.layout_widgets()
        self.create_connections()
        self.setWindowTitle("Set Number Format (`Live')")

    def create_widgets(self):
        punctuationRe = QRegExp(r"[ ,;:.]")
        self.thousandsLabel = QLabel("&Thousands separator")
        self.thousandsEdit = QLineEdit(self.format["thousandsseparator"])
        self.thousandsLabel.setBuddy(self.thousandsEdit)
        self.thousandsEdit.setMaxLength(1)
        self.thousandsEdit.setValidator(QRegExpValidator(punctuationRe, self))
        self.decimalMarkerLabel = QLabel("Decimal &marker")
        self.decimalMarkerEdit = QLineEdit(self.format["decimalmarker"])
        self.decimalMarkerLabel.setBuddy(self.decimalMarkerEdit)
        self.decimalMarkerEdit.setMaxLength(1)
        self.decimalMarkerEdit.setValidator(
            QRegExpValidator(punctuationRe, self))
        self.decimalMarkerEdit.setInputMask("X")
        self.decimalPlacesLabel = QLabel("&Decimal places")
        self.decimalPlacesSpinBox = QSpinBox()
        self.decimalPlacesLabel.setBuddy(self.decimalPlacesSpinBox)
        self.decimalPlacesSpinBox.setRange(0, 6)
        self.decimalPlacesSpinBox.setValue(self.format["decimalplaces"])
        self.redNegativesCheckBox = QCheckBox("&Red negative numbers")
        self.redNegativesCheckBox.setChecked(self.format["rednegatives"])

    def layout_widgets(self):
        grid = QGridLayout()
        grid.addWidget(self.thousandsLabel, 0, 0)
        grid.addWidget(self.thousandsEdit, 0, 1)
        grid.addWidget(self.decimalMarkerLabel, 1, 0)
        grid.addWidget(self.decimalMarkerEdit, 1, 1)
        grid.addWidget(self.decimalPlacesLabel, 2, 0)
        grid.addWidget(self.decimalPlacesSpinBox, 2, 1)
        grid.addWidget(self.redNegativesCheckBox, 3, 0, 1, 2)
        self.setLayout(grid)

    def create_connections(self):
        self.thousandsEdit.textEdited.connect(self.checkAndFix)
        self.decimalMarkerEdit.textEdited.connect(self.checkAndFix)
        self.decimalPlacesSpinBox.valueChanged.connect(self.apply)
        self.redNegativesCheckBox.toggled.connect(self.apply)

    def checkAndFix(self):
        thousands = unicode(self.thousandsEdit.text())
        decimal = unicode(self.decimalMarkerEdit.text())
        if thousands == decimal:
            self.thousandsEdit.clear()
            self.thousandsEdit.setFocus()
        if len(decimal) == 0:
            self.decimalMarkerEdit.setText(".")
            self.decimalMarkerEdit.selectAll()
            self.decimalMarkerEdit.setFocus()
        self.apply()

    def apply(self):
        self.format["thousandsseparator"] = (unicode(
            self.thousandsEdit.text()))
        self.format["decimalmarker"] = (unicode(self.decimalMarkerEdit.text()))
        self.format["decimalplaces"] = (self.decimalPlacesSpinBox.value())
        self.format["rednegatives"] = (self.redNegativesCheckBox.isChecked())
        self.callback()
예제 #54
0
class SessionEditor(QDialog):
    def __init__(self, parent=None):
        super(SessionEditor, self).__init__(parent)
        self.setWindowModality(Qt.WindowModal)
        
        layout = QVBoxLayout()
        self.setLayout(layout)
        
        grid = QGridLayout()
        layout.addLayout(grid)
        
        self.name = QLineEdit()
        self.nameLabel = l = QLabel()
        l.setBuddy(self.name)
        grid.addWidget(l, 0, 0)
        grid.addWidget(self.name, 0, 1)
        
        self.autosave = QCheckBox()
        grid.addWidget(self.autosave, 1, 1)
        
        self.basedir = widgets.urlrequester.UrlRequester()
        self.basedirLabel = l = QLabel()
        l.setBuddy(self.basedir)
        grid.addWidget(l, 2, 0)
        grid.addWidget(self.basedir, 2, 1)
        
        self.inclPaths = ip = QGroupBox(self, checkable=True, checked=False)
        ipLayout = QVBoxLayout()
        ip.setLayout(ipLayout)
        
        self.replPaths = QCheckBox()
        ipLayout.addWidget(self.replPaths)
        self.replPaths.toggled.connect(self.toggleReplace)
        
        self.include = widgets.listedit.FilePathEdit()
        self.include.listBox.setDragDropMode(QAbstractItemView.InternalMove)
        ipLayout.addWidget(self.include)
        
        grid.addWidget(ip, 3, 1)
        
        self.revt = QPushButton(self)
        self.clear = QPushButton(self)
        self.revt.clicked.connect(self.revertPaths)
        self.clear.clicked.connect(self.clearPaths)
       
        self.include.layout().addWidget(self.revt, 5, 1)
        self.include.layout().addWidget(self.clear, 6, 1)
        
        layout.addWidget(widgets.Separator())
        self.buttons = b = QDialogButtonBox(self)
        layout.addWidget(b)
        b.setStandardButtons(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        b.accepted.connect(self.accept)
        b.rejected.connect(self.reject)
        userguide.addButton(b, "sessions")
        app.translateUI(self)
        
    def translateUI(self):
        self.nameLabel.setText(_("Name:"))
        self.autosave.setText(_("Always save the list of documents in this session"))
        self.basedirLabel.setText(_("Base directory:"))
        self.inclPaths.setTitle(_("Use session specific include path"))
        self.replPaths.setText(_("Replace global path"))
        self.replPaths.setToolTip(_("When checked, paths in LilyPond preferences are not included."))
        self.revt.setText(_("Copy global path"))
        self.revt.setToolTip(_("Add and edit the path from LilyPond preferences."))
        self.clear.setText(_("Clear"))
        self.clear.setToolTip(_("Remove all paths."))
    
    def load(self, name):
        settings = sessions.sessionGroup(name)
        self.autosave.setChecked(settings.value("autosave", True, bool))
        self.basedir.setPath(settings.value("basedir", "", type("")))
        try:
            paths = settings.value("include-path", [], type(""))
        except TypeError:
            paths = []
        self.include.setValue(paths)
        self.inclPaths.setChecked(settings.value("set-paths", False, bool))
        self.replPaths.setChecked(settings.value("repl-paths", False, bool))
        if not self.replPaths.isChecked():
            self.addDisabledGenPaths()
            self.revt.setEnabled(False)
        # more settings here
        
    def fetchGenPaths(self):
        """Fetch paths from general preferences."""
        s = QSettings()
        s.beginGroup("lilypond_settings")
        try:
            return s.value("include_path", [], type(""))
        except TypeError:
            return []
            
    def addDisabledGenPaths(self):
        """Add global paths, but set as disabled."""
        genPaths = self.fetchGenPaths()
        for p in genPaths:
            i = QListWidgetItem(p, self.include.listBox)
            i.setFlags(Qt.NoItemFlags)
            
    def toggleReplace(self):
        """Called when user changes setting for replace of global paths."""
        if self.replPaths.isChecked():
            items = self.include.items()
            for i in items:
                if not (i.flags() & Qt.ItemIsEnabled): #is not enabled
                  self.include.listBox.takeItem(self.include.listBox.row(i))
            self.revt.setEnabled(True)
        else:
            self.addDisabledGenPaths()
            self.revt.setEnabled(False)
            
    def revertPaths(self):
        """Add global paths (for edit)."""
        genPaths = self.fetchGenPaths()
        for p in genPaths:
            i = QListWidgetItem(p, self.include.listBox)
        
    def clearPaths(self):
        """Remove all active paths."""
        items = self.include.items()
        for i in items:
            if i.flags() & Qt.ItemIsEnabled:
              self.include.listBox.takeItem(self.include.listBox.row(i))
        
    def save(self, name):
        settings = sessions.sessionGroup(name)
        settings.setValue("autosave", self.autosave.isChecked())
        settings.setValue("basedir", self.basedir.path())
        settings.setValue("set-paths", self.inclPaths.isChecked())
        settings.setValue("repl-paths", self.replPaths.isChecked())
        path = [i.text() for i in self.include.items() if i.flags() & Qt.ItemIsEnabled]
        settings.setValue("include-path", path)
        # more settings here
        
    def defaults(self):
        self.autosave.setChecked(True)
        self.basedir.setPath('')
        self.inclPaths.setChecked(False)
        self.replPaths.setChecked(False)
        self.addDisabledGenPaths()
        self.revt.setEnabled(False)
        # more defaults here
        
    def edit(self, name=None):
        self._originalName = name
        if name:
            caption = _("Edit session: {name}").format(name=name)
            self.name.setText(name)
            self.load(name)
        else:
            caption = _("Edit new session")
            self.name.clear()
            self.name.setFocus()
            self.defaults()
        self.setWindowTitle(app.caption(caption))
        if self.exec_():
            # name changed?
            name = self.name.text()
            if self._originalName and name != self._originalName:
                sessions.renameSession(self._originalName, name)
            self.save(name)
            return name

    def done(self, result):
        if not result or self.validate():
            super(SessionEditor, self).done(result)
        
    def validate(self):
        """Checks if the input is acceptable.
        
        If this method returns True, the dialog is accepted when OK is clicked.
        Otherwise a messagebox could be displayed, and the dialog will remain
        visible.
        """
        name = self.name.text().strip()
        self.name.setText(name)
        if not name:
            self.name.setFocus()
            QMessageBox.warning(self, app.caption(_("Warning")),
                _("Please enter a session name."))
            if self._originalName:
                self.name.setText(self._originalName)
            return False
        
        elif name == '-':
            self.name.setFocus()
            QMessageBox.warning(self, app.caption(_("Warning")),
                _("Please do not use the name '{name}'.".format(name="-")))
            return False
        
        elif self._originalName != name and name in sessions.sessionNames():
            self.name.setFocus()
            box = QMessageBox(QMessageBox.Warning, app.caption(_("Warning")),
                _("Another session with the name {name} already exists.\n\n"
                  "Do you want to overwrite it?").format(name=name),
                QMessageBox.Discard | QMessageBox.Cancel, self)
            box.button(QMessageBox.Discard).setText(_("Overwrite"))
            result = box.exec_()
            if result != QMessageBox.Discard:
                return False
            
        return True
예제 #55
0
class MainWindow(QMainWindow):
    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)
        self.setWindowFlags(Qt.FramelessWindowHint
                            | Qt.WindowMinimizeButtonHint)
        self.setWindowTitle(u"鱿鱼")
        self.setFixedSize(800, 600)
        self.setObjectName('principal')
        self.createGUI()

    def createGUI(self):
        self.frame_window = QWidget(self)
        self.frame_window.setGeometry(0, 0, 800, 40)
        self.frame_window.setObjectName('frame_window')
        self.title_frame = QLabel(self.frame_window)
        self.title_frame.setGeometry(0, 0, 800, 40)
        self.title_frame.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
        self.title_frame.setFont(QFont("微软雅黑", 20, QFont.Bold))
        self.title_frame.setText(u" 鱿鱼-阿里云白名单设置")
        self.title_frame.setObjectName('title_frame')
        # buttons
        clsfont = self.font() or QFont()
        clsfont.setFamily('Webdings')
        self.button_close = QPushButton('r', self.frame_window, font=clsfont)
        self.button_close.setGeometry(760, 0, 40, 40)
        self.button_close.setObjectName('button_close')
        self.button_close.setToolTip(u'关闭')
        self.button_close.enterEvent(
            self.button_close.setCursor(Qt.PointingHandCursor))
        self.button_min = QPushButton('0', self.frame_window, font=clsfont)
        self.button_min.setGeometry(720, 0, 40, 40)
        self.button_min.setObjectName('button_min')
        self.button_min.setToolTip(u'最小化')
        self.button_min.enterEvent(
            self.button_min.setCursor(Qt.PointingHandCursor))
        ###左边选择栏部分
        self.GroupBox_checkbox = QGroupBox(self)
        self.GroupBox_checkbox.setTitle(u'选择白名单组')
        self.GroupBox_checkbox.setGeometry(10, 50, 200, 540)
        self.ecs_test = QCheckBox(u'测试环境服务器', self.GroupBox_checkbox)
        self.ecs_test.enterEvent(self.ecs_test.setCursor(
            Qt.PointingHandCursor))
        self.ecs_test.setChecked(True)
        self.ecs_test.setGeometry(20, 30, 150, 30)
        self.rds_mysql = QCheckBox(u'MySQL数据库', self.GroupBox_checkbox)
        self.rds_mysql.enterEvent(
            self.rds_mysql.setCursor(Qt.PointingHandCursor))
        self.rds_mysql.setChecked(True)
        self.rds_mysql.setGeometry(20, 60, 150, 30)
        self.rds_sqlserver = QCheckBox(u'SQLServer数据库', self.GroupBox_checkbox)
        self.rds_sqlserver.enterEvent(
            self.rds_sqlserver.setCursor(Qt.PointingHandCursor))
        self.rds_sqlserver.setChecked(True)
        self.rds_sqlserver.setGeometry(20, 90, 150, 30)
        ###右边IP设置部分
        self.GroupBox_ipset = QGroupBox(self)
        self.GroupBox_ipset.setTitle(u'公网IP配置')
        self.GroupBox_ipset.setGeometry(220, 50, 570, 200)
        self.label_outip = QLabel(self.GroupBox_ipset,
                                  objectName="label_outip")
        self.label_outip.setText(u'公网IP:')
        self.label_outip.setGeometry(15, 30, 75, 30)
        self.line_outip = QLineEdit(self.GroupBox_ipset)
        self.line_outip.setMinimumWidth(200)
        self.line_outip.setGeometry(85, 30, 150, 30)
        self.line_outip.setFont(QFont("Timers", 13, QFont.Bold))
        self.line_outip.setStyleSheet("color:green")
        self.button_getip = QPushButton(u'自动获取公网IP',
                                        self.GroupBox_ipset,
                                        objectName="button_getip")
        self.button_getip.setToolTip(u'从ip138上抓取本机公网IP')
        self.button_getip.enterEvent(
            self.button_getip.setCursor(Qt.PointingHandCursor))
        self.button_getip.setGeometry(300, 30, 110, 30)
        self.button_setup = QPushButton(u'添加',
                                        self.GroupBox_ipset,
                                        objectName="button_setup")
        self.button_setup.enterEvent(
            self.button_setup.setCursor(Qt.PointingHandCursor))
        self.button_setup.setToolTip(u'将该IP添加至已选白名单组中')
        self.button_setup.setGeometry(430, 30, 110, 30)
        ###右边消息输出部分
        self.GroupBox_text = QGroupBox(self)
        self.GroupBox_text.setGeometry(220, 260, 570, 330)
        self.browser_text = QTextBrowser(self.GroupBox_text)
        self.browser_text.setGeometry(0, 0, 570, 330)
        self.browser_text.setFont(QFont("Roman times", 12))
        self.browser_text.setObjectName('browser_text')

        # conexiones
        self.button_close.clicked.connect(self.close)
        self.button_min.clicked.connect(self.showMinimized)
        self.button_getip.clicked.connect(self.auto_ip)
        self.button_setup.clicked.connect(self.setup)

    def auto_ip(self):
        self.line_outip.clear()
        self.button_getip.setEnabled(False)
        self.th_get_ip = GETIP()
        self.th_get_ip.ip_line_Signal.connect(self.show_ip_info)
        self.th_get_ip.start()

    def show_ip_info(self, ip=None, status=1):
        self.button_getip.setEnabled(True)
        if status:
            self.line_outip.setText(ip)
        else:
            self.browser_text.append(ip)

    def setup(self):
        myip = self.line_outip.text()
        if myip and validate_ip(myip):
            check_list = []
            if self.ecs_test.isChecked():
                check_list.append('ecs_test')
            if self.rds_mysql.isChecked():
                check_list.append('rds_mysql')
            if self.rds_sqlserver.isChecked():
                check_list.append('rds_sqlserver')
            if len(check_list) == 0:
                self.browser_text.append(u'没什么事可做的~')
            else:
                self.button_setup.setEnabled(False)
                self.th_setup = SETIP(myip, check_list)
                self.th_setup.text_browser_Signal.connect(self.show_text)
                self.th_setup.start()
        else:
            self.browser_text.append(u'请填入正确的IP地址!')

    def show_text(self, text=None, end=0):
        if end:
            self.button_setup.setEnabled(True)
        if text:
            self.browser_text.append(text)

    def mousePressEvent(self, event):
        self.offset = event.pos()

    def mouseMoveEvent(self, event):
        x = event.globalX()
        y = event.globalY()
        x_w = self.offset.x()
        y_w = self.offset.y()
        self.move(x - x_w, y - y_w)