Beispiel #1
0
class UIWellPlotPG(QtCore.QObject):
    def setupUI(self):
        self.mainWidget = WellPlotWidget()
        vBox = QtGui.QVBoxLayout()

        self.splitter = QSplitter(QtCore.Qt.Vertical)

        self.headerScrollArea = QScrollArea()
        self.headerScrollArea.setVerticalScrollBarPolicy(
            QtCore.Qt.ScrollBarAlwaysOn)
        self.headerScrollArea.setHorizontalScrollBarPolicy(
            QtCore.Qt.ScrollBarAlwaysOff)
        self.headerScrollArea.setWidgetResizable(False)

        self.scrollArea = QScrollArea()
        self.scrollArea.setVerticalScrollBarPolicy(
            QtCore.Qt.ScrollBarAlwaysOff)
        self.scrollArea.setHorizontalScrollBarPolicy(
            QtCore.Qt.ScrollBarAlwaysOn)
        #Needs to be true to allow widget in scroll area size to change
        self.scrollArea.setWidgetResizable(True)
        #self.scrollArea.setWidget(self.dataWidget)
        #see http://stackoverflow.com/questions/29583927/pyqt-qscrollarea-within-qscrollarea/29584939#29584939
        self.scrollArea.horizontalScrollBar().valueChanged.connect(
            self.headerScrollArea.horizontalScrollBar().setValue)

        self.splitter.addWidget(self.headerScrollArea)
        self.splitter.addWidget(self.scrollArea)

        #test
        hBox = QtGui.QHBoxLayout()
        #set parent so can access it for widget sizing
        self.scaleWidget = QWidget()
        self.scaleWidgetLayout = QtGui.QVBoxLayout()
        self.scaleWidget.setLayout(self.scaleWidgetLayout)
        self.scaleWidget.setMinimumWidth(30)
        hBox.addWidget(self.splitter, 1)
        hBox.addWidget(self.scaleWidget)
        self.mainWidget.setLayout(hBox)
        #end test
        '''
Beispiel #2
0
def selectFile():
    global path
    path = QFileDialog.getOpenFileName()
    ui.fileUploadText.setText(path + ' uploaded.')

    file = open(path)

    counts = defaultdict(int)
    for line in file:

        list = line.split(',')
        counts[list[0]] += 1

    counts = OrderedDict(sorted(counts.items()))

    #Create the plot
    plot.bar(range(len(counts)), counts.values(), align='center')
    plot.xticks(range(len(counts)), counts.keys())

    fig = plot.gcf()
    fig.set_size_inches(24, 8)

    fig.suptitle('Age distribution', fontsize=18)
    plot.xlabel('Age', fontsize=18)
    plot.ylabel('Number of records', fontsize=18)

    fig.savefig(str(path) + 'plot.png', dpi=60)
    outputGraph = str(path) + 'plot.png'

    pixMap = QtGui.QPixmap(outputGraph)
    ui.inputDataLabel.setPixmap(pixMap)

    scrollArea = QScrollArea()
    scrollArea.setWidgetResizable(True)
    scrollArea.setWidget(ui.inputDataLabel)
    scrollArea.setFixedHeight(500)
    scrollArea.horizontalScrollBar().setValue(
        scrollArea.horizontalScrollBar().value() + 100)
    hLayout = QtGui.QHBoxLayout()
    hLayout.addWidget(scrollArea)
    ui.uploadTab.setLayout(hLayout)
Beispiel #3
0
def selectFile():
    global path
    path = QFileDialog.getOpenFileName()
    ui.fileUploadText.setText(path + ' uploaded.')

    file = open(path)

    counts = defaultdict(int)
    for line in file:

        list = line.split(',')
        counts[list[0]] += 1

    counts = OrderedDict(sorted(counts.items()))

    #Create the plot
    plot.bar(range(len(counts)), counts.values(), align='center')
    plot.xticks(range(len(counts)), counts.keys())

    fig = plot.gcf()
    fig.set_size_inches(24, 8)

    fig.suptitle('Age distribution', fontsize=18)
    plot.xlabel('Age', fontsize=18)
    plot.ylabel('Number of records', fontsize=18)

    fig.savefig(str(path) + 'plot.png', dpi=60)
    outputGraph = str(path) + 'plot.png'

    pixMap = QtGui.QPixmap(outputGraph)
    ui.inputDataLabel.setPixmap(pixMap)
    
    scrollArea = QScrollArea()
    scrollArea.setWidgetResizable(True)
    scrollArea.setWidget(ui.inputDataLabel)
    scrollArea.setFixedHeight(500)
    scrollArea.horizontalScrollBar().setValue(scrollArea.horizontalScrollBar().value() + 100); 
    hLayout = QtGui.QHBoxLayout()
    hLayout.addWidget(scrollArea)
    ui.uploadTab.setLayout(hLayout)
class ScrollArea(QFrame):

    def __init__(self, parent=None, horizontal=True, vertical=True,
                 color=None):
        QFrame.__init__(self, parent)
        
        self.scrollarea = QScrollArea(self)
        self.scrollarea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.scrollarea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        
        self.v_pad = scrollbar.ScrollPad(self)
        self.v_pad.setOrientation(Qt.Vertical)
        self.v_pad.setMinimumWidth(30)
        if color:
            self.v_pad.set_color(color)

        self.h_pad = scrollbar.ScrollPad(self)
        self.h_pad.setOrientation(Qt.Horizontal)
        self.h_pad.setMinimumHeight(30)
        if color:
            self.h_pad.set_color(color)

        QObject.connect(self.v_pad, SIGNAL('valueChanged(int)'),
                        self.v_scroll)
        QObject.connect(self.h_pad, SIGNAL('valueChanged(int)'),
                        self.h_scroll)

        for name in ('setWidgetResizable',):
            setattr(self, name, getattr(self.scrollarea, name))
        self.horizontal(horizontal)
        self.vertical(vertical)

        Layout1 = QVBoxLayout(self)
        Layout1.setSpacing(0)
        Layout1.setMargin(0)
        Layout2 = QHBoxLayout()
        Layout2.setSpacing(0)
        Layout2.setMargin(0)
        Layout2.addWidget(self.scrollarea)
        Layout2.addWidget(self.v_pad)
        Layout1.addLayout(Layout2)
        Layout1.addWidget(self.h_pad)

    def setWidget(self, widget):
        self.scrollarea.setWidget(widget)

    def horizontal(self, on):
        if on:
            self.h_pad.show()
        else:
            self.h_pad.hide()

    def vertical(self, on):
        if on:
            self.v_pad.show()
        else:
            self.v_pad.hide()

    def v_scroll(self, value):
        sb = self.v_pad
        target_sb = self.scrollarea.verticalScrollBar()
        percent = sb.value() / float(sb.maximum())
        target_sb.setValue(int(percent * target_sb.maximum()))

    def h_scroll(self, value):
        sb = self.h_pad
        target_sb = self.scrollarea.horizontalScrollBar()
        percent = sb.value() / float(sb.maximum())
        target_sb.setValue(int(percent * target_sb.maximum()))
Beispiel #5
0
def runDecisionTree():

    #Todo: try not to use global variables
    global path
    global alteredPath

    fileName = ''

    if (alteredPath):
        fileName = alteredPath
    elif (path):
        fileName = path
    else:
        print('Must upload file first')
        return

    x = []
    y = []

    file = open(fileName)
    for line in file:
        line = line.rstrip()
        features = []
        classification = []

        list = line.split(',')
        features = list[0:-1]
        if (features and features[0].strip()):
            x.append(features)

        classification = [list[-1]]
        if (classification and classification[0].strip()):
            y.append(classification)

    ui.progressBar.setValue(25)

    samples = [dict(enumerate(sample)) for sample in x]

    # turn list of dicts into a numpy array
    vect = DictVectorizer(sparse=False)
    x = vect.fit_transform(samples)
    ui.progressBar.setValue(50)

    clf = tree.DecisionTreeClassifier()
    clf = clf.fit(x, y)

    with open(fileName + '.dot', 'w') as f:
        f = tree.export_graphviz(clf, out_file=f)
    graph = pydot.graph_from_dot_file(fileName + '.dot')
    graph.write_png(fileName + '.png')
    global outputGraph
    outputGraph = fileName + '.png'

    ui.progressBar.setValue(75)

    pixMap = QtGui.QPixmap(outputGraph)
    #ui.outputLabel.setPixmap(pixMap.scaled(ui.outputTab.size(), QtCore.Qt.KeepAspectRatio))
    ui.outputLabel.setPixmap(pixMap)
    #ui.outputLabel.setScaledContents(True)

    scrollArea = QScrollArea()
    scrollArea.setWidgetResizable(True)
    scrollArea.setWidget(ui.outputLabel)
    scrollArea.setFixedHeight(525)
    scrollArea.horizontalScrollBar().setValue(
        scrollArea.horizontalScrollBar().value() + 3400)
    hLayout = QtGui.QHBoxLayout()
    hLayout.addWidget(scrollArea)
    ui.outputTab.setLayout(hLayout)

    ui.progressBar.setValue(100)

    ui.algorithmText.setText('Built decision tree')
Beispiel #6
0
def runDecisionTree():

    #Todo: try not to use global variables
    global path
    global alteredPath

    fileName = ''

    if (alteredPath):
        fileName = alteredPath
    elif (path):
        fileName = path
    else:
        print('Must upload file first')
        return

    x = []
    y = []

    file = open(fileName)
    for line in file:
        line = line.rstrip()
        features = []
        classification = []

        list = line.split(',')
        features = list[0:-1]
        if (features and features[0].strip()):
            x.append(features)

        classification = [list[-1]]
        if (classification and classification[0].strip()):
            y.append(classification)


    ui.progressBar.setValue(25)

    samples = [dict(enumerate(sample)) for sample in x]

    # turn list of dicts into a numpy array
    vect = DictVectorizer(sparse=False)
    x = vect.fit_transform(samples)
    ui.progressBar.setValue(50)

    clf = tree.DecisionTreeClassifier()
    clf = clf.fit(x, y)

    
    with open(fileName + '.dot', 'w') as f:
        f = tree.export_graphviz(clf, out_file=f)
    graph = pydot.graph_from_dot_file(fileName + '.dot')
    graph.write_png(fileName + '.png')
    global outputGraph
    outputGraph = fileName + '.png'

    ui.progressBar.setValue(75)
    

    pixMap = QtGui.QPixmap(outputGraph)
    #ui.outputLabel.setPixmap(pixMap.scaled(ui.outputTab.size(), QtCore.Qt.KeepAspectRatio))
    ui.outputLabel.setPixmap(pixMap)
    #ui.outputLabel.setScaledContents(True)

    
    scrollArea = QScrollArea()
    scrollArea.setWidgetResizable(True)
    scrollArea.setWidget(ui.outputLabel)
    scrollArea.setFixedHeight(525)
    scrollArea.horizontalScrollBar().setValue(scrollArea.horizontalScrollBar().value() + 3400); 
    hLayout = QtGui.QHBoxLayout()
    hLayout.addWidget(scrollArea)
    ui.outputTab.setLayout(hLayout)

    ui.progressBar.setValue(100)

    ui.algorithmText.setText('Built decision tree')
Beispiel #7
0
class XNavigationEdit(XLineEdit):
    """ """
    navigationChanged = Signal()
    
    __designer_icon__ = projexui.resources.find('img/ui/navigate.png')
    
    def __init__( self, parent = None ):
        super(XNavigationEdit, self).__init__( parent )
        
        # define custom properties
        self._separator             = '/'
        self._partsEditingEnabled   = True
        self._originalText          = ''
        self._scrollWidget          = QScrollArea(self)
        self._partsWidget           = QWidget(self._scrollWidget)
        self._buttonGroup           = QButtonGroup(self)
        self._scrollAmount          = 0
        self._navigationModel       = None
        
        # create the completer tree
        palette = self.palette()
        palette.setColor(palette.Base, palette.color(palette.Window))
        palette.setColor(palette.Text, palette.color(palette.WindowText))
        
        bg      = palette.color(palette.Highlight)
        abg     = bg.darker(115)
        fg      = palette.color(palette.HighlightedText)
        sbg     = 'rgb(%s, %s, %s)' % (bg.red(), bg.green(), bg.blue())
        sabg    = 'rgb(%s, %s, %s)' % (abg.red(), abg.green(), abg.blue())
        sfg     = 'rgb(%s, %s, %s)' % (fg.red(), fg.green(), fg.blue())
        style   = 'QTreeView::item:hover { '\
                  '     color: %s;'\
                  '     background: qlineargradient(x1:0,'\
                  '                                 y1:0,'\
                  '                                 x2:0,'\
                  '                                 y2:1,'\
                  '                                 stop: 0 %s,'\
                  '                                 stop: 1 %s);'\
                  '}' % (sfg, sbg, sabg)
        
        self._completerTree = QTreeView(self)
        self._completerTree.setStyleSheet(style)
        self._completerTree.header().hide()
        self._completerTree.setFrameShape(QTreeView.Box)
        self._completerTree.setFrameShadow(QTreeView.Plain)
        self._completerTree.setPalette(palette)
        self._completerTree.setEditTriggers(QTreeView.NoEditTriggers)
        self._completerTree.setWindowFlags(Qt.Popup)
        self._completerTree.installEventFilter(self)
        self._completerTree.setRootIsDecorated(False)
        self._completerTree.setItemsExpandable(False)
        
        # create the editing widget
        layout = QHBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)
        layout.addStretch()
        
        self._scrollWidget.setFrameShape( QScrollArea.NoFrame )
        self._scrollWidget.setFocusPolicy(Qt.NoFocus)
        self._scrollWidget.setWidget(self._partsWidget)
        self._scrollWidget.setWidgetResizable(True)
        self._scrollWidget.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self._scrollWidget.setAlignment(Qt.AlignTop | Qt.AlignRight)
        self._scrollWidget.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self._scrollWidget.setContentsMargins(0, 0, 0, 0)
        self._scrollWidget.setViewportMargins(0, 0, 0, 0)
        self._scrollWidget.move(2, 2)
        
        self._partsWidget.setLayout(layout)
        self._partsWidget.setCursor(Qt.ArrowCursor)
        self._partsWidget.setAutoFillBackground(True)
        self._partsWidget.setFixedHeight(self.height() - 12)
        
        palette = self._partsWidget.palette()
        palette.setColor(palette.Background, palette.color(palette.Base))
        self._partsWidget.setPalette(palette)
        
        # create connections
        self._completerTree.clicked.connect( self.navigateToIndex )
        self._buttonGroup.buttonClicked.connect( self.handleButtonClick )
        self._scrollWidget.horizontalScrollBar().valueChanged.connect( 
                                                        self.scrollParts )
    
    def acceptEdit( self ):
        """
        Accepts the current text and rebuilds the parts widget.
        """
        
        if ( self._partsWidget.isVisible() ):
            return False
        
        use_completion = self.completer().popup().isVisible()
        completion     = self.completer().currentCompletion()
        
        self._completerTree.hide()
        self.completer().popup().hide()
        
        if ( use_completion ):
            self.setText(completion)
        else:
            self.rebuild()
            
        return True
    
    def cancelEdit( self ):
        """
        Rejects the current edit and shows the parts widget.
        """
        
        if ( self._partsWidget.isVisible() ):
            return False
            
        self._completerTree.hide()
        self.completer().popup().hide()
        
        self.setText(self._originalText)
        return True
    
    def currentItem( self ):
        """
        Returns the current navigation item from the current path.
        
        :return     <XNavigationItem> || None
        """
        model = self.navigationModel()
        if ( not model ):
            return None
        
        return model.itemByPath(self.text())
    
    def eventFilter( self, object, event ):
        """
        Filters the events for the inputed object through this edit.
        
        :param      object | <QObject>
                    event  | <QEvent>
        
        :return     <bool> | consumed
        """
        if ( event.type() == event.KeyPress ):
            if ( event.key() == Qt.Key_Escape ):
                self._completerTree.hide()
                self.completer().popup().hide()
                
                self.cancelEdit()
                
            elif ( event.key() in (Qt.Key_Return, Qt.Key_Enter) ):
                self.acceptEdit()
                return True
                
            elif ( event.key() == Qt.Key_Tab ):
                if ( self.completer().popup().isVisible() ):
                    text   = str(self.completer().currentCompletion())
                    super(XNavigationEdit, self).setText(text)
                    return True
                else:
                    self.acceptEdit()
                    return False
            
        elif ( event.type() == event.MouseButtonPress ):
            if ( not self._completerTree.rect().contains(event.pos()) ):
                self._completerTree.hide()
                self.completer().popup().hide()
                
                self.cancelEdit()
        
        return False
    
    def focusOutEvent( self, event ):
        """
        Overloads the focus out event to cancel editing when the widget loses
        focus.
        
        :param      event | <QFocusEvent>
        """
        super(XNavigationEdit, self).focusOutEvent(event)
        
        self.cancelEdit()
    
    def handleButtonClick( self, button ):
        """
        Handle the event when a user clicks on one of the part buttons.
        
        :param      button | <QToolButton>
        """
        path            = button.property('path')
        is_completer    = button.property('is_completer')
        
        # popup a completion menu
        if ( unwrapVariant(is_completer) ):
            model = self.navigationModel()
            if ( not model ):
                return
            
            sep  = self.separator()
            path = str(unwrapVariant(path))
            item = model.itemByPath(path, includeRoot = True)
            if ( not item ):
                return
            
            curr_path = str(self.text()).strip(self.separator())
            curr_path = curr_path.replace(path, '').strip(self.separator())
            
            child_name = ''
            if ( curr_path ):
                child_name = curr_path.split(self.separator())[0]
            
            index = model.indexFromItem(item)
            
            self._completerTree.move(QCursor.pos())
            self._completerTree.setRootIndex(index)
            self._completerTree.verticalScrollBar().setValue(0)
            
            if ( child_name ):
                child_item = None
                for i in range(item.rowCount()):
                    child = item.child(i)
                    if ( child.text() == child_name ):
                        child_item = child
                        break
                
                if ( child_item ):
                    child_index = model.indexFromItem(child_item)
                    self._completerTree.setCurrentIndex(child_index)
                    self._completerTree.scrollTo(child_index)
            
            self._completerTree.show()
            self._completerTree.setUpdatesEnabled(True)
        else:
            self.setText(unwrapVariant(path))
    
    def keyPressEvent( self, event ):
        """
        Overloads the key press event to listen for escape calls to cancel the
        parts editing.
        
        :param      event | <QKeyPressEvent>
        """
        if ( self.scrollWidget().isHidden() ):
            if ( event.key() == Qt.Key_Escape ):
                self.cancelEdit()
                return
                
            elif ( event.key() in (Qt.Key_Return, Qt.Key_Enter) ):
                self.acceptEdit()
                return
            
        elif ( event.key() == Qt.Key_A and 
               event.modifiers() == Qt.ControlModifier ):
            self.startEdit()
        
        super(XNavigationEdit, self).keyPressEvent(event)
    
    def mouseDoubleClickEvent( self, event ):
        """
        Overloads the system to enable editing when a user double clicks.
        
        :param      event | <QMouseEvent>
        """
        super(XNavigationEdit, self).mouseDoubleClickEvent(event)
        
        self.startEdit()
    
    def navigationModel( self ):
        """
        Returns the navigation model linked with this edit.
        
        :return     <XNavigationModel> || None
        """
        return self._navigationModel
    
    def navigateToIndex( self, index ):
        """
        Navigates to the inputed action's path.
        
        :param      action | <QAction>
        """
        self._completerTree.hide()
        item = self._navigationModel.itemFromIndex(index)
        self.setText(self._navigationModel.itemPath(item))
    
    def parts( self ):
        """
        Returns the parts that are used for this system.
        
        :return     [<str>, ..]
        """
        path = str(self.text()).strip(self.separator())
        if ( not path ):
            return []
        return path.split(self.separator())
    
    def partsWidget( self ):
        """
        Returns the widget that contains the parts system.
        
        :return     <QScrollArea>
        """
        return self._partsWidget
    
    def startEdit( self ):
        """
        Rebuilds the pathing based on the parts.
        """
        self._originalText = self.text()
        self.scrollWidget().hide()
        self.setFocus()
        self.selectAll()
    
    def rebuild( self ):
        """
        Rebuilds the parts widget with the latest text.
        """
        navitem = self.currentItem()
        if ( navitem ):
            navitem.initialize()
            
        self.setUpdatesEnabled(False)
        self.scrollWidget().show()
        self._originalText = ''
        
        partsw = self.partsWidget()
        for button in self._buttonGroup.buttons():
            self._buttonGroup.removeButton(button)
            button.close()
            button.setParent(None)
            button.deleteLater()
        
        # create the root button
        layout = partsw.layout()
        parts  = self.parts()
        
        button = QToolButton(partsw)
        button.setAutoRaise(True)
        button.setMaximumWidth(12)
        button.setArrowType(Qt.RightArrow)
        
        button.setProperty('path',          wrapVariant(''))
        button.setProperty('is_completer',  wrapVariant(True))
        last_button = button
            
        self._buttonGroup.addButton(button)
        layout.insertWidget(0, button)
        
        # check to see if we have a navigation model setup
        if ( self._navigationModel ):
            last_item = self._navigationModel.itemByPath(self.text())
            show_last =  last_item and last_item.rowCount() > 0
        else:
            show_last = False
        
        # load the navigation system
        count = len(parts)
        for i, part in enumerate(parts):
            path = self.separator().join(parts[:i+1])
            
            button = QToolButton(partsw)
            button.setAutoRaise(True)
            button.setText(part)
            
            if ( self._navigationModel ):
                item = self._navigationModel.itemByPath(path)
                if ( item ):
                    button.setIcon(item.icon())
                    button.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
            
            button.setProperty('path',         wrapVariant(path))
            button.setProperty('is_completer', wrapVariant(False))
            
            self._buttonGroup.addButton(button)
            layout.insertWidget((i * 2) + 1, button)
            
            # determine if we should show the final button
            if ( show_last or i < (count - 1) ):
                button = QToolButton(partsw)
                button.setAutoRaise(True)
                button.setMaximumWidth(12)
                button.setArrowType(Qt.RightArrow)
                
                button.setProperty('path',          wrapVariant(path))
                button.setProperty('is_completer',  wrapVariant(True))
            
                self._buttonGroup.addButton(button)
                layout.insertWidget((i * 2) + 2, button)
                
                last_button = button
        
        if ( self.scrollWidget().width() < partsw.width() ):
            self.scrollParts(partsw.width() - self.scrollWidget().width())
            
        self.setUpdatesEnabled(True)
        self.navigationChanged.emit()
    
    def resizeEvent( self, event ):
        """
        Resizes the current widget and its parts widget.
        
        :param      event | <QResizeEvent>
        """
        super(XNavigationEdit, self).resizeEvent(event)
        
        w = self.width()
        h = self.height()
        
        self._scrollWidget.resize(w - 4, h - 4)
        
        if ( self._scrollWidget.width() < self._partsWidget.width() ):
           self.scrollParts( self._partsWidget.width() - self._scrollWidget.width() )
    
    def scrollParts( self, amount ):
        """
        Scrolls the parts to offset the scrolling amount.
        
        :param      amount | <int>
        """
        change = self._scrollAmount - amount
        self._partsWidget.scroll(change, 0)
        self._scrollAmount = amount
    
    def scrollWidget( self ):
        """
        Returns the scrolling widget.
        
        :return     <QScrollArea>
        """
        return self._scrollWidget
    
    def separator( self ):
        """
        Returns the separation character that is used for this edit.
        
        :return     <str>
        """
        return self._separator
    
    def setTopLevelItems( self, items ):
        """
        Initializes the navigation system to start with the inputed root \
        item.
        
        :param      item | <XNavigationItem>
        """
        if ( not self._navigationModel ):
            self.setNavigationModel(XNavigationModel(self))
        
        self._navigationModel.setTopLevelItems(items)
    
    def setNavigationModel( self, model ):
        """
        Sets the navigation model for this edit.
        
        :param      model | <XNavigationModel>
        """
        self._navigationModel = model
        self._completerTree.setModel(model)
        
        if ( model ):
            model.setSeparator(self.separator())
            completer = XNavigationCompleter(model, self)
            self.setCompleter(completer)
            completer.popup().installEventFilter(self)
        else:
            self.setCompleter(None)
        
        self.rebuild()
    
    def setParts( self, parts ):
        """
        Sets the path for this edit widget by providing the parts to the path.
        
        :param      parts | [<str>, ..]
        """
        self.setText(self.separator().join(map(str, parts)))
    
    def setSeparator( self, separator ):
        """
        Sets the separator to the inputed character.
        
        :param      separator | <str>
        """
        self._separator = separator
        if ( self._navigationModel ):
            self._navigationModel.setSeparator(separator)
        self.rebuild()
    
    def setText( self, text ):
        """
        Sets the text for this edit to the inputed text.
        
        :param      text | <str>
        """
        super(XNavigationEdit, self).setText(text)
        
        self.scrollWidget().show()
        if ( text == '' or self._originalText != text ):
            self.rebuild()
Beispiel #8
0
class WellPlotMPL(QtCore.QObject):
    def __init__(self, logs, well, logSet=None, parent=None):
        super(WellPlotMPL, self).__init__(parent)

        self._well = well
        self._logSet = logSet
        self._logs = logs
        self.plots = []
        self.canvas = None
        self.depthPlot = None
        self.headerPlot = None
        centralWidget = centraltabwidget.CentralTabWidget()
        #id(self) returns the 'hash' of this object
        self.uid = (centralWidget.count(), id(self))
        self.wellPlotSignals = WellPlotSignals()

        self.setupUI()
        self.createTabView()
        self.connectSlots()
        self.plotMultiLogs()
        self.setSplitterStretch()
        self.createToolWidget()

    def setupUI(self):
        self.mainWidget = WellPlotWidget()
        vBox = QtGui.QVBoxLayout()
        self.mainWidget.setLayout(vBox)

        self.headerWidget = QWidget()
        self.headerLayout = QtGui.QHBoxLayout()
        self.headerWidget.setLayout(self.headerLayout)

        self.dataWidget = QWidget()
        self.dataLayout = QtGui.QHBoxLayout()
        self.dataWidget.setLayout(self.dataLayout)

        #if don't set a minimum, get matplotlib error when is very small
        self.dataWidget.setMinimumHeight(self.getMinimumVerticalHeight())

        self.splitter = QSplitter(QtCore.Qt.Vertical)

        self.headerScrollArea = QScrollArea()
        self.headerScrollArea.setVerticalScrollBarPolicy(
            QtCore.Qt.ScrollBarAlwaysOn)
        self.headerScrollArea.setHorizontalScrollBarPolicy(
            QtCore.Qt.ScrollBarAlwaysOff)
        self.headerScrollArea.setWidgetResizable(False)
        self.headerScrollArea.setWidget(self.headerWidget)

        self.scrollArea = QScrollArea()
        self.scrollArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
        self.scrollArea.setHorizontalScrollBarPolicy(
            QtCore.Qt.ScrollBarAlwaysOn)
        self.scrollArea.setWidgetResizable(False)
        self.scrollArea.setWidget(self.dataWidget)
        #see http://stackoverflow.com/questions/29583927/pyqt-qscrollarea-within-qscrollarea/29584939#29584939
        self.scrollArea.horizontalScrollBar().valueChanged.connect(
            self.headerScrollArea.horizontalScrollBar().setValue)

        self.splitter.addWidget(self.headerScrollArea)
        self.splitter.addWidget(self.scrollArea)
        self.splitter.setStretchFactor(1, 10)

        vBox.addWidget(self.splitter)

    def getMinimumVerticalHeight(self):
        screenRect = QtGui.QDesktopWidget().screenGeometry()
        #need to set a minimum size otherwise get matplotlib error when rezizing to too small
        twentythOfScreen = int(round(screenRect.width() / 20))
        return twentythOfScreen

    def plotMultiLogs(self):
        logPlotModelAccess = WellPlotModelAccess()
        logPlotData = logPlotModelAccess.createWellPlotData(self._logs)
        self.createCanvas(logPlotData)
        self.plotHeaderFields(logPlotData)

    def createCanvas(self, logPlotData):
        logger.debug(">>createCanvas()")
        #test
        for subPlotData in logPlotData.sub_plots:
            logger.debug(
                "--createCanvas() plot_index:{0} track_width:{1} track_gap:{2}"
                .format(subPlotData.plot_index, subPlotData.track_width,
                        subPlotData.track_gap))
            for log in subPlotData._logs:
                logger.debug("--createCanvas id:{0}, name:{1}".format(
                    log.id, log.name))
        #end test
        if len(logPlotData.sub_plots) > 0:
            WidgetUtils.removeWidgets(self.dataLayout)

            #test
            #time.sleep(1) # delays for 1 second
            #end test

            #There may be a better way to link plots with the toolbar
            self.mainWidget.setLogPlotData(logPlotData)

            self.depthPlot = DepthAxis(logPlotData, self.dataWidget)
            self.dataLayout.addWidget(self.depthPlot)

            self.canvas = MultiLogCanvas(logPlotData, self.dataWidget)
            self.canvas.setAutoFillBackground(True)
            self.dataLayout.addWidget(self.canvas)

            spacerItem = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding,
                                           QtGui.QSizePolicy.Minimum)
            self.dataLayout.addItem(spacerItem)
        else:
            logger.error("--plotMultiLogs() Error: no logs to plot")
            if AppSettings.isDebugMode:
                raise ValueError

    def plotHeaderFields(self, logPlotData):
        logger.debug(">>plotMultiLogs()")
        WidgetUtils.removeWidgets(self.headerLayout)
        self.headerPlot = HeaderPlotMPL(depthPlot=self.depthPlot,
                                        mainPlot=self.canvas,
                                        logPlotData=logPlotData)
        self.headerLayout.addWidget(self.headerPlot)

    def setSplitterStretch(self):
        #Minimum size is required for the QScrollArea.setWidgetResizable(False) setting'''
        headerW = self.headerPlot.width()
        headerH = self.headerPlot.height()
        self.headerWidget.setMinimumSize(headerW, headerH)

        #test
        (totalW, dataH) = MplUtils.calcFigCanvasWidthHeight(self.canvas.figure)
        #end test
        dWidth, dHeight = self.canvas.figure.canvas.get_width_height()

        self.dataWidget.setMinimumSize(dWidth, dHeight)

    def connectSlots(self):
        logger.debug(">>connectSlots")
        self.wellPlotSignals.logPlotSettingsModified.connect(self.replotLogs)

    @pyqtSlot(WellPlotData)
    def replotLogs(self, logPlotData):
        logger.debug(">>replotLogs len(logPlotData.sub_plots): " +
                     str(len(logPlotData.sub_plots)))
        #check uid's before accessing them, where uid is a (number widgets in central widget, id) tuple
        logger.debug(
            "--replotLogs() len(self.uid):{0}, len(logPlotData.uid):{1}".
            format(len(self.uid), len(logPlotData.uid)))
        if (len(self.uid) == 2) and (len(logPlotData.uid) == 2):
            #ensure this object is associated with the plot object
            if self.uid[0] == logPlotData.uid[0] and self.uid[
                    1] == logPlotData.uid[1]:
                logger.debug("--replotLogs() match found uid: " +
                             str(self.uid[0]))

                self.createCanvas(logPlotData)
                self.plotHeaderFields(logPlotData)

    def spacePlots(self, bottomLayout):
        rightSpacer = QtGui.QWidget()
        rightSpacer.setSizePolicy(QtGui.QSizePolicy.Expanding,
                                  QtGui.QSizePolicy.Expanding)
        #topLayout.addWidget(rightSpacer)
        bottomLayout.addWidget(rightSpacer)
        #self.topWidget.setLayout(topLayout)
        self.dataWidget.setLayout(bottomLayout)

    def createTabView(self):
        centralWidget = centraltabwidget.CentralTabWidget()
        self.mainWidget.setData(self.uid)
        #centralWidget.addTab(self.scrollArea, "Well plot "+str(self.uid[0]))
        centralWidget.addTab(self.mainWidget, "Well plot " + str(self.uid[0]))

    def createToolWidget(self):
        if len(self._logs) > 0:
            toolbar = logsettingstoolbar.LogSettingsToolbar()
            toolbar.setData(self._well, self._logSet, self.canvas,
                            self.depthPlot, self.headerPlot)
            toolbar.emitShowToolbarSignal()
            logger.debug("<<createToolWidget() toolbar created")
Beispiel #9
0
class pngDisplay(QWidget):
    def __init__(self, parent=None):
        super(pngDisplay, self).__init__(parent)
        #self.profiler = cProfile.Profile()
        # create the label that displays the image - cribbing from the Image
        # Viewer example in the Qt docs.
        self.imLabel = QLabel()
        self.imLabel.setBackgroundRole(QPalette.Base)
        self.imLabel.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
        self.imLabel.setScaledContents(True)
        # Create a gray field to use when no png is available
        self.defaultPM = QPixmap(700,900)
        self.defaultPM.fill(QColor("gray"))
        # Create a scroll area within which to display our imLabel, this
        # enables the creation of horizontal and vertical scroll bars, when
        # the imLabel exceeds the size of the scroll area.
        self.scarea = QScrollArea()
        # The following two lines make sure that page up/dn gets through
        # the scrollarea widget and up to us.
        self.setFocusPolicy(Qt.ClickFocus)
        self.scarea.setFocusProxy(self)
        self.scarea.setBackgroundRole(QPalette.Dark)
        #self.scarea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        #self.scarea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        self.scarea.setWidget(self.imLabel)
        # create the text label that will have the page number in it
        self.txLabel = QLabel(u"No image")
        self.txLabel.setAlignment(Qt.AlignBottom | Qt.AlignHCenter)
        self.txLabel.setFrameStyle(QFrame.Sunken | QFrame.StyledPanel)
        # Create a spinbox to set the zoom from 15 to 200 with a label:
        # (originally a slider, hence the name)
        self.minZoom = 0.15
        self.maxZoom = 2.00
        self.zlider = QSpinBox()
        self.zlider.setRange(int(100*self.minZoom),int(100*self.maxZoom))
        # connect the value change signal to a slot to handle it
        self.connect(self.zlider, SIGNAL("valueChanged(int)"), self.newZoomFactor)
        # create the to-width and to-height zoom buttons
        zoomWidthButton = QPushButton(u'to Width')
        self.connect(zoomWidthButton, SIGNAL("clicked()"), self.zoomToWidth)
        zoomHeightButton = QPushButton(u'to Height')
        self.connect(zoomHeightButton, SIGNAL("clicked()"), self.zoomToHeight)
        # Make an hbox to contain the spinbox and two pushbuttons, with
        # stretch on left and right to center the group.
        zlabel = QLabel(
            u'&Zoom ' + str(self.zlider.minimum())
            + '-' + str(self.zlider.maximum()) + '%')
        zlabel.setBuddy(self.zlider)
        zhbox = QHBoxLayout()
        zhbox.addStretch(1)
        zhbox.addWidget(zlabel,0,Qt.AlignLeft)
        zhbox.addWidget(self.zlider,0)
        zhbox.addStretch(1)
        zhbox.addWidget(zoomWidthButton)
        zhbox.addWidget(zoomHeightButton)
        zhbox.addStretch(1)
        # With all the pieces in hand, create our layout basically a
        # vertical stack: scroll area, label, slider box.
        vbox = QVBoxLayout()
        # the image gets a high stretch and default alignment, the text
        # label hugs the bottom and doesn't stretch at all.
        vbox.addWidget(self.txLabel,0,Qt.AlignBottom)
        vbox.addWidget(self.scarea,10)
        vbox.addLayout(zhbox,0)
        self.setLayout(vbox)
        # Initialize assuming no book is open.
        self.ready = False # nothing to display
        # Recover the last-set zoom factor from the settings object, default 1.0
        qv = IMC.settings.value("pngs/zoomFactor",QVariant(1.0))
        self.zoomFactor = qv.toFloat()[0]
        # The following causes entry into newZoomFactor, below, which tests
        # self.ready, hence the latter has to be assigned-to first.
        self.zlider.setValue(int(self.zoomFactor*100))
        self.clear()

    # local subroutine to initialize our contents for an empty edit.
    # called from _init_ and from newPosition when we discover the file
    # has been cleared on us. Don't reset the zoomFactor, leave it as
    # the user last set it.
    def clear(self):
        # Clear the page name, used by pqNotes
        IMC.currentImageNumber = None # will be name of last png file e.g. "002"
        # Clear the page filename, used in our caption label
        self.lastPage = QString() # last file name e.g. "002.png"
        # Clear the path to the pngs folder, used to fetch image files
        self.pngPath = QString()
        # Clear the index of the last-shown page in the page table
        # -1 means no page is being displayed.
        self.lastIndex = -1
        # Clear the index of the next page to display, normally same as last
        self.nextIndex = -1
        # Set not-ready to indicate no pngs directory available.
        self.ready = False
        # Clear out & release storage of our QImage and QPixmaps
        self.pixmap = QPixmap() # null pixmap
        self.image = QImage()
        self.noImage() # show gray image

    # Display a blank gray frame and "No Image" below.
    # Called from clear() above and from showPage when no valid image.
    def noImage(self) :
        self.imLabel.setPixmap(self.defaultPM)
        self.txLabel.setText(u"No image")
        self.lastIndex = -1 # didn't see a prior page
        self.nextIndex = -1

    # This slot gets the main window's signal shuttingDown.
    # We save our current zoom factor into IMC.settings.
    def shuttingDown(self):
        IMC.settings.setValue("pngs/zoomFactor",QVariant(self.zoomFactor))

    # This slot gets pqMain's signal docHasChanged(QString), telling
    # us that a different document has been loaded. This could be for
    # a successful File>Open, or a failed File>Open or File>New.
    # The bookPath is a null QString for File>New, or the full bookPath.
    # If the latter, we convert that into the path to the pngs folder,
    # and see if bookPath/pngs is a directory. If so, we set self.ready
    # to true, indicating it is worthwhile to try opening image files.
    # At this point the gray image is displayed and previously would remain displayed
    # until the user moved the cursor in some way, generating cursorPositionChanged.
    # That's a minor annoyance, to avoid it we will fake that signal now.
    def newFile(self, bookPath):
        if not bookPath.isNull(): # this was successful File>Open
            finf = QFileInfo(bookPath)
            self.pngPath = finf.absolutePath().append(u"/pngs/")
            finf = QFileInfo(self.pngPath)
            if finf.exists() and finf.isDir(): # looking good
                self.ready = True
                self.newPosition()
            else:
                # We could inform the user we couldn't find a pngs folder,
                # but you know -- the user is probably already aware of that.
                self.clear() # just put up the gray default image
        else: # It was a File>New
            self.clear()

    # This function is the slot that is connected to the editor's
    # cursorPositionChanged signal. Its input is cursor position and
    # the page table. Its output is to set self.nextIndex to the
    # desired next image table row, and to call showPage.
    def newPosition(self):
        if self.ready :
            # We have a book and some pngs. Find the position of the higher end
            # of the current selection.
            pos = IMC.editWidget.textCursor().selectionEnd()
            # Get the page table index that matches this position, or -1
            # if that is above the first psep, or there is no page data
            self.nextIndex = IMC.pageTable.getIndex(pos)
        else :# No file loaded or no pngs folder found.
            self.nextIndex = -1
        if self.nextIndex != self.lastIndex :
            self.showPage()

    # Display the page indexed by self.nextIndex. This is called when the cursor
    # moves to a new page (newPosition, above), or when the PageUp/Dn keys are used,
    # (keyPressEvent, below) or when the zoom factor changes in any of several ways.
    def showPage(self):
        # If self.lastIndex is different from self.nextIndex, the page has
        # changed, and we need to load a new image.
        if self.lastIndex != self.nextIndex :
            self.lastIndex = self.nextIndex # don't come here again until it changes.
            if self.lastIndex > -1 :
                # Form the image filename as a Qstring, e.g. "025" and save that for
                # use by pqNotes:
                IMC.currentImageNumber = IMC.pageTable.getScan(self.lastIndex)
                # dbg = unicode(IMC.currentImageNumber)
                # Form the complete filename by appending ".png" and save as
                # self.lastPage for use in forming our caption label.
                self.lastPage = QString(IMC.currentImageNumber).append(QString(u".png"))
                # dbg = unicode(self.lastPage)
                # Form the full path to the image. Try to load it as a QImage.
                pngName = QString(self.pngPath).append(self.lastPage)
                self.image = QImage(pngName,'PNG')
                # dbg = unicode(self.image)
                # dbg = self.image.isNull()
                # If that successfully loaded an image, make sure it is one byte/pixel.
                if not self.image.isNull() \
                   and self.image.format() != QImage.Format_Indexed8 :
                    # It might be Format_Mono (1 bit/pixel) or even Format_RGB32.
                    self.image = self.image.convertToFormat(QImage.Format_Indexed8,Qt.ColorOnly)
                # Convert the image to a pixmap. If it's null, so is the pixmap.
                self.pixmap = QPixmap.fromImage(self.image,Qt.ColorOnly)
            else :
                IMC.currentImageNumber = QString(u"n.a.")
                self.lastPage = QString()
                self.image = QImage()
                self.pixmap = QPixmap()
        if not self.pixmap.isNull():
            # We successfully found and loaded an image and converted it to pixmap.
            # Load it in our label for display, set the zoom factor, and the caption.
            # We do this every time through (even if lastIndex equalled nextIndex)
            # because the zoomfactor might have changed.
            self.imLabel.setPixmap(self.pixmap)
            self.imLabel.resize( self.zoomFactor * self.pixmap.size() )
            folio = IMC.pageTable.getDisplay(self.lastIndex)
            self.txLabel.setText(u"image {0} (folio {1})".format(self.lastPage,folio))
        else: # no file was loaded. It's ok if pages are missing
            self.noImage() # display the gray image.

    # Catch the signal from the Zoom spinbox with a new value.
    # Store the new value as a float, and if we have a page, repaint it.
    def newZoomFactor(self,new_value):
        self.zoomFactor = new_value / 100
        if self.ready :
            self.showPage()

    # Catch the click on zoom-to-width and zoom-to height. The job is basically
    # the same for both. 1: Using the QImage that should be in self.image,
    # scan the pixels to find the width (height) of the nonwhite area.
    # 2. Get the ratio of that to our image label's viewport width (height).
    # 4. Set that ratio as the zoom factor and redraw the image. And finally
    # 5. Set the scroll position(s) of our scroll area to left-justify the text.
    #
    # We get access to the pixels using QImage:bits() which gives us a PyQt4
    # "voidptr" that we can index to get byte values.
    #
    def zoomToWidth(self):
        if (not self.ready) or (self.image.isNull()) :
            return # nothing to do here
        #self.profiler.enable() #dbg
        # Query the Color look-up table and build a list of the Green values
        # corresponding to each possible pixel value. Probably there are just
        # two colors so colortab is [0,255] but there could be more, depending
        # on how the PNG was defined, 16 or 32 or even 255 grayscale.
        colortab = [ int((self.image.color(c) >> 4) & 255)
                     for c in range(self.image.colorCount()) ]
        ncols = self.image.width() # number of logical pixels across
        stride = (ncols + 3) & (-4) # number of bytes per scanline
        nrows = self.image.height() # number of pixels high
        vptr = self.image.bits() # uchar * bunch-o-pixel-bytes
        vptr.setsize(stride * nrows) # make the pointer indexable

        # Scan in from left and right to find the outermost dark spots.
        # Looking for single pixels yeilds too many false positives, so we
        # look for three adjacent pixels that sum to less than 32.
        # Most pages start with many lines of white pixels so in hopes of
        # establishing the outer edge early, we start at the middle, go to
        # the end, then do the top half.
        left_side = int(ncols/2) # leftmost dark spot seen so far
        # scan from the middle down
        for r in xrange(int(nrows/2)*stride, (nrows-1)*stride, stride) :
            pa, pb = 255, 255 # virtual white outside border
            for c in xrange(left_side):
                pc = colortab[ ord(vptr[c + r]) ]
                if (pa + pb + pc) < 32 : # black or dark gray pair
                    left_side = c # new, further-left, left margin
                    break # no need to look further on this line
                pa = pb
                pb = pc
        # scan from the top to the middle, hopefully left_side is small now
        for r in xrange(0, int(nrows/2)*stride, stride) :
            pa, pb = 255, 255 # virtual white outside border
            for c in xrange(left_side):
                pc = colortab[ ord(vptr[c + r]) ]
                if (pa + pb + pc) < 32 : # black or dark gray pair
                    left_side = c # new, further-left, left margin
                    break # no need to look further on this line
                pa = pb
                pb = pc
        # Now do the same for the right margin.
        right_side = int(ncols/2) # rightmost dark spot seen so far
        for r in xrange(int(nrows/2)*stride, (nrows-1)*stride, stride) :
            pa, pb = 255, 255 # virtual white outside border
            for c in xrange(ncols-1,right_side,-1) :
                pc = colortab[ ord(vptr[c + r]) ]
                if (pa + pb + pc) < 32 : # black or dark gray pair
                    right_side = c # new, further-right, right margin
                    break
                pa = pb
                pb = pc
        for r in xrange(0, int(nrows/2)*stride, stride)  :
            pa, pb = 255, 255 # virtual white outside border
            for c in xrange(ncols-1,right_side,-1) :
                pc = colortab[ ord(vptr[c + r]) ]
                if (pa + pb + pc) < 32 : # black or dark gray pair
                    right_side = c # new, further-right, right margin
                    break
                pa = pb
                pb = pc
        # The area with color runs from left_side to right_side. How does
        # that compare to the size of our viewport? Scale to that and redraw.
        #print('ls {0} rs {1} vp {2}'.format(left_side,right_side,self.scarea.viewport().width()))
        text_size = right_side - left_side + 2
        port_width = self.scarea.viewport().width()
        self.zoomFactor = max( self.minZoom, min( self.maxZoom, port_width / text_size ) )
        # the next line signals newZoomFactor, which calls showPage.
        self.zlider.setValue(int(100*self.zoomFactor))
        # Set the scrollbar to show the page from its left margin.
        self.scarea.horizontalScrollBar().setValue(int( left_side * self.zoomFactor) )
        #self.profiler.disable() #dbg
        #pstats.Stats(self.profiler).print_stats() # dbg


    def zoomToHeight(self):
        if (not self.ready) or (self.image.isNull()) :
            return # nothing to do here
        # Query the Color look-up table and build a list of the Green values
        # corresponding to each possible pixel value. Probably there are just
        # two colors so colortab is [0,255] but there could be more, depending
        # on how the PNG was defined, 16 or 32 or even 255 grayscale.
        colortab = [ int((self.image.color(c) >> 4) & 255)
                     for c in range(self.image.colorCount()) ]
        ncols = self.image.width() # number of logical pixels across
        stride = (ncols + 3) & (-4) # number of bytes per scanline
        nrows = self.image.height() # number of pixels high
        vptr = self.image.bits() # uchar * bunch-o-pixel-bytes
        vptr.setsize(stride * nrows) # make the pointer indexable
        # Scan in from top and bottom to find the outermost rows with
        # significant pixels.
        top_side = -1 # The uppermost row with a significant spot of black
        offset = 0 # vptr index to the first/next pixel row
        for r in range(nrows) :
            pa, pb = 255, 255 # virtual white outside border
            for c in range(ncols) :
                pc = colortab[ ord(vptr[offset + c]) ]
                if (pa + pb + pc) < 32 : # black or dark gray triplet
                    top_side = r # that's the row,
                    break # ..so stop scanning
                pa, pb = pb, pc
            if top_side >= 0 : # we hit
                break # ..so don't scan down any further
            offset += stride # continue to next row
        # top_side indexes the first row with a significant blot
        if top_side == -1 : # never found one: an all-white page. bug out.
            return
        bottom_side = nrows # The lowest row with a significant blot
        offset = stride * nrows # vptr index to last/next row of pixels
        for r in range(nrows,top_side,-1) :
            offset -= stride
            pa, pb = 255, 255 # virtual white outside border
            for c in range(ncols) :
                pc = colortab[ ord(vptr[offset + c]) ]
                if (pa + pb + pc) < 32 : # black or dark gray triplet
                    bottom_side = r
                    break
                pa, pb = pb, pc
            if bottom_side < nrows : # we hit
                break
        # bottom_side is the lowest row with significant pixels. It must be
        # < nrows, there is at least one row (top_side) with a dot in it.
        # However if the page is mostly white, don't zoom to that extent.
        if bottom_side < (top_side+100) :
            return # seems to be a mostly-white page, give up
        # The text area runs from scanline top_side to bottom_side.
        text_height = bottom_side - top_side + 1
        port_height = self.scarea.viewport().height()
        self.zoomFactor = max( self.minZoom, min( self.maxZoom, port_height / text_height ) )
        self.zlider.setValue(int(100*self.zoomFactor)) # signals newZoomFactor->showPage
        # Set the scrollbar to show the page from its top margin.
        self.scarea.verticalScrollBar().setValue(int( top_side * self.zoomFactor) )

    # Re-implement the parent's keyPressEvent in order to provide zoom:
    # ctrl-plus increases the image size by 1.25
    # ctrl-minus decreases the image size by 0.8
    # Also trap pageup/dn and use to walk through images.
    # At this point we do not reposition the editor to match the page viewed.
    # we page up/dn but as soon as focus returns to the editor and the cursor
    # moves, this display will snap back to the edited page. As a user that
    # seems best, come over to Pngs and page ahead to see what's coming, then
    # back to the editor to read or type.
    def keyPressEvent(self, event):
        # assume we will not handle this key and clear its accepted flag
        event.ignore()
        # If we are initialized and have displayed some page, look at the key
        if self.ready:
            kkey = int( int(event.modifiers()) & IMC.keypadDeModifier) | int(event.key())
            if kkey in IMC.zoomKeys :
                # ctl/cmd + or -, do the zoom
                event.accept()
                fac = (0.8) if (kkey == IMC.ctl_minus) else (1.25)
                fac *= self.zoomFactor # target zoom factor
                if (fac >= self.minZoom) and (fac <= self.maxZoom): # keep in bounds
                    self.zoomFactor = fac
                    self.zlider.setValue(int(100*fac))
                    self.showPage()
            elif (event.key() == Qt.Key_PageUp) or (event.key() == Qt.Key_PageDown) :
                event.accept() # real pgUp or pgDn, we do it
                fac = 1 if (event.key() == Qt.Key_PageDown) else -1
                fac += self.lastIndex
                if (fac >= 0) and (fac < IMC.pageTable.size()) :
                    # not off either end of the book, so,
                    self.nextIndex = fac
                    self.showPage()
        if not event.isAccepted() : # we don't do those, pass them on
            super(pngDisplay, self).keyPressEvent(event)
Beispiel #10
0
class WTestPng(Document.WDocument):
    """
    Test png widget
    """
    def __init__(self,
                 parent=None,
                 path=None,
                 filename=None,
                 extension=None,
                 nonameId=None,
                 remoteFile=True,
                 repoDest=None,
                 project=0):
        """
        Constructs WScript widget

        @param parent: 
        @type parent: 

        @param path: 
        @type path: 

        @param filename: 
        @type filename: 

        @param extension: 
        @type extension: 

        @param nonameId: 
        @type nonameId: 
        """
        Document.WDocument.__init__(self, parent, path, filename, extension,
                                    nonameId, remoteFile, repoDest, project)
        self.scaleFactor = 0.0
        self.rawContent = ''
        self.createWidgets()
        self.createActions()
        self.createToolbar()
        self.createConnections()

    def createActions(self):
        """
        Create qt actions
        """
        self.zoomInAct = QtHelper.createAction(self,
                                               "&Zoom &In (25%.",
                                               self.zoomIn,
                                               icon=QIcon(":/zoom-in.png"))
        self.zoomOutAct = QtHelper.createAction(self,
                                                "Zoom &Out (25%.",
                                                self.zoomOut,
                                                icon=QIcon(":/zoom-out.png"))
        self.normalSizeAct = QtHelper.createAction(
            self,
            "&Normal Size",
            self.normalSize,
            icon=QIcon(":/zoom-normal.png"))

    def createToolbar(self):
        """
        Toolbar creation
            
        ||------|------|||
        || Open | Save |||
        ||------|------|||
        """
        self.dockToolbar.setObjectName("Test Config toolbar")
        self.dockToolbar.addAction(self.zoomInAct)
        self.dockToolbar.addAction(self.zoomOutAct)
        self.dockToolbar.addAction(self.normalSizeAct)
        self.dockToolbar.addSeparator()
        self.dockToolbar.setIconSize(QSize(16, 16))

    def createWidgets(self):
        """
        QtWidgets creation
        """
        self.dockToolbar = QToolBar(self)
        self.dockToolbar.setStyleSheet(
            "QToolBar { border: 0px }")  # remove 3D border

        self.imageLabel = QLabel(self)
        self.imageLabel.setBackgroundRole(QPalette.Base)
        self.imageLabel.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
        self.imageLabel.setScaledContents(True)

        self.scrollArea = QScrollArea()
        self.scrollArea.setBackgroundRole(QPalette.Dark)
        self.scrollArea.setWidget(self.imageLabel)

        title = QLabel("Image:")
        title.setStyleSheet("QLabel { padding-left: 2px; padding-top: 2px }")
        font = QFont()
        font.setBold(True)
        title.setFont(font)

        layout = QVBoxLayout()
        layout.addWidget(title)
        layout.addWidget(self.dockToolbar)
        layout.addWidget(self.scrollArea)
        layout.setContentsMargins(2, 2, 2, 2)
        self.setLayout(layout)

    def zoomIn(self):
        """
        Zoom in
        """
        self.scaleImage(1.25)

    def zoomOut(self):
        """
        Zoom out
        """
        self.scaleImage(0.8)

    def normalSize(self):
        """
        Normal size
        """
        self.imageLabel.adjustSize()
        self.scaleFactor = 1.0

    def scaleImage(self, factor):
        """
        Scale image
        """
        self.scaleFactor *= factor
        self.imageLabel.resize(self.scaleFactor *
                               self.imageLabel.pixmap().size())

        self.adjustScrollBar(self.scrollArea.horizontalScrollBar(), factor)
        self.adjustScrollBar(self.scrollArea.verticalScrollBar(), factor)

    def adjustScrollBar(self, scrollBar, factor):
        """
        Adjust scrollbar
        """
        scrollBar.setValue(
            int(factor * scrollBar.value() +
                ((factor - 1) * scrollBar.pageStep() / 2)))

    def createConnections(self):
        """
        QtSignals connection
        """
        pass

    def write(self, force=False):
        """
        Save 
        """
        absPath = '%s/%s.%s' % (self.path, self.filename, self.extension)
        try:
            with open(absPath, mode='wb') as myfile:
                myfile.write(self.rawContent)
        except Exception as e:
            self.error("unable to write png file: %s" % e)
            return None
        else:
            self.setUnmodify()
            return True

    def load(self, content=None):
        """
        Open file
        """
        if content is None:
            absPath = '%s/%s.%s' % (self.path, self.filename, self.extension)
            file = QFile(absPath)
            if not file.open(QIODevice.ReadOnly):
                self.error("Error opening image file: %s" % absPath)
                return False
            else:
                content = file.readAll()

        self.rawContent = content
        image = QImage()
        image.loadFromData(content)
        if image.isNull():
            self.error("cannot load image")
            return False
        else:
            self.imageLabel.setPixmap(QPixmap.fromImage(QImage(image)))
            self.scaleFactor = 1.0
            self.imageLabel.adjustSize()

            return True

    def getraw_encoded(self):
        """
        Returns raw data encoded
        """
        encoded = ''
        try:
            encoded = base64.b64encode(self.rawContent)
        except Exception as e:
            self.error('unable to encode raw image: %s' % str(e))
        return encoded