示例#1
0
class CheckableComboBox(QtGui.QWidget):
    """
    A combo box with selectable items.
    """

    optionSelected = QtCore.Signal(str)

    def __init__(self, title, options, selected=None, icons=None, parent=None):
        QtGui.QWidget.__init__(self, parent)
        layout = QtGui.QVBoxLayout(self)

        self.__btn = btn = QtGui.QPushButton(title)
        btn.setFocusPolicy(QtCore.Qt.NoFocus)
        btn.setMaximumHeight(22)
        btn.setFlat(True)
        btn.setContentsMargins(0, 0, 0, 0)

        self.__menu = menu = QtGui.QMenu(self)
        btn.setMenu(menu)

        self.setOptions(options, selected, icons)

        layout.addWidget(btn)

        btn.toggled.connect(btn.showMenu)
        menu.triggered.connect(
            lambda action: self.optionSelected.emit(action.text()))

    def options(self):
        return [a.text() for a in self.__menu.actions()]

    def setOptions(self, options, selected=None, icons=None):
        if selected and not isinstance(selected, (set, dict)):
            selected = set(selected)

        menu = self.__menu
        menu.clear()

        for opt, icon in izip_longest(options, icons or []):
            a = QtGui.QAction(menu)
            a.setText(opt)
            a.setCheckable(True)
            if selected and opt in selected:
                a.setChecked(True)
            if icon:
                a.setIcon(icons[i])
            menu.addAction(a)

    def setSelected(self, options):
        opts = set(options)
        for action in self.__menu.actions():
            checked = action.text() in opts
            action.setChecked(checked)

    def selectedOptions(self):
        return [a.text() for a in self.__menu.actions() if a.isChecked()]
示例#2
0
class JobColumnWidget(QtGui.QScrollArea):

    DATA_ROLE = FilterableListBox.DATA_ROLE

    selectionChanged = QtCore.Signal(list)

    def __init__(self, parent=None):
        super(JobColumnWidget, self).__init__(parent)

        self.__currentJob = None
        self.__currentLayer = None
        self.__currentTask = None

        self.setFocusPolicy(QtCore.Qt.NoFocus)

        contentWidget = QtGui.QWidget(self)
        self.setWidget(contentWidget)
        self.setWidgetResizable(True)

        mainLayout = QtGui.QHBoxLayout(contentWidget)

        self._jobWidget = job = JobSelectionWidget(self)
        job.setMinimumWidth(220)

        self._layerWidget = layer = FilterableListBox(parent=self)
        layer.setLabel("Layer:")
        layer.setMinimumWidth(180)

        self._taskWidget = task = FilterableListBox(parent=self)
        task.setLabel("Task:")
        task.setMinimumWidth(120)

        mainLayout.addWidget(job)
        mainLayout.addWidget(layer)
        mainLayout.addWidget(task)

        # connections
        job.selectionChanged.connect(self._jobSelectionChanged)
        job.valueClicked.connect(layer.clearSelection)
        job.valueClicked.connect(task.clearSelection)

        layer.selectionChanged.connect(self._layerSelectionChanged)
        layer.valueClicked.connect(task.clearSelection)

        task.selectionChanged.connect(self._taskSelectionChanged)

    @property
    def currentJob(self):
        return self.__currentJob

    @property
    def currentLayer(self):
        return self.__currentLayer

    def reset(self):
        self._clearTask()
        self._clearLayer()
        self._clearJob()

    def setJobFilter(self, val):
        self._jobWidget.setFilter(val, selectFirst=True)

    def setLayerFilter(self, val):
        self._layerWidget.setFilter(val, selectFirst=True)

    def setTaskFilter(self, val):
        self._taskWidget.setFilter(val, selectFirst=True)

    def setSingleSelections(self, enabled):
        for w in (self._jobWidget, self._layerWidget, self._taskWidget):
            w.setSingleSelections(enabled)

    def getSelection(self):
        for w in (self._taskWidget, self._layerWidget, self._jobWidget):
            items = w.getSelectedValues(self.DATA_ROLE)
            if items:
                return items

        return []

    def setLayersEnabled(self, enabled):
        self._layerWidget.clearSelection(clearFilter=False)
        self._layerWidget.setEnabled(enabled)
        self.setTasksEnabled(enabled)

    def setTasksEnabled(self, enabled):
        self._taskWidget.clearSelection(clearFilter=False)
        self._taskWidget.setEnabled(enabled)

    def _jobSelectionChanged(self, selection):
        self.__currentJob = None
        self._clearTask()

        count = len(selection)
        if count != 1:
            self._clearLayer()
            return

        jobs = self._jobWidget.getSelectedValues(self.DATA_ROLE)
        if not jobs:
            return

        self.__currentJob = jobs[0]

        if self._layerWidget.isEnabled():
            layers = self.__currentJob.get_layers()
            layerNames = [l.name for l in layers]
            self._layerWidget.setStringList(layerNames, data=layers)

        self.selectionChanged.emit(jobs)

    def _layerSelectionChanged(self, selection):
        self.__currentLayer = None

        count = len(selection)
        if count != 1:
            self._clearTask()
            return

        self.__currentLayer = None
        layers = self._layerWidget.getSelectedValues(self.DATA_ROLE)
        if not layers:
            return

        layer = layers[0]
        self.__currentLayer = layer

        if self._taskWidget.isEnabled():
            tasks = layer.get_tasks()
            self._taskWidget.setStringList([t.name for t in tasks], data=tasks)

        self.selectionChanged.emit(layers)

    def _taskSelectionChanged(self, selection):
        tasks = self._taskWidget.getSelectedValues(self.DATA_ROLE)
        self.selectionChanged.emit(tasks)

    def _clearLayer(self):
        self.__currentLayer = None
        self._layerWidget.clear()

    def _clearTask(self):
        self.__currentTask = None
        self._taskWidget.clear()

    def _clearJob(self):
        self.__currentJob = None
        self._jobWidget.clearSelection()
        self._jobWidget.setFilter('')
示例#3
0
class TabbedLogVieweWidget(QtGui.QWidget):

    fontSizeChanged = QtCore.Signal(int)

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

        self.__tasks = {}
        self.__interval = 1000

        self.__tabs = QtGui.QTabWidget(self)
        self.__tabs.setTabsClosable(True)
        self.__tabs.tabCloseRequested.connect(self.closeTab)

        self.__fontSize = DEFAULT_FONT_SIZE

        layout = QtGui.QVBoxLayout()
        layout.setContentsMargins(4, 0, 4, 4)
        layout.addWidget(self.__tabs)
        self.setLayout(layout)

    def __iter__(self):
        for i in xrange(self.__tabs.count()):
            yield self.__tabs.widget(i)

    def addTask(self, job, task):
        tabs = self.__tabs
        index = self.__tasks.get(task.id, None)

        if index is not None:
            tabs.setCurrentIndex(index)
            logView = tabs.currentWidget()
            logView.setCurrentTask(task)

        else:
            viewer = LogViewerWidget(job, task, {}, self)
            viewer.setFontSize(self.__fontSize)
            viewer.setInterval(self.__interval)
            index = tabs.addTab(viewer, task.name)
            tabs.setTabToolTip(index, viewer.logPath)
            tabs.setCurrentIndex(index)
            self.__tasks[task.id] = index

            viewer.fontSizeChanged.connect(self.setFontSize)

    def closeTab(self, index):
        taskId = None
        for k, v in self.__tasks.iteritems():
            if v == index:
                taskId = k
                break
        if taskId:
            del self.__tasks[taskId]
        self.__tabs.removeTab(index)

    def closeAllTabs(self):
        while self.__tabs.count():
            self.closeTab(0)

    def interval(self):
        return self.__interval

    def setInterval(self, msec):
        self.__interval = msec
        for i in xrange(self.__tabs.count()):
            self.__tabs.widget(i).setInterval(msec)

    def setFontSize(self, size):
        self.__fontSize = size
        for tab in self:
            tab.setFontSize(size)

        self.fontSizeChanged.emit(size)
示例#4
0
class FileWatcher(QtCore.QObject):

    fileChanged = QtCore.Signal(str)

    def __init__(self, parent=None):
        super(FileWatcher, self).__init__(parent)

        self.__files = {}

        self.__timer = QtCore.QTimer(self)
        self.__timer.setInterval(5000)
        self.__timer.timeout.connect(self.checkFiles)

    def addPath(self, path):
        if not path in self.__files:
            self.__files[path] = QtCore.QFileInfo(path).lastModified()

        if self.__files and not self.__timer.isActive():
            self.start()

    def removePath(self, path):
        try:
            del self.__files[path]
        except KeyError:
            pass

        if not self.__files:
            self.stop()

    def removePaths(self, paths):
        for p in paths:
            self.removePath(p)

    def interval(self):
        return self.__timer.interval()

    def setInterval(self, msec):
        timer = self.__timer
        timer.setInterval(msec)
        if timer.isActive():
            timer.start()

    def start(self):
        self.__timer.start()

    def stop(self):
        self.__timer.stop()

    def files(self):
        return self.__files.keys()

    def checkFiles(self):
        if not self.__files:
            return

        info = QtCore.QFileInfo()

        for path, mtime in self.__files.iteritems():
            info.setFile(path)
            test_mtime = info.lastModified()
            if mtime != test_mtime:
                self.__files[path] = test_mtime
                LOGGER.debug("Log file modified: (%r) '%s'", test_mtime, path)
                self.fileChanged.emit(path)
示例#5
0
class LogViewerWidget(QtGui.QWidget):

    fontSizeChanged = QtCore.Signal(int)

    def __init__(self, job=None, task=None, attrs=None, parent=None):
        QtGui.QWidget.__init__(self, parent)

        self.__task = None
        self.__log_file = QtCore.QFile()
        self.__log_stream = QtCore.QTextStream()

        openAction = QtGui.QAction("Open Log File", self)
        openAction.setShortcut(QtGui.QKeySequence.Open)
        self.addAction(openAction)

        self.__searchLine = QtGui.QLineEdit(self)
        self.__chk_tail = QtGui.QAction("Tail log", self)
        self.__chk_tail.setCheckable(True)

        self.__findPrevBtn = prev = QtGui.QAction(self)
        prev.setToolTip("Find Previous Match")
        prev.setIcon(QtGui.QIcon(":/images/left_arrow.png"))

        self.__findNextBtn = nxt = QtGui.QAction(self)
        nxt.setToolTip("Find Next Match")
        nxt.setIcon(QtGui.QIcon(":/images/right_arrow.png"))

        self.__jobNameLabel = label = QtGui.QLabel(self)
        label.setIndent(10)
        # label.setTextInteractionFlags(QtCore.Qt.TextSelectableByMouse)
        label.hide()
        self.__jobNameSpacer = QtGui.QWidget(self)
        self.__jobNameSpacer.setFixedHeight(6)
        self.__jobNameSpacer.hide()

        def spacer(width):
            w = QtGui.QWidget()
            w.setFixedWidth(width)
            return w

        stretch = QtGui.QWidget()
        stretch.setSizePolicy(QtGui.QSizePolicy.Expanding,
                              QtGui.QSizePolicy.Preferred)

        self.__toolbar = tb = QtGui.QToolBar(self)
        tb.addWidget(spacer(4))
        tb.addWidget(QtGui.QLabel("Find: ", self))
        tb.addWidget(self.__searchLine)
        tb.addAction(self.__findPrevBtn)
        tb.addAction(self.__findNextBtn)
        tb.addWidget(stretch)
        tb.addAction(self.__chk_tail)
        tb.addWidget(spacer(4))

        self.__view = view = QtGui.QPlainTextEdit(self)
        font = view.font()
        font.setPixelSize(DEFAULT_FONT_SIZE)
        view.setFont(font)
        view.setLineWrapMode(view.WidgetWidth)
        view.setReadOnly(True)
        view.setMaximumBlockCount(1000000)
        # self.__view.setFocusPolicy(QtCore.Qt.NoFocus)

        layout = QtGui.QVBoxLayout(self)
        layout.setSpacing(0)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self.__toolbar)
        layout.addWidget(self.__jobNameLabel)
        layout.addWidget(self.__jobNameSpacer)
        layout.addWidget(self.__view)

        self.__highlighter = TextHighlighter(view.document())
        self.__logWatcher = FileWatcher(self)

        # Connections
        self.__logWatcher.fileChanged.connect(self.__logUpdated)
        self.__chk_tail.toggled.connect(self.__logTailToggled)
        self.__searchLine.textChanged.connect(self.findText)
        self.__searchLine.returnPressed.connect(self.findNext)
        self.__findPrevBtn.triggered.connect(self.findPrev)
        self.__findNextBtn.triggered.connect(self.findNext)
        openAction.triggered.connect(self.openLogFile)

        # Optional args
        if job:
            self.setJobName(job.name)

        if task:
            self.setCurrentTask(task)

    def keyPressEvent(self, event):
        if event.modifiers() & QtCore.Qt.ControlModifier:
            key = event.key()
            if key == QtCore.Qt.Key_Plus:
                self.incrementFontSize()
            elif key == QtCore.Qt.Key_Minus:
                self.decrementFontSize()

        super(LogViewerWidget, self).keyPressEvent(event)

    @property
    def logPath(self):
        return self.__log_file.fileName()

    @property
    def taskId(self):
        if self.__task:
            return self.__task.id

    @property
    def taskName(self):
        if self.__task:
            return self.__task.name

    @property
    def task(self):
        return self.__task

    @property
    def jobName(self):
        return self.__jobNameLabel.text()

    def interval(self):
        return self.__logWatcher.interval()

    def setInterval(self, msec):
        self.__logWatcher.setInterval(msec)

    def fontSize(self):
        return self.__view.font().pixelSize()

    def setFontSize(self, size):
        size = min(max(size, MIN_FONT_SIZE), MAX_FONT_SIZE)
        font = self.__view.font()
        lastSize = font.pixelSize()
        if size == lastSize:
            return

        font.setPixelSize(size)
        self.__view.setFont(font)
        self.fontSizeChanged.emit(size)

    def incrementFontSize(self):
        self.setFontSize(min(self.fontSize() + 1, MAX_FONT_SIZE))

    def decrementFontSize(self):
        self.setFontSize(max(self.fontSize() - 1, MIN_FONT_SIZE))

    def setCurrentTask(self, task):
        if not task.id:
            return

        if task.id == self.taskId:
            if self.isTailing():
                self.scrollToBottom()
            else:
                self.readMore()
            return

        logPath = task.get_log_path()
        if not os.path.exists(logPath):
            LOGGER.warn("Failed to open log file: '%s'", logPath)
            return

        self.__task = task
        self.setLogPath(logPath)

    def setLogPath(self, path):
        self.stopLogTail()

        f = self.__log_file
        f.close()
        f.setFileName(path)
        if not f.open(QtCore.QIODevice.ReadOnly | QtCore.QIODevice.Text):
            LOGGER.warn("Failed to open log file '%s'", path)
            return

        self.__view.clear()

        self.__log_stream.setDevice(f)
        self.__view.setPlainText(self.__log_stream.readAll())

        if self.__chk_tail.isChecked():
            self.startLogTail()

    def setJobName(self, name):
        self.__jobNameLabel.setText(name)
        self.__jobNameLabel.setVisible(bool(name))
        self.__jobNameSpacer.setVisible(bool(name))

    def findText(self, text, cursor=None, opts=None):
        if not cursor:
            cursor = QtGui.QTextCursor()

        if opts:
            newCursor = self.__view.document().find(text, cursor, opts)
        else:
            newCursor = self.__view.document().find(text, cursor)

        if newCursor.isNull():
            LOGGER.debug("nothing found in text")

        self.__view.setTextCursor(newCursor)
        self.__view.centerCursor()

        self.__highlighter.setFoundMatchText(text)

    def findPrev(self):
        cursor = self.__view.textCursor()
        self.findText(self.__searchLine.text(), cursor,
                      QtGui.QTextDocument.FindBackward)

    def findNext(self):
        cursor = self.__view.textCursor()
        self.findText(self.__searchLine.text(), cursor)

    def startLogTail(self):
        self.stopLogTail()
        self.__logWatcher.addPath(self.__log_file.fileName())

    def stopLogTail(self):
        paths = self.__logWatcher.files()
        if paths:
            self.__logWatcher.removePaths(paths)

    def openLogFile(self):
        logPath, _ = QtGui.QFileDialog.getOpenFileName(
            self, "Open a log file", "", "Logs (*.log *.txt);;All Files (*)")

        if logPath:
            self.setLogPath(logPath)

    def readMore(self, scroll=True):
        self.__logUpdated()
        if scroll:
            self.scrollToBottom()

    def scrollToBottom(self):
        bar = self.__view.verticalScrollBar()
        bar.setValue(bar.maximum())

    def isTailing(self):
        return self.__chk_tail.isChecked()

    def __logUpdated(self):
        cursor = self.__view.textCursor()
        cursor.movePosition(cursor.End)

        while True:
            line = self.__log_stream.read(1024)
            if not line:
                break
            cursor.insertText(line)

        if not self.__searchLine.text().strip():
            self.scrollToBottom()

    def __logTailToggled(self, checked):
        if checked:
            self.startLogTail()
        else:
            self.stopLogTail()
示例#6
0
class FilterItem(DragDropItem):

    filterUpdated = QtCore.Signal()
    filterEnabled = QtCore.Signal(bool)

    def __init__(self, filterObj=None, *args, **kwargs):
        super(FilterItem, self).__init__(*args, **kwargs)

        self.__filter = None

        self._enabledCheck = check = QtGui.QCheckBox(self)
        check.setToolTip("Enable or Disable this filter")
        check.setSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)

        self._nameLabel = name = QtGui.QLineEdit(self)
        name.setPlaceholderText("<Set Filter Name>")
        name.setFrame(False)
        name.setReadOnly(True)
        name.setSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)
        name.installEventFilter(self)

        self._widgetLayout.addWidget(self._enabledCheck)
        self._widgetLayout.addWidget(self._nameLabel)

        self.setStyleSheet("""
            QCheckBox, QLineEdit {background-color: transparent; }
            QLineEdit {border: none; }
            """)

        if filterObj:
            self.setFilterObject(filterObj)

        # Connections
        name.editingFinished.connect(self.__nameEditingFinished)
        check.toggled.connect(self.__filterEnabled)

    def __repr__(self):
        f = self.__filter
        return "<FilterItem: %s >" % (f.name if f else "")

    def eventFilter(self, obj, event):
        if obj is self._nameLabel:

            typ = event.type()
            if typ == event.FocusIn:
                # we will trigger our own focus event
                self.click()
                return True

            elif typ == event.MouseButtonDblClick:
                obj.setReadOnly(False)
                obj.focusInEvent(QtGui.QFocusEvent(event.FocusIn, QtCore.Qt.MouseFocusReason))

        return super(FilterItem, self).eventFilter(obj, event)

    def filterObject(self):
        return self.__filter

    def setFilterObject(self, filt):
        self.__filter = filt
        self._enabledCheck.setChecked(filt.enabled)
        self._nameLabel.setText(filt.name)

    def setColumnWidths(self, widths):
        widgets = (self._enabledCheck, self._nameLabel)
        for width, widget in zip(widths, widgets):
            widget.setMinimumWidth(width)

    def __nameEditingFinished(self):
        nameLabel = self._nameLabel
        nameLabel.clearFocus()
        nameLabel.setReadOnly(True)

        filt = self.__filter

        newName = nameLabel.text()
        if not newName.strip():
            nameLabel.setText(filt.name)
            return

        if newName != filt.name:
            filt.set_name(newName)
            self.filterUpdated.emit()

    def __filterEnabled(self, enabled):
        if enabled != self.__filter.enabled:
            print "Toggle filter status", enabled
示例#7
0
class FiltersList(DragDropList):
    """
    Display a list of Filters for a project, 
    and allow them to be managed.
    """

    ITEM_SPACING = 10
    COLUMN_WIDTHS = [80]

    filterSelected = QtCore.Signal(object)

    def __init__(self, project=None, *args, **kwargs):
        super(FiltersList, self).__init__(*args, **kwargs)

        self.__project = None

        self.setHeaderLabels(['Enabled', 'Filter Name'])

        if project:
            self.setProject(project)

    def project(self):
        return self.__project 

    def setProject(self, project):
        if not isinstance(project, client.Project):
            raise TypeError("Invalid type %r. Must provide a Project instance" % type(project))

        self.__project = project
        self.refresh()

    def refresh(self):
        layout = self._itemLayout 
        layout.setEnabled(False)

        try:
            self.clear()

            if not self.__project:
                return 

            widths = self.COLUMN_WIDTHS

            filters = client.get_filters(self.__project)
            for f in filters:
                widget = FilterItem(f, self)
                self.appendItem(widget)

                widget.filterUpdated.connect(self._filterUpdated)
                widget.filterEnabled.connect(self._filterUpdated)

        finally:
            layout.setEnabled(True)

    def itemClicked(self, item):
        filterObj = item.filterObject()
        if filterObj:
            self.filterSelected.emit(filterObj)

    def _filterUpdated(self):
        print "refresh"
        self.refresh()
示例#8
0
文件: base.py 项目: kurtontheway/plow
class Panel(QtGui.QDockWidget):
    """
    The base class for all panels.
    """

    panelClosed = QtCore.Signal(object)

    def __init__(self, name, ptype, parent=None):
        QtGui.QDockWidget.__init__(self, parent)

        # Add the standard dock action buttons in.
        # TODO: hook up signals
        self.__label = QtGui.QLabel(self)
        self.__label.setIndent(10)
        self.__name = None
        self.__ptype = ptype
        self.setName(name)

        self.attrs = {}

        self.__refreshTimer = None

        # Note: the widet in the panel adds more buttons
        # to this toolbar.
        titleBar = QtGui.QWidget(self)
        barLayout = QtGui.QHBoxLayout(titleBar)
        barLayout.setSpacing(0)
        barLayout.setContentsMargins(0, 0, 0, 0)

        self.__toolbar = toolbar = QtGui.QToolBar(self)
        toolbar.setIconSize(QtCore.QSize(18, 18))
        toolbar.addAction(QtGui.QIcon(":/images/close.png"), "Close",
                          self.__close)

        float_action = QtGui.QAction(QtGui.QIcon(":/images/float.png"),
                                     "Float", self)
        float_action.toggled.connect(self.__floatingChanged)
        float_action.setCheckable(True)
        toolbar.addAction(float_action)

        config_action = QtGui.QAction(QtGui.QIcon(":/images/config.png"),
                                      "Configure Panel", self)
        config_action.triggered.connect(self._openPanelSettingsDialog)
        toolbar.addAction(config_action)

        toolbar.addSeparator()

        barLayout.addWidget(toolbar)
        barLayout.addStretch()
        barLayout.addWidget(self.__label)
        barLayout.addSpacing(4)

        self.setTitleBarWidget(titleBar)
        self.init()

    def titleBarWidget(self):
        return self.__toolbar

    def setRefreshTime(self, value):
        value = int(value)

        if self.__refreshTimer is None:
            self.__refreshTimer = QtCore.QTimer(self)
            self.__refreshTimer.timeout.connect(self.__refresh)

        self.__refreshTimer.stop()
        self.__refreshTimer.start(max(value, 1) * 1000)

    def type(self):
        """
        Return the type of panel.
        """
        return self.__ptype

    def name(self):
        """
        Return the panel's name.
        """
        return self.__name

    def setName(self, name):
        """
        Sets the panel's name, used to allow panels of the same type
        to have unique configurations.
        """
        self.__name = name
        self.__label.setText(name)
        self.setObjectName("%s::%s" % (self.__class__.__name__, self.__name))

    def init(self):
        """
        Initialization function implemented by subclass.
        """
        pass

    def __refresh(self):
        """
        Wrap the public refresh method in calls 
        that stop and start the timer
        """
        timer = self.__refreshTimer
        if timer:
            timer.stop()

        self.refresh()

        if timer:
            timer.start()

    def refresh(self):
        """
        Refresh the main widget.
        """
        pass

    def save(self, settings):
        """
        Called when the application needs the planel to save its configuration.
        """
        for attr in self.attrs:
            key = "panel::%s::%s" % (self.objectName(), attr)
            settings.setValue(key, self.attrs[attr])

    def restore(self, settings):
        """
        Called when the application needs the panel to restore its configuration.
        """
        for attr in self.attrs.keys():
            key = "panel::%s::%s" % (self.objectName(), attr)
            if settings.contains(key):
                self.attrs[attr] = settings.value(key)

        if self.attrs.has_key("refreshSeconds"):
            val = int(self.attrs["refreshSeconds"])
            self.attrs["refreshSeconds"] = val
            self.setRefreshTime(val)
            QtCore.QTimer.singleShot(0, self.refresh)

    def setAttr(self, prop, value):
        self.attrs[prop] = value

    def getAttr(self, prop, default=None):
        return self.attrs.get(prop, default)

    def _openPanelSettingsDialog(self):
        pass

    def __close(self):
        self.panelClosed.emit(self)

    def __floatingChanged(self, value):
        self.setFloating(value)
示例#9
0
class TabbedLogVieweWidget(QtGui.QWidget):

    fontSizeChanged = QtCore.Signal(int)

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

        self.__interval = 1000
        self.__multiTab = True

        self.__tabs = QtGui.QTabWidget(self)
        self.__tabs.setTabsClosable(True)
        self.__tabs.tabCloseRequested.connect(self.closeTab)

        self.__fontSize = DEFAULT_FONT_SIZE

        layout = QtGui.QVBoxLayout()
        layout.setContentsMargins(4,0,4,4)
        layout.addWidget(self.__tabs)
        self.setLayout(layout)

    def __iter__(self):
        for i in xrange(self.__tabs.count()):
            yield self.__tabs.widget(i)

    def addTask(self, job, task):
        if task.retries == -1:
            LOGGER.debug("Task %r has not started yet. No log available", task)
            return 

        tabs = self.__tabs
        index = self.indexOfTaskId(task.id)

        # We just want to refresh an existing log view
        if index > -1:
            tabs.setCurrentIndex(index)
            viewer = tabs.currentWidget()
            viewer.setCurrentTask(task)
            return

        # We are in single tab mode and need to replace with a new one
        if self.__tabs.count() and not self.__multiTab:
            self.closeAllTabs()

        viewer = LogViewerWidget(job, task, attrs={}, parent=self)
        viewer.setFontSize(self.__fontSize)
        viewer.setInterval(self.__interval)
        viewer.fontSizeChanged.connect(self.setFontSize)

        index = tabs.addTab(viewer, task.name)

        tabs.setTabToolTip(index, viewer.logPath)
        tabs.setCurrentIndex(index)
           
    def closeTab(self, index):
        if index > -1:
            widget = self.__tabs.widget(index)
            if widget:
                widget.deleteLater()

            self.__tabs.removeTab(index)

    def closeAllTabs(self):
        while self.__tabs.count():
            self.closeTab(0) 

    def interval(self):
        return self.__interval

    def setInterval(self, msec):
        self.__interval = msec
        for i in xrange(self.__tabs.count()):
            self.__tabs.widget(i).setInterval(msec)

    def setFontSize(self, size):
        self.__fontSize = size
        for tab in self:
            tab.setFontSize(size)

        self.fontSizeChanged.emit(size)

    def setMultiTabMode(self, enabled):
        if enabled == self.__multiTab:
            return

        self.__multiTab = enabled

        if not enabled:
            tabs = self.__tabs
            currentIndex = tabs.currentIndex()
            for i in reversed(xrange(tabs.count())):
                if i == currentIndex:
                    continue
                self.closeTab(i)

    def indexOfTaskId(self, taskId):
        tabs = self.__tabs

        for i in xrange(tabs.count()):
            viewer = tabs.widget(i)
            if viewer and viewer.taskId == taskId:
                return i

        return -1
示例#10
0
class FilterableListBox(QtGui.QWidget):
    """
    A list box widget with a text filter.
    """

    DATA_ROLE = QtCore.Qt.UserRole

    selectionChanged = QtCore.Signal(list)
    valueDoubleClicked = QtCore.Signal(object)
    valueClicked = QtCore.Signal(object)

    def __init__(self, filt=None, items=None, data=None, parent=None):
        QtGui.QWidget.__init__(self, parent)

        self.__data = {}

        self.__txt_label = QtGui.QLabel(self)
        self.__txt_filter = QtGui.QLineEdit(self)
        self.__txt_filter.textChanged.connect(self.__filterChanged)

        self.__model = QtGui.QStringListModel(self)

        self.__proxyModel = proxy = QtGui.QSortFilterProxyModel(self)
        proxy.setSourceModel(self.__model)

        self.__list = view = QtGui.QListView(self)
        view.setSelectionMode(self.__list.ExtendedSelection)
        view.setModel(proxy)

        proxy.sort(0)
        proxy.setDynamicSortFilter(True)

        layout = QtGui.QVBoxLayout(self)
        layout.setSpacing(4)
        layout.setContentsMargins(0, 0, 0, 0)

        hlayout = QtGui.QHBoxLayout()
        hlayout.setContentsMargins(0, 0, 0, 0)
        hlayout.addWidget(self.__txt_label)
        hlayout.addWidget(self.__txt_filter)

        layout.addLayout(hlayout)
        layout.addWidget(self.__list)

        # connections
        self.__list.doubleClicked.connect(self._itemDoubleClicked)
        self.__list.clicked.connect(self._itemClicked)
        self.__list.selectionModel().selectionChanged.connect(
            self._selectionChanged)

        if items:
            self.setStringList(items)

        if filt:
            self.setFilter(filt)

    def clear(self):
        self.setStringList([])
        self.setFilter('')

    def clearSelection(self, clearFilter=True):
        self.__list.clearSelection()
        if clearFilter:
            self.setFilter('')

    def setLabel(self, val):
        self.__txt_label.setText(val)

    def setFilter(self, val, selectFirst=False):
        if not val:
            val = ''

        self.__txt_filter.setText(val)

        if not selectFirst:
            return

        proxy = self.__proxyModel
        matches = proxy.match(proxy.index(0, 0), QtCore.Qt.DisplayRole, val, 1,
                              QtCore.Qt.MatchContains)
        if matches:
            selModel = self.__list.selectionModel()
            selModel.select(matches[0], selModel.ClearAndSelect)

    def setStringList(self, aList, data=None):
        model = self.__model
        model.setStringList(aList)
        self.__data = {}

        role = self.DATA_ROLE
        for row, val in enumerate(aList):
            try:
                dataVal = data[row]
            except Exception, e:
                dataVal = val
            self.__data[row] = dataVal
示例#11
0
        Called when the application needs the panel to restore its configuration.
        """
        for attr in self.attrs.keys():
            key = "panel::%s::%s" % (self.objectName(), attr)
            if settings.contains(key):
                self.attrs[attr] = settings.value(key)

        if self.attrs.has_key("refreshSeconds"):
            val = int(self.attrs["refreshSeconds"])
            self.attrs["refreshSeconds"] = val
            self.setRefreshTime(val)
            self.refresh()

    def setAttr(self, prop, value):
        self.attrs[prop] = value

    def getAttr(self, prop, default=None):
        return self.attrs.get(prop)

    def _openPanelSettingsDialog(self):
        pass

    def __close(self):
        self.panelClosed.emit(self)

    def __floatingChanged(self, value):
        self.setFloating(value)


Panel.panelClosed = QtCore.Signal(Panel)