예제 #1
0
class NotificationServer(QObject):
    def __init__(self, parent=None):
        QObject.__init__(self, parent)
        self.notifications = set()
        self.size = QSize(300, 100)
        self.margin = QPoint(10, 10)

    def notify(self, html):
        note = Notification(html)
        self.connect(note, SIGNAL("done"), self.noteDestroyed)

        desktop = QApplication.desktop().availableGeometry(note)
        me = QRect(QPoint(0, 0), self.size)
        me.moveBottomRight(desktop.bottomRight() - self.margin)
        while self.notePosTaken(me):
            me.translate(0, 0 - (self.size.height() + (self.margin.y() * 2)))
            if not desktop.contains(me):
                me.moveBottom(desktop.bottom() - self.margin.y())
                me.translate(0 - (self.size.width() + self.margin.x() * 2), 0)

        note.setGeometry(me)
        self.notifications.add(note)
        note.display()

    def notePosTaken(self, rect):
        for note in self.notifications:
            if note.geometry().intersects(rect):
                return True
        return False

    def noteDestroyed(self, note):
        self.notifications.remove(note)
예제 #2
0
 def get_border(self, p: QPoint):
     if p.x() <= 2:
         return Alignment.Left
     elif p.x() >= self.width() - 2:
         return Alignment.Right
     elif p.y() <= 2:
         return Alignment.Top
     elif p.y() >= self.height() - 2:
         return Alignment.Bottom
     return None
예제 #3
0
 def get_border(self, p: QPoint):
     if p.x() <= 2:
         return Alignment.Left
     elif p.x() >= self.width() - 2:
         return Alignment.Right
     elif p.y() <= 2:
         return Alignment.Top
     elif p.y() >= self.height() - 2:
         return Alignment.Bottom
     return None
예제 #4
0
class MovingMessage(FadeMessage):
    def __init__(self, message, str=None, pos=None):
        cfg = Config('messages', message)

        if (pos is None):
            self.pos = QPoint(*cfg.get('position'))
        else:
            self.pos = QPoint(*pos)

        self.velocity = cfg.get('velocity')

        FadeMessage.__init__(self, message, str)

    def with_controller(self):
        self.rect = QRect(0, 0, self.controller.width(),
                          self.controller.height())
        self.rect.moveCenter(self.pos)

    def tick(self, elapsed):
        FadeMessage.tick(self, elapsed)

        self.pos.setX(self.pos.x() + self.velocity[0] * elapsed)
        self.pos.setY(self.pos.y() + self.velocity[1] * elapsed)

        self.rect.moveCenter(self.pos)

    def draw(self):
        FadeMessage.draw(self)

        if (self.color.alpha() == 0):
            self.rect = self.bounding_text_rect
예제 #5
0
class MovingMessage(FadeMessage):
    def __init__(self, message, str = None, pos = None):
        cfg = Config('messages', message)
        
        if (pos is None):
            self.pos = QPoint(*cfg.get('position'))
        else:
            self.pos = QPoint(*pos)
        
        self.velocity = cfg.get('velocity') 
        
        FadeMessage.__init__(self, message, str)
    
    def with_controller(self):
        self.rect = QRect(0, 0, self.controller.width(), self.controller.height())
        self.rect.moveCenter(self.pos)

    def tick(self, elapsed):        
        FadeMessage.tick(self, elapsed)

        self.pos.setX(self.pos.x() + self.velocity[0] * elapsed)
        self.pos.setY(self.pos.y() + self.velocity[1] * elapsed)
        
        self.rect.moveCenter(self.pos)
    
    def draw(self):
        FadeMessage.draw(self)
        
        if (self.color.alpha() == 0):
            self.rect = self.bounding_text_rect
예제 #6
0
	def readSettings(self):
		self.imageFolder = os.path.normpath(str(self.settings.value("imageFolder").toString()))
		self.ui.actionIgnore_Transparent_Pixels.setChecked( self.settings.value("ignoreAlpha", True).toBool())
		self.ui.actionCheck_for_update_at_start.setChecked( self.settings.value("checkupdate", True).toBool())
		self.ui.tolerance_le.setText( self.settings.value("tolerance").toString())
		self.settings.beginGroup("/geometry")
		p = QPoint()  # position
		s = QSize()  # size

		x = self.settings.value("X", -1).toInt()[0]
		y = self.settings.value("Y", -1).toInt()[0]
		# don't position outside current screen
		qRect = QtGui.QDesktopWidget.availableGeometry(app.desktop())
		if x > qRect.right():
			x = 10
		if y > qRect.bottom():
			y = 10
		p.setX(x)
		p.setY(y)
		s.setWidth(self.settings.value("W", -1).toInt()[0])
		s.setHeight(self.settings.value("H", -1).toInt()[0])
		self.settings.endGroup()
		if p.x() > 0 and p.y() > 0 and s.width() > 0 and s.height() > 0:
			self.resize(s)  # restore size
			self.move(p)  # restore position
예제 #7
0
 def contains(self, p: QPoint):
     d = self.size * Info.dpi
     pos = self.real_pos()
     dx = pos.x() - p.x()
     dy = pos.y() - p.y()
     if dx * dx + dy * dy <= d * d:
         return True
     return False
예제 #8
0
 def showPopup(self):
     if not self.popup:
         return
     pos = QPoint(self.width(), self.height())
     pos = self.mapToGlobal(pos)
     size = self.popup.size()
     self.popup.move(pos.x() - size.width(), pos.y())
     self.popup.show()
예제 #9
0
 def contains(self, p: QPoint):
     d = self.size * Info.dpi
     pos = self.real_pos()
     dx = pos.x() - p.x()
     dy = pos.y() - p.y()
     if dx * dx + dy * dy <= d * d:
         return True
     return False
예제 #10
0
 def showPopup(self):
     if not self.popup:
         return
     pos = QPoint(self.width(), self.height())
     pos = self.mapToGlobal(pos)
     size = self.popup.size()
     self.popup.move(pos.x() - size.width(), pos.y())
     self.popup.show()
예제 #11
0
    def kineticMove(self, oldx, oldy, newx, newy ):
        """Start a kinetic move from (oldx, oldy) to (newx, newy)"""
        if newx == oldx and newy == oldy:
            return
        
        speed = QPoint(0,0)
        # solve speed*(speed+1)/2 = delta to ensure 1+2+3+...+speed is as close as possible under delta..
        speed.setX((sqrt(1+8*abs(newx-oldx))-1)/2)
        speed.setY((sqrt(1+8*abs(newy-oldy))-1)/2)
        
        # compute the amount of displacement still needed because we're dealing with integer values.
        diff = QPoint(0,0)
        diff.setX(-abs(newx-oldx) + speed.x()*(speed.x()+1)/2)
        diff.setY(-abs(newy-oldy) + speed.y()*(speed.y()+1)/2)

        # Since this function is called for exact moves (not free scrolling)
        # limit the kinetic time to 2 seconds, which means 100 ticks, 5050 pixels.
        if speed.y() > 100:
            speed.setY(100)
            diff.setY(-abs(newy-oldy) + 5050)
            
        # Although it is less likely to go beyond that limit for horizontal scrolling,
        # do it for x as well.
        if speed.x() > 100:
            speed.setX(100)
            diff.setX(-abs(newx-oldx) + 5050)
        
        # move left or right, up or down
        if newx > oldx :
            speed.setX(-speed.x())
            diff.setX(-diff.x())
        if newy > oldy :
            speed.setY(-speed.y())
            diff.setY(-diff.y())
        
        # move immediately by the step that cannot be handled by kinetic scrolling.
        # By construction that step is smaller that the initial speed value.
        self.fastScrollBy(diff)
        
        self.kineticStart(speed)
예제 #12
0
    def kineticMove(self, oldx, oldy, newx, newy):
        """Start a kinetic move from (oldx, oldy) to (newx, newy)"""
        if newx == oldx and newy == oldy:
            return

        speed = QPoint(0, 0)
        # solve speed*(speed+1)/2 = delta to ensure 1+2+3+...+speed is as close as possible under delta..
        speed.setX((sqrt(1 + 8 * abs(newx - oldx)) - 1) / 2)
        speed.setY((sqrt(1 + 8 * abs(newy - oldy)) - 1) / 2)

        # compute the amount of displacement still needed because we're dealing with integer values.
        diff = QPoint(0, 0)
        diff.setX((speed.x() * (speed.x() + 1) // 2) - abs(newx - oldx))
        diff.setY((speed.y() * (speed.y() + 1) // 2) - abs(newy - oldy))

        # Since this function is called for exact moves (not free scrolling)
        # limit the kinetic time to 2 seconds, which means 100 ticks, 5050 pixels.
        if speed.y() > 100:
            speed.setY(100)
            diff.setY(-abs(newy - oldy) + 5050)

        # Although it is less likely to go beyond that limit for horizontal scrolling,
        # do it for x as well.
        if speed.x() > 100:
            speed.setX(100)
            diff.setX(-abs(newx - oldx) + 5050)

        # move left or right, up or down
        if newx > oldx:
            speed.setX(-speed.x())
            diff.setX(-diff.x())
        if newy > oldy:
            speed.setY(-speed.y())
            diff.setY(-diff.y())

        # move immediately by the step that cannot be handled by kinetic scrolling.
        # By construction that step is smaller that the initial speed value.
        self.fastScrollBy(diff)

        self.kineticStart(speed)
예제 #13
0
    def drawNetwork(self, qp):

    #for each vehicle
        for j in range(len(self.vehicleList)):
        #we check others vehicles
            for k in range(len(self.vehicleList)):
                #if we are testing the current vehicle
                if j == k:
                    continue
                # if we are testing an other vehicle
                else:
                    # calculating the distance between the 2 vehicles
                    xDiff = self.vehicleList[k].position.x() - self.vehicleList[j].position.x()
                    yDiff = self.vehicleList[k].position.y() - self.vehicleList[j].position.y()
                    dist = math.sqrt(math.pow(xDiff, 2) + math.pow(yDiff, 2))
                    if dist < globalvars.msg_distance:
                        # creating a connection between the 2 vehicles
                        qp.drawLine(
                            self.vehicleList[j].position.x(),
                            self.vehicleList[j].position.y(),
                            self.vehicleList[k].position.x(),
                            self.vehicleList[k].position.y()
                        )

            # creating a random movement
            if not self.isPause:
                isPosX = bool(random.getrandbits(1))
                isPosY = bool(random.getrandbits(1))
                if isPosX:
                    if self.vehicleList[j].position.x() < self.size.width() - 50:
                        self.vehicleList[j].position.setX(self.vehicleList[j].position.x() + 1)
                else:
                    if self.vehicleList[j].position.x() > 25:
                        self.vehicleList[j].position.setX(self.vehicleList[j].position.x() - 1)

                if isPosY:
                    if self.vehicleList[j].position.y() < self.size.height() - 50:
                        self.vehicleList[j].position.setY(self.vehicleList[j].position.y() + 1)
                else:
                    if self.vehicleList[j].position.y() > 25:
                       self.vehicleList[j].position.setY(self.vehicleList[j].position.y() - 1)

                
                pos = QPoint(self.vehicleList[j].position.x() - (self.vehicleImg[j].size().width()/2), 
                             self.vehicleList[j].position.y() - (self.vehicleImg[j].size().height()/2))
                self.vehicleImg[j].move(pos.x(), pos.y())


        time.sleep(0.001)
        # calling paintEvent
        self.update()
예제 #14
0
class Circle():
    def __init__(self, diameter, x, y):
        self.diameter = diameter
        self.radius = math.floor(diameter / 2.0)
        self.center = QPoint(x, y)

    def drawCircle(self, event, qp):
        qp.setBrush(QtGui.QColor(34, 34, 200))
        qp.drawEllipse(self.center, self.radius, self.radius)

    def isClicked(self, pos):
        result = math.pow((pos.x() - self.center.x()), 2) + math.pow(
            (pos.y() - self.center.y()), 2)
        if result <= math.pow(self.radius, 2):
            return True
        else:
            return False

    def x(self):
        return self.center.x()

    def y(self):
        return self.center.y()
예제 #15
0
class Circle():

    def __init__(self, diameter, x, y):
        self.diameter = diameter
        self.radius = math.floor(diameter / 2.0)
        self.center = QPoint(x, y)

    def drawCircle(self, event, qp):
        qp.setBrush(QtGui.QColor(34, 34, 200))
        qp.drawEllipse(self.center, self.radius, self.radius)

    def isClicked(self, pos):
        result = math.pow((pos.x() - self.center.x()), 2) + math.pow((pos.y() - self.center.y()), 2)
        if result <= math.pow(self.radius, 2):
            return True
        else:
            return False

    def x(self):
        return self.center.x()

    def y(self):
        return self.center.y()
예제 #16
0
 def kineticAddDelta(self, delta ):
     """Add a kinetic delta to an already started kinetic move."""
     speed = QPoint(0,0)
     
     # Get the remaining scroll amount.
     currentSpeed = abs( self._kineticData._speed.y() )
     leftToScroll = (currentSpeed+1)*currentSpeed / 2 ;
     if self._kineticData._speed.y() < 0:
         leftToScroll *= -1
     leftToScroll += delta
     
     speed.setY((sqrt(1+8*abs(leftToScroll))-1)/2)
     speed.setX( self._kineticData._speed.x() )
     if leftToScroll < 0:
         speed.setY(-speed.y())
         
     self.kineticStart(speed)
예제 #17
0
class Window(QLabel):

    #First of all, user can watch the full screenshot
    def __init__(self, parent=None):

        QLabel.__init__(self, parent)
        self.rubberBand = QRubberBand(QRubberBand.Rectangle, self)
        self.origin = QPoint()

        img = QPixmap.grabWindow(QApplication.desktop().winId())
        self.setPixmap(img)

    #Using Mouse, user can select area of screenshot to choose word(english) for searching.
    # This version cannot support capture of area.

    def mousePressEvent(self, event):

        if event.button() == Qt.LeftButton:
            self.origin = QPoint(event.pos())
            posDictionary1.append(self.origin.x())
            posDictionary1.append(self.origin.y())
            self.rubberBand.setGeometry(QRect(self.origin, QSize()))
            self.rubberBand.show()

    def mouseMoveEvent(self, event):

        if not self.origin.isNull():
            self.rubberBand.setGeometry(
                QRect(self.origin, event.pos()).normalized())

    def mouseReleaseEvent(self, event):

        if event.button() == Qt.LeftButton:
            x = (QPoint(event.pos())).x()
            y = (QPoint(event.pos())).y()

            posDictionary2.append(x)
            posDictionary2.append(y)
            self.rubberBand.hide()
            self.close()

            Capture(posDictionary1[0], posDictionary1[1], posDictionary2[0],
                    posDictionary2[1])
            Result_Window()
예제 #18
0
 def __init__(self, level_number, level):
     self.level_number = level_number
     
     self.info = {}
     self.fields = set()
     
     self.level = level
     self.player_state = Player.get_instance()
             
     cfg = Config('interface', 'Settings')
     font_name = cfg.get('field_font')
     font_size = cfg.get('field_font_sz')
     self.field_font = FontManager.getFont(font_name)
     self.field_font.setPointSize(font_size)
     self.field_color = QColor.fromRgb(*cfg.get('field_color'))
     
     for f_name in ConfigManager.getOptions('interface', 'Fields'):
         s = ConfigManager.getVal('interface', 'Fields', f_name)
         s = map(str.strip, s.split('||'))
         
         img = QImage('resources/images/'+s[0])
         img_pos = QPoint(*eval(s[1]))
         info_rect = QRect(*eval(s[2]))
         scale = float(s[3])
         
         if (len(s) >= 5):
             font = QFont(self.field_font)
             font.setPointSize(int(s[4]))
         else:
             font = self.field_font
         
         img_w, img_h = img.width(), img.height()
         img_rect = QRect(
             img_pos.x(), img_pos.y(),
             int(img_w*scale), int(img_h*scale)
         )
         
         self.info[f_name] = ''
         
         self.fields.add(Field(f_name, img, img_rect, info_rect, font))
     
     self.radar = Radar.from_config('E-Radar', self)
     self.missile = GuidedMissile.from_config('GuidedMissile', self)
예제 #19
0
파일: drawer.py 프로젝트: kzwkt/dff
    def drawXInfos(self):
        pen = self.painter.pen()
        i = 1
        scale = 6
        x = self.yLeftMargin
        y = self.ploter.height - self.m
        if not self.selDateMin:
            date = self.baseDateMin
            shift_date = (self.baseDateMax - self.baseDateMin) / scale
        else:
            date = self.selDateMin
            shift_date = (self.selDateMax - self.selDateMin) / scale
        while i <= scale + 1:
            pen.setColor(Qt.black)
            pen.setStyle(Qt.SolidLine)
            pos = QPoint(x - 40, y + 17)
            self.painter.setPen(pen)
            # Draw vertical doted line
            self.painter.drawLine(x, y - 3, x, y + 3)
            # Draw date
            self.painter.drawText(
                pos, str(self.timeline.fromUSec(date).strftime('%d.%m.%Y')))
            # If number of days shown < scale, draw time
            if shift_date <= (86400 * 1000000):
                pos.setY(pos.y() + 15)
                pos.setX(pos.x() + 9)
                # Draw time
                self.painter.drawText(
                    pos,
                    str(self.timeline.fromUSec(date).strftime('%H:%M:%S')))

            pen.setColor(Qt.gray)
            pen.setStyle(Qt.DotLine)
            self.painter.setPen(pen)
            if i != 1:
                self.painter.drawLine(x, y + 3, x, self.m / 3)
            x = self.yLeftMargin + (i * (
                (self.ploter.width - self.m - self.yLeftMargin) / (scale)))
            i += 1
            date += shift_date
        pen.setStyle(Qt.SolidLine)
        self.painter.setPen(pen)
예제 #20
0
파일: drawer.py 프로젝트: halbbob/dff
  def drawXInfos(self):
    pen = self.painter.pen()
    i = 1
    scale = 6
    x = self.yLeftMargin
    y = self.ploter.height - self.m
    if not self.selDateMin:
      date = self.baseDateMin
      shift_date = (self.baseDateMax - self.baseDateMin) / scale
    else:
      date = self.selDateMin
      shift_date = (self.selDateMax - self.selDateMin) / scale
    while i <= scale + 1:
      pen.setColor(Qt.black)
      pen.setStyle(Qt.SolidLine)
      pos = QPoint(x - 40, y + 17)
      self.painter.setPen(pen)
# Draw vertical doted line
      self.painter.drawLine(x, y - 3, x, y + 3)
# Draw date
      self.painter.drawText(pos, str(self.timeline.fromUSec(date).strftime('%d.%m.%Y')))
# If number of days shown < scale, draw time
      if shift_date <= (86400 * 1000000):
        pos.setY(pos.y() + 15)
        pos.setX(pos.x() + 9)
# Draw time
        self.painter.drawText(pos, str(self.timeline.fromUSec(date).strftime('%H:%M:%S')))
      
      pen.setColor(Qt.gray)
      pen.setStyle(Qt.DotLine)
      self.painter.setPen(pen)
      if i != 1:
        self.painter.drawLine(x, y + 3, x, self.m / 3)
      x = self.yLeftMargin + (i * ((self.ploter.width - self.m - self.yLeftMargin) / (scale)))
      i += 1
      date += shift_date
    pen.setStyle(Qt.SolidLine)
    self.painter.setPen(pen)
예제 #21
0
class VispaWidgetOwner(object):
    """ Interface for classes containing VispaWidgets
    
    Only makes sense if implementing class also inherits QWidget or class inheriting QWidget.
    """
    def enableMultiSelect(self, multiSelect=True):
        self._multiSelectEnabledFlag = multiSelect

    def multiSelectEnabled(self):
        return hasattr(
            self, "_multiSelectEnabledFlag") and self._multiSelectEnabledFlag

    def selectedWidgets(self):
        """ Returns a list of all selected widgets.
        """
        if hasattr(self, "_selectedWidgets"):
            return self._selectedWidgets
        return [
            child for child in self.children()
            if hasattr(child, "isSelected") and child.isSelected()
        ]

    def widgetSelected(self, widget, multiSelect=False):
        """ Forward selection information to super class if it is a VispaWidgetOwner.
        """
        logging.debug(self.__class__.__name__ + ": widgetSelected()")

        if isinstance(self, QObject):
            if not hasattr(self, "_selectedWidgets"):
                self._selectedWidgets = []

            if not multiSelect or not self.multiSelectEnabled():
                self.deselectAllWidgets(widget)
                self._selectedWidgets = []

            if widget.parent() == self and not widget in self._selectedWidgets:
                self._selectedWidgets.append(widget)

            for widget in [
                    child for child in self._selectedWidgets
                    if hasattr(child, "isSelected") and not child.isSelected()
            ]:
                self._selectedWidgets.remove(widget)

            if isinstance(self.parent(), VispaWidgetOwner):
                self.parent().widgetSelected(widget)

    def widgetDoubleClicked(self, widget):
        """ Forward selection information to super class if it is a VispaWidgetOwner.
        """
        #logging.debug(self.__class__.__name__ +": widgetDoubleClicked()")
        if isinstance(self, QObject):
            if isinstance(self.parent(), VispaWidgetOwner):
                self.parent().widgetDoubleClicked(widget)

    def initWidgetMovement(self, widget):
        self._lastMovedWidgets = []
        if self.multiSelectEnabled():
            pos = widget.pos()
            for child in self.children():
                if child != widget and hasattr(
                        child, "isSelected") and child.isSelected():
                    child.setDragReferencePoint(pos - child.pos())

    def widgetDragged(self, widget):
        """ Tell parent widget has moved.
        
        Only informs parent if it is a VispaWidgetOwner, too.
        """
        if isinstance(self.parent(), VispaWidgetOwner):
            self.parent().widgetDragged(widget)

        if hasattr(self, "_lastMovedWidgets"):
            self._lastMovedWidgets.append(widget)

        if self.multiSelectEnabled():
            for child in self.children():
                if hasattr(
                        child,
                        "dragReferencePoint") and child != widget and hasattr(
                            child, "isSelected") and child.isSelected():
                    if hasattr(child, "setPreviousDragPosition"):
                        child.setPreviousDragPosition(child.pos())
                    child.move(widget.pos() - child.dragReferencePoint())
                    self._lastMovedWidgets.append(child)

# apparently unused feature (2010-07-02), remove if really unnecessary
# also see self._lastMovedWidget definition above

    def lastMovedWidgets(self):
        if hasattr(self, "_lastMovedWidgets"):
            return self._lastMovedWidgets
        return None

    def widgetAboutToDelete(self, widget):
        """ This function is called from the delete() function of VispaWidget.
        """
        pass

    def keyPressEvent(self, event):
        """ Calls delete() method of selected child widgets if multi-select is activated.
        """
        if self.multiSelectEnabled() and (event.key() == Qt.Key_Backspace
                                          or event.key() == Qt.Key_Delete):
            selection = self.selectedWidgets()[:]
            for widget in selection:
                widget.delete()

    def deselectAllWidgets(self, exception=None):
        """ Deselects all widgets except the widget given as exception.
        """
        #logging.debug(self.__class__.__name__ +": deselectAllWidgets()")
        self._selectedWidgets = []
        for child in self.children():
            if child != exception:
                if hasattr(child, 'select'):
                    child.select(False)
            else:
                self._selectedWidgets.append(child)

            if isinstance(child, VispaWidgetOwner):
                child.deselectAllWidgets(exception)
        self.update()

    def mousePressEvent(self, event):
        """ Calls deselectAllWidgets.
        """
        multiSelectEnabled = self.multiSelectEnabled()
        if event.modifiers() != Qt.ControlModifier:
            self.deselectAllWidgets()
        if multiSelectEnabled:
            self._selectionRectStartPos = QPoint(event.pos())
            self._selectionRect = None

    def mouseMoveEvent(self, event):
        if self.multiSelectEnabled() and self._selectionRectStartPos and (
                event.pos() - self._selectionRectStartPos
        ).manhattanLength() >= QApplication.startDragDistance():
            eventX = event.pos().x()
            eventY = event.pos().y()
            startX = self._selectionRectStartPos.x()
            startY = self._selectionRectStartPos.y()
            oldRect = self._selectionRect
            self._selectionRect = QRect(min(startX, eventX),
                                        min(startY, eventY),
                                        abs(eventX - startX),
                                        abs(eventY - startY))
            if oldRect:
                self.update(
                    self._selectionRect.united(oldRect).adjusted(-5, -5, 5, 5))
            else:
                self.update(self._selectionRect)

            # dynamically update selection statur
            # currently bad performance (2010-07-07)
            # TODO: improve selection mechanism
#            for child in self.children():
#                if hasattr(child, "select") and hasattr(child, "isSelected"):
#                    child.select(self._selectionRect.contains(child.geometry()), True)    # select, mulitSelect

    def mouseReleaseEvent(self, event):
        if hasattr(self, "_selectionRect"
                   ) and self._selectionRect and self.multiSelectEnabled():
            for child in self.children():
                if hasattr(child, "select") and hasattr(
                        child, "isSelected") and self._selectionRect.contains(
                            child.geometry()) and not child.isSelected():
                    child.select(True, True)  # select, mulitSelect
            self.update(self._selectionRect.adjusted(-5, -5, 5, 5))
        self._selectionRect = None
        self._selectionRectStartPos = None
예제 #22
0
class GLWidget(QtOpenGL.QGLWidget):
    """
    This class renders something with OpenGL
    """

    def __init__(self, parent=None):
        """
        Constructor
        """
        self.__image_width = 250
        self.__image_height = 250

        self.__isMouseDown = False
        self.__zoomFactor = 1.0

        self.__scrollOffset = QPoint()

        if hasattr(QGLFormat, "setVersion"):
            # Modern OpenGL
            f = QGLFormat()
            f.setVersion(3, 3)
            f.setProfile(QGLFormat.CoreProfile)
            f.setSampleBuffers(True)
            c = QGLContext(f, None)

            QGLWidget.__init__(self, c, parent)
            print "Version is set to 3.3"
        else:
            QGLWidget.__init__(self, parent)

        # self.__svgItem = QtSvg.QGraphicsSvgItem("circle_star.svg")
        self.__mySvgTool = MySvgTool()

        self.__mySvgWriter = MySvgWriter()
        self.__mySvgWriter.DrawSomething()
        self.__myBufferPainter = MyBufferPainter()

    def initializeGL(self):

        glClearColor(0.5, 0.5, 0.5, 1.0)
        glEnable(GL_DEPTH_TEST)
        glEnable(GL_CULL_FACE)
        glEnable(GL_LINE_SMOOTH)
        glHint(GL_LINE_SMOOTH_HINT, GL_NICEST)

        self.__shaderProgram = QGLShaderProgram()
        if self.__shaderProgram.addShaderFromSourceFile(QGLShader.Vertex, "shader.vert"):
            print "Main - Vertex shader OK"
        if self.__shaderProgram.addShaderFromSourceFile(QGLShader.Fragment, "shader.frag"):
            print "Main - Fragment shader OK"
        self.__shaderProgram.link()

        self.__texCoordLocation = self.__shaderProgram.attributeLocation("uv")
        self.__vertexLocation = self.__shaderProgram.attributeLocation("position")
        self.__colorLocation = self.__shaderProgram.attributeLocation("color")
        self.__use_color_location = self.__shaderProgram.uniformLocation("use_color")
        self.__mvpMatrixLocation = self.__shaderProgram.uniformLocation("mvpMatrix")

        # Returns -1 if name is not a valid attribute for this shader program.
        print "\n__texCoordLocation   :", self.__texCoordLocation, " ", "\n__vertexLocation     :", self.__vertexLocation, " ", "\n__colorLocation      :", self.__colorLocation, " ", "\n__use_color_location :", self.__use_color_location, " ", "\n__mvpMatrixLocation  :", self.__mvpMatrixLocation

        self.__blurProgram = QGLShaderProgram()
        if self.__blurProgram.addShaderFromSourceFile(QGLShader.Vertex, "shader.vert"):
            print "Gaussian blur - Vertex shader OK"

        # if I use shader.frag it's okay ???
        # if self.__blurProgram.addShaderFromSourceFile(QGLShader.Fragment, "gaussian_blur.frag") :
        if self.__blurProgram.addShaderFromSourceFile(QGLShader.Fragment, "gaussian_blur.frag"):
            print "Gaussian blur - fragment shader OK"
        self.__blurProgram.link()

        self.__myBufferPainter.SetThings(self.__shaderProgram, self.__blurProgram)
        self.__myBufferPainter.initializeGL(self.bindTexture(QtGui.QPixmap("laughing_man.png")))
        self.__myBufferPainter.prepareFrameRect(
            self.__scrollOffset.x(), self.__scrollOffset.y(), self.width(), self.height(), self.__zoomFactor
        )

        """
        ### texture
        self.__ori_tex = self.bindTexture(QtGui.QPixmap("laughing_man.png"))

        vertexData = numpy.array([   0.0,   0.0, 0.0, 1.0,
                                     0.0, 250.0, 0.0, 1.0,
                                   250.0, 250.0, 0.0, 1.0,

                                     0.0,   0.0, 0.0, 1.0,
                                   250.0, 250.0, 0.0, 1.0,
                                   250.0,   0.0, 0.0, 1.0,

                                # uv
                                0, 1,
                                0, 0,
                                1, 0,

                                0, 1,
                                1, 0,
                                1, 1],
                                dtype = numpy.float32)

        colorData = numpy.array([1.0, 0.0, 0.0, 1.0,
                                 0.0, 0.0, 1.0, 1.0,
                                 0.0, 1.0, 0.0, 1.0,
                                 1.0, 0.0, 0.0, 1.0,
                                 0.0, 1.0, 0.0, 1.0,
                                 0.0, 0.0, 1.0, 1.0,],
                                 dtype = numpy.float32)

        ### create VAO
        self.__VAO = glGenVertexArrays(1)
        glBindVertexArray(self.__VAO)

        ### create a VBO for position and uv
        posVBO = glGenBuffers(1)
        glBindBuffer(GL_ARRAY_BUFFER, posVBO)
        glBufferData(GL_ARRAY_BUFFER, vertexData.nbytes, vertexData, GL_STATIC_DRAW)
        glEnableVertexAttribArray(self.__vertexLocation)
        glVertexAttribPointer(self.__vertexLocation, 4, GL_FLOAT, GL_FALSE, 0, None)

        glEnableVertexAttribArray(self.__texCoordLocation)
        glVertexAttribPointer(self.__texCoordLocation, 2, GL_FLOAT, GL_FALSE, 0, ctypes.c_void_p(96))

        ### create VBO for color
        colVBO = glGenBuffers(1)
        glBindBuffer(GL_ARRAY_BUFFER, colVBO)
        glBufferData(GL_ARRAY_BUFFER, colorData.nbytes, colorData, GL_STATIC_DRAW)
        glEnableVertexAttribArray(self.__colorLocation)
        glVertexAttribPointer(self.__colorLocation,    4, GL_FLOAT, GL_FALSE, 0, None)

        ### unbind vao and vbo
        glBindBuffer(GL_ARRAY_BUFFER, 0)
        glBindVertexArray(0)
        """

    def paintGL(self):
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        ### this doesn't work
        # frameBufferA.bind()
        # frameBufferA.release()

        glViewport(0, 0, self.width(), self.height())

        orthoMatrix = QMatrix4x4()
        orthoMatrix.ortho(
            0 + self.__scrollOffset.x(),
            self.width() + self.__scrollOffset.x(),
            self.height() + self.__scrollOffset.y(),
            0 + self.__scrollOffset.y(),
            -100,
            100,
        )
        transformMatrix = QMatrix4x4()
        transformMatrix.setToIdentity()
        transformMatrix.scale(self.__zoomFactor)

        ### activate shader program
        # self.__shaderProgram.bind()
        ### set a shader attribute (0 means use texture, 1 means use color)
        # self.__shaderProgram.setUniformValue(self.__use_color_location, 0.0)

        ### feed the mpv matrix
        mpvMatrix = orthoMatrix * transformMatrix
        # self.__shaderProgram.setUniformValue(self.__mvpMatrixLocation, mpvMatrix)

        # Draw Something
        self.__myBufferPainter.paintGL(
            self.__scrollOffset.x(), self.__scrollOffset.y(), self.width(), self.height(), self.__zoomFactor, mpvMatrix
        )

        """
        ### DRAW SOMETHING
        ### bind texture
        glBindTexture(GL_TEXTURE_2D, self.__ori_tex)
        ### bind VAO
        glBindVertexArray(self.__VAO)
        ### draw triangle
        glDrawArrays(GL_TRIANGLES, 0, 18)
        """

        ### unbind
        # glBindVertexArray(0)
        # glUseProgram(0)
        # self.__shaderProgram.release()

    def SetSomething(self):
        pass

    def DrawSomething(self):
        pass

    def ZoomIn(self):
        self.__zoomFactor += 0.1

    def ZoomOut(self):
        self.__zoomFactor -= 0.1
        if self.__zoomFactor < 0.1:
            self.__zoomFactor = 0.1

    """
    Get / Set
    """

    def GetImageSize(self):
        """
        Get the size of the canvas / image
        """
        return QSize(self.__image_width, self.__image_height)

    def SetZoomFactor(self, val):
        """
        Set the value of magnification
        """
        self.__zoomFactor = val

    def GetZoomFactor(self):
        """
        Obtain the value of the magnification
        """
        return self.__zoomFactor

    def SetMouseDown(self, val):
        """
        Set the value of mouse down
        """
        self.__isMouseDown = val

    def SetHorizontalScroll(self, val):
        """
        Set horizontal scroll value
        """
        self.__scrollOffset.setX(val)

    def SetVerticalScroll(self, val):
        """
        Set vertical scroll value
        """
        self.__scrollOffset.setY(val)
예제 #23
0
파일: mikiview.py 프로젝트: OSUser/mikidown
class MikiView(QWebView):

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

        self.settings().clearMemoryCaches()
        self.notePath = parent.settings.notePath
        self.settings().setUserStyleSheetUrl(
            QUrl('file://'+self.parent.settings.cssfile))
        print(QUrl('file://'+self.parent.settings.cssfile))
        self.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks)

        self.page().linkClicked.connect(self.linkClicked)
        self.page().linkHovered.connect(self.linkHovered)
        self.page().mainFrame(
        ).contentsSizeChanged.connect(self.contentsSizeChanged)

        self.scrollPosition = QPoint(0, 0)

    def linkClicked(self, qurl):
        '''three kinds of link:
            external uri: http/https
            page ref link:
            toc anchor link: #
        '''
        name = qurl.toString()
        http = re.compile('https?://')
        if http.match(name):                        # external uri
            QDesktopServices.openUrl(qurl)
            return

        self.load(qurl)
        name = name.replace('file://', '')
        name = name.replace(self.notePath, '').split('#')
        item = self.parent.notesTree.pageToItem(name[0])
        if not item or item == self.parent.notesTree.currentItem():
            return
        else:
            self.parent.notesTree.setCurrentItem(item)
            if len(name) > 1:
                link = "file://" + self.notePath + "/#" + name[1]
                self.load(QUrl(link))
            viewFrame = self.page().mainFrame()
            self.scrollPosition = viewFrame.scrollPosition()

    def linkHovered(self, link, title, textContent):
        '''show link in status bar
            ref link shown as: /parent/child/pageName
            toc link shown as: /parent/child/pageName#anchor (ToFix)
        '''
        # TODO: link to page by: /parent/child/pageName#anchor
        if link == '':                              # not hovered
            self.parent.statusBar.showMessage(self.parent.notesTree.currentPage())
        else:                                       # beautify link
            link = link.replace('file://', '')
            link = link.replace(self.notePath, '')
            self.parent.statusBar.showMessage(link)

    def contentsSizeChanged(self, newSize):
        '''scroll notesView while editing (adding new lines)
           Whithout this, every `updateView` will result in scroll to top.
        '''
        if self.scrollPosition == QPoint(0, 0):
            return
        viewFrame = self.page().mainFrame()
        newY = self.scrollPosition.y(
        ) + newSize.height() - self.contentsSize.height()
        self.scrollPosition.setY(newY)
        viewFrame.setScrollPosition(self.scrollPosition)

    def updateView(self):
        # url_notebook = 'file://' + os.path.join(self.notePath, '/')
        viewFrame = self.page().mainFrame()
        # Store scrollPosition before update notesView
        self.scrollPosition = viewFrame.scrollPosition()
        self.contentsSize = viewFrame.contentsSize()
        url_notebook = 'file://' + self.notePath + '/'
        self.setHtml(self.parent.notesEdit.toHtml(), QUrl(url_notebook))
        # Restore previous scrollPosition
        viewFrame.setScrollPosition(self.scrollPosition)

    def updateLiveView(self):
        if self.parent.actions.get('split').isChecked():
            QTimer.singleShot(1000, self.updateView)
예제 #24
0
class ContainerWidget(QWidget):
    def __init__(self, container, parent: QWidget = None):
        QWidget.__init__(self, parent)
        self.setWindowTitle('Container')
        self.__b_widgets = []
        self.__container = container
        self.__translation = QPoint(0, 0)
        self.setMouseTracking(True)
        self.setFocusPolicy(Qt.ClickFocus)
        self.setFocus()
        for b in container.blocks:
            w = b.get_widget(self)
            self.__b_widgets.append(w)
        pal = QPalette(self.palette())
        pal.setColor(QPalette.Background, QColor(55, 50, 47))
        self.setAutoFillBackground(True)
        self.setPalette(pal)
        container.block_added.connect(self.add_block)
        container.block_removed.connect(self.remove_block)
        self.__moving = False
        self.__origin = QPoint()

    def paintEvent(self, e: QPaintEvent):
        if e.isAccepted() and e.accept():
            QWidget.paintEvent(self, e)
            p = QPainter(self)
            p.setRenderHint(QPainter.Antialiasing)
            for l in self.__container.lines:
                l.paint(p)

    def add_block(self, b):
        w = b.get_widget(self)
        self.__b_widgets.append(w)

    def __get_b_widget(self, b):
        for w in self.__b_widgets:
            if w.block() == b:
                return w
        return None

    def remove_block(self, b):
        w = self.__get_b_widget(b)
        if b is not None:
            self.__b_widgets.remove(b)
            w.deleteLater()

    def mousePressEvent(self, e: QMouseEvent):
        BlockManager.deselect_all()
        if e.button() == Qt.LeftButton:
            self.__moving = True
            self.__origin = e.pos()
            self.setCursor(Qt.DragMoveCursor)
        elif e.button() == Qt.RightButton:
            self.show_popup(e.pos())

    def mouseDoubleClickEvent(self, e: QMouseEvent):
        BlockManager.deselect_all()
        if e.button() == Qt.LeftButton:
            self.__moving = False
            self.__translation = QPoint()
            self.translate(0, 0)

    def show_popup(self, pos):
        print('here')

    def mouseMoveEvent(self, e: QMouseEvent):
        if self.__moving:
            dx = e.x() - self.__origin.x()
            dy = e.y() - self.__origin.y()
            self.__origin = e.pos()
            self.translate(dx, dy)

    def mouseReleaseEvent(self, e):
        self.__moving = False
        self.setCursor(Qt.ArrowCursor)

    def translate(self, dx, dy):
        p = QPoint(self.__translation.x() + dx, self.__translation.y() + dy)
        self.__translation = p
        for b in self.__b_widgets:
            b.translate(p)
        self.repaint()
예제 #25
0
class MapSwipeTool(QgsMapTool):
  def __init__(self, iface):
    canvas = iface.mapCanvas()
    super(MapSwipeTool, self).__init__( canvas )
    self.view = iface.layerTreeView()
    self.msgBar = iface.messageBar()
    self.swipe = SwipeMap( canvas )
    self.checkDirection =  self.hasSwipe = self.disabledSwipe = None
    self.firstPoint = QPoint()
    self.cursorV = QCursor( Qt.SplitVCursor )
    self.cursorH = QCursor( Qt.SplitHCursor )
  
  def activate(self):
    self.canvas().setCursor( QCursor( Qt.CrossCursor ) )

    self._connect()

    self.hasSwipe = False
    self.disabledSwipe = False
    
    self.setLayersSwipe( self.view.currentIndex() )

  def canvasPressEvent(self, e):
    if len(self.swipe.layers) == 0:
      msg = "Select active Layer or Group(with layers)  in legend."
      self.msgBar.clearWidgets()
      self.msgBar.pushMessage( "MapSwipeTool", msg, QgsMessageBar.WARNING, 4 )
      return
    
    self.hasSwipe = True
    self.firstPoint.setX( e.x() )
    self.firstPoint.setY( e.y() )
    self.checkDirection = True

  def canvasReleaseEvent(self, e):
    self.hasSwipe = False
    self.canvas().setCursor( QCursor( Qt.CrossCursor ) )
    
  def canvasMoveEvent(self, e):
    if self.hasSwipe:
      if self.checkDirection:
        dX = abs( e.x() - self.firstPoint.x() )
        dY = abs( e.y() - self.firstPoint.y() )
        isVertical = dX > dY
        self.swipe.setIsVertical( isVertical )
        self.checkDirection = False
        self.canvas().setCursor( self.cursorH if isVertical else self.cursorV )
        
      self.swipe.setLength( e.x(), e.y() )

  def _connect(self, isConnect = True):
    signal_slot = (
      { 'signal': self.canvas().mapCanvasRefreshed, 'slot': self.swipe.setMap },
      { 'signal': self.view.activated, 'slot': self.setLayersSwipe },
      { 'signal': QgsMapLayerRegistry.instance().removeAll, 'slot': self.disable }
    )
    if isConnect:
      for item in signal_slot:
        item['signal'].connect( item['slot'] )
    else:
      for item in signal_slot:
        item['signal'].disconnect( item['slot'] )

  @pyqtSlot( "QModelIndex" )
  def setLayersSwipe(self, index):
    if self.disabledSwipe:
      return

    ids = msg = None
    node = self.view.currentNode()
    if isinstance( node, QgsLayerTreeLayer ):
      layer = node.layer()
      ids = [ layer.id() ]
      msg = "Active layer is '%s'." % layer.name()
    else:
      group = self.view.currentGroupNode()
      if group.parent() is None: # Root
        return
      ids = group.findLayerIds()
      msg = "Active group is '%s'." % group.name()

    self.swipe.clear()
    self.swipe.setLayersId( ids )
    self.msgBar.clearWidgets()
    self.msgBar.pushMessage( "MapSwipeTool", msg, QgsMessageBar.INFO, 2 )
    self.swipe.setMap()

  @pyqtSlot()
  def disable(self):
    self.swipe.clear()
    self.hasSwipe = False
    self.disabledSwipe = True
  
  def deactivate(self):
      super( MapSwipeTool, self ).deactivate()
      self.deactivated.emit()
      self.swipe.clear()
      self._connect( False )
예제 #26
0
class OIBlock(QWidget):
    border_color = QColor(137, 117, 89)
    padding = 0.05
    radius = 0.08

    def __init__(self, block, parent):
        QWidget.__init__(self, parent)
        self.__nodes = []
        self.__block = block
        self._resizable = True
        self.__block.repaint.connect(self.repaint)
        self._bg_color = QColor(159, 160, 144, 255)
        self._fg_color = QColor(255, 255, 255)
        self.setGeometry(block.get_geometry(Info.dpi))
        self.__action = Action.NONE
        self.__status = Mode.EDIT_LOGIC
        self.__corner_path = None
        self.__origin = None
        self.__translation = QPoint()
        if self._resizable:
            self.__init_corner()
        self.__init_nodes()
        self.__init_listeners()
        self.setMouseTracking(True)

    def __init_nodes(self):
        y = .45
        x = .01
        for k in self.__block.inputs:
            i = self.__block.inputs[k]
            n = OINode(QPointF(x, y), Alignment.Left, i)
            self.__nodes.append(n)
            y += 0.05 + n.size
        x = self.width() / Info.dpi - .12
        y = 0.45
        for k in self.__block.outputs:
            o = self.__block.outputs[k]
            n = OINode(QPointF(x, y), Alignment.Right, o)
            self.__nodes.append(n)
            y += .05 + n.size

    def __init_listeners(self):
        self.__block.selected.connect(self.select)
        self.__block.settings['Width'].value_update.connect(
            self.geometry_update)
        self.__block.settings['Height'].value_update.connect(
            self.geometry_update)
        self.__block.settings['X'].value_update.connect(self.geometry_update)
        self.__block.settings['Y'].value_update.connect(self.geometry_update)

    def select(self, val: bool):
        if val:
            effect = QGraphicsDropShadowEffect()
            effect.setBlurRadius(20)
            effect.setXOffset(0)
            effect.setYOffset(0)
            effect.setColor(QColor(0, 0, 0, 180))
            self.setGraphicsEffect(effect)
            self.raise_()
        else:
            eff = self.graphicsEffect()
            del eff
            self.setGraphicsEffect(None)

    def geometry_update(self):
        r = self.__block.get_geometry(Info.dpi)
        r.translate(self.__translation)
        self.setGeometry(r)
        self.__update_nodes()

    def __update_nodes(self):
        x = self.width() / Info.dpi - .12
        for n in self.__nodes:
            if n.alignment == Alignment.Right:
                y = n.pos.y()
                n.pos = QPointF(x, y)
        self.repaint()

    def selected(self):
        return self.__block.is_selected()

    def bg(self):
        return self._bg_color

    def title_bg(self):
        return self._bg_color.light(80)

    def block(self):
        return self.__block

    def _paint(self, p: QPainter):
        self._paint_bg(p)
        self._paint_title(p)
        p.setPen(QPen(self.pen().brush(), 0.01 * Info.dpi))
        self._paint_nodes(p)
        # self._paint_outs(p)
        # self._paint_content(p)

    def pen(self):
        p = QPen(
            OIBlock.border_color.lighter().lighter()
            if self.selected() else OIBlock.border_color, .02 * Info.dpi)
        return p

    def _paint_bg(self, p: QPainter):
        dpi = Info.dpi
        pen = self.pen()
        p.setRenderHint(QPainter.Antialiasing, True)
        p.setPen(pen)
        p.setBrush(self.bg())
        p.drawRoundedRect(OIBlock.padding * dpi, OIBlock.padding * dpi,
                          self.width() - 2 * OIBlock.padding * dpi,
                          self.height() - 2 * OIBlock.padding * dpi,
                          OIBlock.radius * dpi, OIBlock.radius * dpi)
        p.setBrush(self.title_bg())
        p.drawRoundedRect(OIBlock.padding * dpi, OIBlock.padding * dpi,
                          self.width() - 2 * OIBlock.padding * dpi,
                          .35 * dpi + OIBlock.padding * dpi,
                          OIBlock.radius * dpi, OIBlock.radius * dpi)
        p.setBrush(self.bg())
        p.setPen(QColor(0, 0, 0, 0))
        p.drawRect(0.01 * dpi + OIBlock.padding * dpi,
                   0.35 * dpi + OIBlock.padding * dpi,
                   self.width() - 0.02 * dpi - 2 * OIBlock.padding * dpi,
                   0.10 * dpi)
        p.setPen(pen)
        if self._resizable:
            if self.__corner_path is None:
                self.__init_corner()
            p.setBrush(pen.brush())
            p.drawPath(
                self.__corner_path.translated(self.width(), self.height()))

    def _paint_title(self, p: QPainter):
        dpi = Info.dpi
        p.drawLine(OIBlock.padding * dpi, 0.35 * dpi + OIBlock.padding * dpi,
                   self.width() - (0.01 + OIBlock.padding) * dpi,
                   0.35 * dpi + OIBlock.padding * dpi)
        p.setPen(self._fg_color)
        f = p.font()
        f.setPointSize(10)
        f.setBold(True)
        p.setFont(f)
        p.drawText(
            QRectF((0.04 + OIBlock.padding) * dpi,
                   (OIBlock.padding + .01) * dpi,
                   self.width() - .12 * dpi, .25 * dpi),
            str(self.__block.name()))
        f.setBold(False)
        f.setPointSize(8)
        p.setPen(
            QColor(self._fg_color.red(), self._fg_color.green(),
                   self._fg_color.blue(), 100))
        p.setFont(f)
        p.drawText(
            QRectF((.04 + OIBlock.padding) * dpi,
                   (.17 + OIBlock.padding) * dpi,
                   self.width() - .12 * dpi, .15 * dpi),
            str(self.__block.type_name()))

    def __init_corner(self):
        path = QPainterPath()
        dpi = Info.dpi
        path.moveTo(-OIBlock.padding * 1.2 * dpi,
                    (-.15 - OIBlock.padding * 1.2) * dpi)
        path.lineTo((-.15 - OIBlock.padding * 1.2) * dpi,
                    -OIBlock.padding * 1.2 * dpi)
        path.lineTo(-OIBlock.padding * 1.2 * dpi, -OIBlock.padding * 1.2 * dpi)
        path.closeSubpath()
        self.__corner_path = path

    def _paint_nodes(self, p: QPainter):
        for n in self.__nodes:
            n.paint(p)
        return

    def _paint_content(self, p: QPainter):
        # nothing to do
        return

    def paintEvent(self, e: QPaintEvent):
        if e.isAccepted():
            p = QPainter(self)
            self._paint(p)

    def _check_corner(self, pos):
        path = self.__corner_path.translated(self.width(), self.height())
        return path.contains(pos)

    def _check_action(self, action):
        if self.__action != Action.NONE and action != Action.NONE:
            return False
        return True

    def _check_nodes(self, p: QPoint):
        for n in self.__nodes:
            if n.contains(p):
                return n
        return None

    def mousePressEvent(self, e: QMouseEvent):
        self.__block.select()
        n = self._check_nodes(e.pos())
        if n is not None:
            print('Node found')
            return
        if e.button() == Qt.LeftButton:
            if self._resizable:
                if self._check_corner(e.pos()) and self._check_action(
                        Action.RESIZE):
                    self.__origin = e.pos()
                    self.__action = Action.RESIZE
                    self.setCursor(Qt.SizeFDiagCursor)
                    return
            if self._check_action(Action.DRAG):
                self.__origin = e.pos()
                self.__action = Action.DRAG
                self.setCursor(Qt.DragMoveCursor)

    def mouseMoveEvent(self, e: QMouseEvent):
        if self.__action == Action.DRAG:
            dx = e.x() - self.__origin.x()
            dy = e.y() - self.__origin.y()
            self.set_pos(self.x() + dx, self.y() + dy)
        elif self.__action == Action.RESIZE:
            self.set_size(e.x(), e.y())
        else:
            if self._resizable and self.__corner_path.translated(
                    self.width(), self.height()).contains(e.pos()):
                self.setCursor(Qt.SizeFDiagCursor)
            else:
                self.setCursor(Qt.ArrowCursor)

    def mouseReleaseEvent(self, e: QMouseEvent):
        self.__action = Action.NONE
        self.setCursor(Qt.ArrowCursor)

    def set_size(self, w, h):
        w1 = w / Info.dpi
        h1 = h / Info.dpi
        W = self.__block.settings['Width'].value()
        H = self.__block.settings['Height'].value()
        if w1 < W.min:
            w1 = W.min
        elif w1 > W.max:
            w1 = W.max
        if h1 < H.min:
            h1 = H.min
        elif h1 > H.max:
            h1 = H.max

        self.__block.set_setting('Width', w1)
        self.__block.set_setting('Height', h1)

    def set_pos(self, x, y):
        x = x - self.__translation.x()
        y = y - self.__translation.y()
        self.__block.set_setting('X', x / Info.dpi)
        self.__block.set_setting('Y', y / Info.dpi)

    def translate(self, p):
        self.__translation = p
        self.geometry_update()
예제 #27
0
class Canvas3d(QtOpenGL.QGLWidget):
    MODE_EXPLORE = 0
    MODE_DRAW = 1
    MODE_SELECT = 2
    MODE_ERASE = 3
    MODE_OPERATION = 4

    DRAW_POINTS = 0
    DRAW_SEGMENTS = 1
    DRAW_POLYGONS = 2
    DRAW_POLYLINES = 3

    def __init__(self, parent=None):
        self.parent = parent
        QtOpenGL.QGLWidget.__init__(self, parent)

        self.shader_program = None  # QtOpenGL.QGLShaderProgram()

        self.camera = Camera(
        )  # initialize a camera object (initially located at the origin and facing (0, 0, -1)

        self.xy_grid = MyGrid()

        self.renderables3d = set(
        )  # this contains all the geometries on canvas

        self.selection_box = None  # this contains at most 1 selection box

        self.last_mouse_position = QPoint(
            0, 0)  # last position of the mouse in viewport-coordinates

        self.bounding_box = Box3D(the_min=Point3(-20, -20, -20),
                                  the_max=Point3(20, 20, 20))
        # the bounding_box of all the geometries in the canvas.
        # BUT is never smaller than the values set here! Because it is used to set the viewport in VIEW_2D mode

        self.mode = Canvas3d.MODE_EXPLORE  # by default in "scene exploration" mode
        self.draw_what = None  # when in MODE_DRAW, this contains an indication of what is being drawn, else None
        self.currently_drawn_geom = None  # this maintains a reference to a geometry being drawn, until the drawing is complete

        self.selected_geoms = set(
        )  # will contain geometries in the canvas selected via the select tool

        self.canvas_cube_proportion = None
        self.setMouseTracking(True)

    @pyqtSlot(bool)
    def set_mode_explore(self, toggled):
        if toggled:
            self.mode = Canvas3d.MODE_EXPLORE

    @pyqtSlot(bool)
    def set_mode_select(self, toggled):
        if toggled:
            self.mode = Canvas3d.MODE_SELECT

    @pyqtSlot(bool)
    def set_mode_erase(self, toggled):
        if toggled:
            self.mode = Canvas3d.MODE_ERASE

    @pyqtSlot(bool)
    def set_mode_operation(self, toggled):
        if toggled:
            self.mode = Canvas3d.MODE_OPERATION

    @pyqtSlot(bool)
    def set_mode_draw_points(self, toggled):
        if toggled:
            # print("MODE: DRAW_POINTS")
            self.mode = Canvas3d.MODE_DRAW
            self.draw_what = Canvas3d.DRAW_POINTS

    @pyqtSlot(bool)
    def set_mode_draw_segments(self, toggled):
        if toggled:
            self.mode = Canvas3d.MODE_DRAW
            self.draw_what = Canvas3d.DRAW_SEGMENTS

    @pyqtSlot(bool)
    def set_mode_draw_polygons(self, toggled):
        if toggled:
            self.mode = Canvas3d.MODE_DRAW
            self.draw_what = Canvas3d.DRAW_POLYGONS

    @pyqtSlot(bool)
    def set_mode_draw_polylines(self, toggled):
        if toggled:
            self.mode = Canvas3d.MODE_DRAW
            self.draw_what = Canvas3d.DRAW_POLYLINES

    @pyqtSlot(bool)
    def reset_view_2d(self, toggled):
        GL.glDisable(
            GL.GL_DEPTH_TEST
        )  # disables the depth test (used to display only "visible" faces)
        GL.glDisable(
            GL.GL_CULL_FACE
        )  # disables culling (improves performance as only "visible" faces are processed)

        self.xy_grid.hide()  # hide the grid
        self.camera.set_view_2d(
            toggled)  # reset the position of the camera for 2D View
        self.setMouseTracking(True)

        self.updateGL()  # update the rendered scene

    @pyqtSlot(bool)
    def reset_view_3d(self, toggled):
        GL.glEnable(
            GL.GL_DEPTH_TEST
        )  # enables the depth test (used to display only "visible" faces)
        GL.glEnable(
            GL.GL_CULL_FACE
        )  # enables culling (improves performance as only "visible" faces are processed)

        self.drawingEventEnd()  # if we were drawing something end the drawing

        self.xy_grid.show()  # un-hide the grid
        self.camera.set_view_3d(
            toggled)  # reset the position of the camera for 3D view
        self.window().update_status_bar("3D VIEW")
        self.setMouseTracking(False)
        self.updateGL()  # update the rendered scene

    @pyqtSlot()
    def reset_view(self):
        self.camera.reset_view()  # reset the view
        self.updateGL()  # update the rendered scene

    def mousePressEvent(self, event):
        # when we press a mouse button on the canvas the canvas get the keyboard focus
        self.setFocus()

        # if in drawing mode
        if self.mode == Canvas3d.MODE_DRAW:
            # drawing events are only accepted in 2D View
            if self.camera.view_mode == Camera.VIEW_2D:
                self.drawingEventAddVertex(event=event)

        # if we are in "selection" or "erase" mode
        elif self.mode == Canvas3d.MODE_SELECT or self.mode == Canvas3d.MODE_ERASE:
            # selection events are only accepted in 2D View
            if self.camera.view_mode == Camera.VIEW_2D:
                event_x, event_y, z = self.camera.canvas2world(
                    event.x(), event.y())

                self.selection_box = SelectionBox(Point3(event_x, event_y, 0))

        # update the rendered scene
        self.updateGL()

        self.last_mouse_position = event.pos()
        event.accept()

    def mouseReleaseEvent(self, event):
        # if in drawing mode
        if self.mode == Canvas3d.MODE_DRAW:
            # drawing events are only accepted in 2D View
            if self.camera.view_mode == Camera.VIEW_2D:
                self.drawingEventConfirmLastVertex(event=event)

        # if we are in "selection" mode
        elif self.mode == Canvas3d.MODE_SELECT:
            # selection events are only accepted in 2D View
            if self.camera.view_mode == Camera.VIEW_2D:
                # select geometries inside the box before deleting it
                self.selected_geoms = self.selection_box.select_geometries(
                    self.renderables3d)

                self.window().console_add_line("\nSELECTED SHAPES")
                # self.parent.parent.console_add_line("\nSELECTED SHAPES")
                for g in self.selected_geoms:
                    self.window().console_add_line(str(g))

                self.selection_box = None

        # if we are in "erase" mode
        elif self.mode == Canvas3d.MODE_ERASE:
            # erase events are only accepted in 2D View
            if self.camera.view_mode == Camera.VIEW_2D:
                # select geometries inside the box before deleting it
                selected_geoms = self.selection_box.select_geometries(
                    self.renderables3d)

                for g in selected_geoms:
                    self.remove_geometry(g)

                self.selection_box = None

        # update the rendered scene
        self.updateGL()

        self.last_mouse_position = event.pos()
        event.accept()

    def mouseMoveEvent(self, event):

        if self.camera.view_mode == Camera.VIEW_2D:
            x, y, z = self.camera.canvas2world(event.x(), event.y())
            self.window().update_status_bar("(x, y): ({:.3f}, {:.3f})".format(
                x, y))

        # if moving while pressing the left button
        if event.buttons() and event.buttons() == QtCore.Qt.LeftButton:
            # if in draw mode: continue drawing
            if self.mode == Canvas3d.MODE_DRAW:
                self.drawingEventMoveLastVertex(event)

            # if we are in "selection" or "erase" mode
            elif self.mode == Canvas3d.MODE_SELECT or self.mode == Canvas3d.MODE_ERASE:
                # selection events are only accepted in 2D View
                if self.camera.view_mode == Camera.VIEW_2D:
                    event_x, event_y, z = self.camera.canvas2world(
                        event.x(), event.y())
                    x, y, z = self.camera.canvas2world(
                        self.last_mouse_position.x(),
                        self.last_mouse_position.y())
                    delta_x, delta_y = event_x - x, event_y - y
                    self.selection_box.move_corner2(Point3(
                        delta_x, delta_y, 0))

            # if in exploration mode
            elif self.mode == Canvas3d.MODE_EXPLORE:
                # if no button is held down: pan
                if QtGui.QApplication.keyboardModifiers(
                ) == QtCore.Qt.NoModifier:
                    self.panEvent(event)

                # if in 3D View
                if self.camera.view_mode == Camera.VIEW_3D:
                    # if the ctrl (cmd on mac) button is held down: rotate
                    if QtGui.QApplication.keyboardModifiers(
                    ) == QtCore.Qt.ControlModifier:
                        self.rotateEvent(event)

        # update the rendered scene
        self.updateGL()

        self.last_mouse_position = event.pos()
        event.accept()

    def keyPressEvent(self, event):
        # if in drawing mode
        if self.mode == Canvas3d.MODE_DRAW:
            # if the escape key is pressed: cancel the current drawing
            if event.key() == QtCore.Qt.Key_Escape:
                # print("pressed Esc")
                self.drawingEventCancel()
            # if either enter or return key is pressed: end the current drawing
            elif event.key() in (QtCore.Qt.Key_Return, QtCore.Qt.Key_Enter):
                # print("pressed Enter")
                self.drawingEventEnd()
            elif event.key() == QtCore.Qt.Key_Backspace:
                self.drawingEventRemoveLastVertex()

        # update the rendered scene
        self.updateGL()

    def wheelEvent(self, event):
        # if scrolling vertically
        if event.orientation() == QtCore.Qt.Vertical:
            # if in exploration mode: zoom
            if self.mode == Canvas3d.MODE_EXPLORE:
                self.zoomEvent(event)

        # update the rendered scene
        self.updateGL()

        event.accept()

    def rotateEvent(self, event):
        delta_x = event.x() - self.last_mouse_position.x()
        # delta_y is computed the opposite way, because the canvas origin is at the up-left corner
        # with positive y-axis point downwards
        delta_y = self.last_mouse_position.y() - event.y()

        # ORBIT (i.e., rotate) the camera around the camera._target
        self.camera.orbit(delta_x, delta_y)

    def panEvent(self, event):
        delta_x = event.x() - self.last_mouse_position.x()
        # delta_y is computed the opposite way, because the canvas origin is at the up-left corner
        # with positive y-axis point downwards
        delta_y = self.last_mouse_position.y() - event.y()

        # PAN the scene by altering camera._target
        self.camera.pan(delta_x, delta_y)

    def zoomEvent(self, event):
        delta = event.delta()
        # if in 3D View mode, the zoom is obtained by changing the distance of the camera from the target
        if self.camera.view_mode == Camera.VIEW_3D:
            # MOVE the camera wrt its _target (change the distance to _target)
            self.camera.move_radial(delta)

        # else, the zoom is obtained by changing the size of the viewed area
        else:
            # ZOOM
            if delta < 0:
                self.camera.zoom(1.05)
            elif delta > 0:
                self.camera.zoom(0.95)

            x, y, z = self.camera.canvas2world(event.x(), event.y())
            self.window().update_status_bar("(x, y): ({:.3f}, {:.3f})".format(
                x, y))

    def drawingEventAddVertex(self, event):
        """if no geometry is being drawn, create one.
        add a vertex to the drawn geometry"""

        # only if in draw mode
        if self.mode == Canvas3d.MODE_DRAW:
            x, y, z = self.camera.canvas2world(event.x(), event.y())
            new_point = Point3(x, y, z)
            if self.draw_what == Canvas3d.DRAW_POINTS:
                self.currently_drawn_geom = new_point
            elif self.draw_what == Canvas3d.DRAW_SEGMENTS:
                if self.currently_drawn_geom is None:
                    self.currently_drawn_geom = Line()
                self.currently_drawn_geom.add_vertex(new_point)
            elif self.draw_what == Canvas3d.DRAW_POLYGONS:
                if self.currently_drawn_geom is None:
                    self.currently_drawn_geom = Polygon()
                self.currently_drawn_geom.add_vertex(new_point)
            elif self.draw_what == Canvas3d.DRAW_POLYLINES:
                if self.currently_drawn_geom is None:
                    self.currently_drawn_geom = LineString()
                self.currently_drawn_geom.add_vertex(new_point)

            if isinstance(self.currently_drawn_geom, Geometry):
                self.add_geometry(self.currently_drawn_geom)

    def drawingEventRemoveLastVertex(self):
        """if possible, remove the last vertex from the drawn geometry (depends on the type of geometry)"""

        # only if in draw mode
        if self.mode == Canvas3d.MODE_DRAW:
            # if a geom is being drawn
            if self.currently_drawn_geom is not None:
                # if the geometry has at least one vertex
                if len(self.currently_drawn_geom) > 0:
                    self.currently_drawn_geom.remove_vertex()

                # if the current geom has no vertices, cancel it
                if len(self.currently_drawn_geom) == 0:
                    self.drawingEventCancel()

    def drawingEventMoveLastVertex(self, event):
        """move the last drawn vertex of the currently drawn geometry"""

        # only if in draw mode
        if self.mode == Canvas3d.MODE_DRAW:
            if self.currently_drawn_geom is not None:
                x, y, z = self.camera.canvas2world(event.x(), event.y())
                if self.draw_what == Canvas3d.DRAW_POINTS:
                    self.currently_drawn_geom.set_coords(x, y, z)
                elif self.draw_what in (Canvas3d.DRAW_SEGMENTS,
                                        Canvas3d.DRAW_POLYGONS,
                                        Canvas3d.DRAW_POLYLINES):
                    self.currently_drawn_geom.update_vertex(Point3(x, y, z))

    def drawingEventConfirmLastVertex(self, event):
        """this functions does nothing,
        unless the drawn geometry can have at most a fixed number of vertices,
        in which case, end the drawing"""

        # only if in draw mode
        if self.mode == Canvas3d.MODE_DRAW:
            if self.currently_drawn_geom is not None:
                # points and segments have a limited number of vertices. When we reach this amount we end the drawing
                if isinstance(self.currently_drawn_geom, Point3) \
                   or (isinstance(self.currently_drawn_geom, Line) and len(self.currently_drawn_geom) == 2):
                    self.drawingEventEnd()

    def drawingEventCancel(self):
        """cancel the drawing event (including the removal of the geometry drawn so far from the canvas)"""

        # only if in draw mode and there is a geometry being drawn
        if self.mode == Canvas3d.MODE_DRAW and self.currently_drawn_geom is not None:
            self.remove_geometry(self.currently_drawn_geom)
            self.currently_drawn_geom = None

    def drawingEventEnd(self):
        """ends the drawing of the geometry and prepares the canvas for a new drawing"""

        # only if in draw mode and there is a geometry being drawn
        if self.mode == Canvas3d.MODE_DRAW and self.currently_drawn_geom is not None:
            # if the drawn geometry is valid
            if not self.currently_drawn_geom.is_valid():
                self.remove_geometry(self.currently_drawn_geom)
            self.currently_drawn_geom = None

    def prepare_shader_program(self, v_shader_path="", f_shader_path=""):

        v_shader_file = open(v_shader_path, 'r')
        vertex_shader_code = v_shader_file.read()
        v_shader_file.close()

        f_shader_file = open(f_shader_path, 'r')
        fragment_shader_code = f_shader_file.read()
        f_shader_file.close()

        if not self.shader_program:
            # print("The shader is None, initialize it.")
            self.shader_program = GL.glCreateProgram()
            if not self.shader_program:
                print("ERROR in shader PROGRAM creation")
                return

        # VERTEX SHADER
        # create a vertex shader
        vertex_shader = GL.glCreateShader(GL.GL_VERTEX_SHADER)
        # set shader source_vertex
        GL.glShaderSource(vertex_shader, vertex_shader_code)
        # compile shader
        GL.glCompileShader(vertex_shader)

        # FRAGMENT SHADER
        # create a fragment shader
        fragment_shader = GL.glCreateShader(GL.GL_FRAGMENT_SHADER)
        # set shader source_vertex
        GL.glShaderSource(fragment_shader, fragment_shader_code)
        # compile shader
        GL.glCompileShader(fragment_shader)

        # build and link the shader program given the vertex and the fragment shader
        GL.glAttachShader(self.shader_program, vertex_shader)
        GL.glAttachShader(self.shader_program, fragment_shader)
        GL.glLinkProgram(self.shader_program)

        # get rid of the shaders as 1. they have been compiled in the program, 2. we do not need them any longer
        GL.glDetachShader(self.shader_program, vertex_shader)
        GL.glDetachShader(self.shader_program, fragment_shader)

        # make the shader program we just compiled the default program to be run
        GL.glUseProgram(self.shader_program)

    def initializeGL(self):
        # set the background color (to white)
        self.qglClearColor(QtGui.QColor(255, 255, 255))

        GL.glDepthMask(GL.GL_TRUE)

        GL.glEnable(GL.GL_POINT_SMOOTH
                    )  # makes point smooth (looks approx like a sphere)
        GL.glPointSize(config_rendering_point_size)  # size of points

        GL.glEnable(GL.GL_LINE_SMOOTH)
        GL.glLineWidth(config_rendering_line_width)

        GL.glFrontFace(
            GL.GL_CCW
        )  # the "front" of a face is those for which vertices are seen in CCW order

        # FOR TRANSPARENCY?
        # GL.glAlphaFunc(GL.GL_GREATER, 0.1)
        # GL.glEnable(GL.GL_ALPHA_TEST)
        # FOR TRANSPARENCY?
        GL.glEnable(GL.GL_BLEND)
        GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA)

        # load and link the shader program
        self.prepare_shader_program('shaders/vertex_shader.glsl',
                                    'shaders/fragment_shader.glsl')

    def resizeGL(self, width, height):
        """This function is called automatically by QT when a resize event occurs.
        We need to resize the viewport accordingly"""
        # print("resizeGL")

        # resize the viewport
        GL.glViewport(0, 0, width, height)

        # adjust the view accordingly with the new size of the canvas
        self.camera.resize_view(width, height)

    def paintGL(self):
        # print("paintGL")
        GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT)

        # bind (i.e., pass) the up-to-date view matrix to the vertex shader
        loc = GL.glGetUniformLocation(self.shader_program, "u_view")
        GL.glUniformMatrix4fv(loc, 1, GL.GL_FALSE,
                              self.camera.get_view_matrix().data())

        # bind (i.e., pass) the up-to-date projection matrix to the vertex shader
        loc = GL.glGetUniformLocation(self.shader_program, "u_projection")
        GL.glUniformMatrix4fv(loc, 1, GL.GL_FALSE,
                              self.camera.get_projection_matrix().data())

        # if visible not hidden, render the xy grid (only visible in 3D mode)
        self.xy_grid.render(self.shader_program)

        # render all the geometries in the canvas
        for renderable in self.renderables3d:
            # print("Going to paint the renderable: " + str(cube.renderable_vertex_array['position']))
            renderable.render(self.shader_program)

        if self.selection_box is not None:
            self.selection_box.render(self.shader_program)

    def add_geometry(self, *geoms):
        """
        add a geometry to the canvas (namely to the list renderables)
        :param geom: the geometry to add
        :return: None
        """
        for geom in geoms:
            self.renderables3d.add(geom)
        self.updateGL()

    def remove_geometry(self, geom):
        """
        removes the given geometry from the canvas
        :param geom: the geometry to be removed
        :return: None
        """
        self.renderables3d.remove(geom)
        self.updateGL()
예제 #28
0
class ControllerPage(QWebPage):
    evaljsSignalSent = pyqtSignal(str)
    avaljsSignalSent = pyqtSignal(str)
    
    def __init__(self, parent,contentPage,args):
      super(ControllerPage, self).__init__(parent)
      self.phantom = parent
      self.contentPage = contentPage
      self.evaljsSignalSent.connect(self.onEval)
      self.avaljsSignalSent.connect(self.onAval)
      self.mainFrame().addToJavaScriptWindowObject('page', self)
      self.m_scrollPosition = QPoint()

      self.contentFrame = self.contentPage.mainFrame()

#
    #def shouldInterruptJavaScript(self):
    #    QApplication.processEvents(QEventLoop.AllEvents, 42)
    #    return False
#
    #def javaScriptAlert(self, originatingFrame, msg):
    #    self.parent().javaScriptAlertSent.emit(msg)
#
    def javaScriptConsoleMessage(self, message, lineNumber, sourceID):
      self.parent().javaScriptConsoleMessageSent.emit(message, lineNumber, sourceID)

    def onEval(self,data):
      a = unicode(data).split(" ",1)

      if ( len(a) != 2 ):
        self.phantom.error("EVAL format error len(a)=%d" % len(a))
      else:
        (eid,cmd) = a
        self.lastError = None
        javascript = "try { %s } catch(e) {page.setLastError(e);}" % cmd
        retVal = self.mainFrame().evaluateJavaScript(javascript).toPyObject()

        if self.lastError:
          self.phantom.errret(eid,self.lastError)
        else:
          self.phantom.ret(eid,retVal)

    def onAval(self,data):
      a = unicode(data).split(" ",1)

      if ( len(a) != 2 ):
        self.phantom.error("EVAL format error len(a)=%d" % len(a))
      else:
        (eid,cmd) = a
        self.lastError = None
        javascript = "try { var AVAL=function (eid){ %s };AVAL(%s); } catch(e) {page.setLastError(e);}" % (cmd,eid)
        retVal = self.mainFrame().evaluateJavaScript(javascript).toPyObject()
        if self.lastError:
          self.phantom.errret(eid,self.lastError)
        #else:
        #  self.phantom.ret(eid,retVal)

    
    @pyqtSlot(str, result='QVariant')
    def setLastError(self, code):
      self.lastError = code
      return None

    @pyqtSlot(str, result='QVariant')
    def render(self,fname):
      contentsSize = self.contentFrame.contentsSize()
      contentsSize -= QSize(self.m_scrollPosition.x(), self.m_scrollPosition.y())
      frameRect = QRect(QPoint(0, 0), contentsSize)
      #if not self.m_clipRect.isEmpty():
      #    frameRect = self.m_clipRect

      viewportSize = self.contentPage.viewportSize()
      self.contentPage.setViewportSize(contentsSize)

      image = QImage(frameRect.size(), QImage.Format_ARGB32)
      image.fill(qRgba(255, 255, 255, 0))

      painter = QPainter()

      # We use tiling approach to work-around Qt software rasterizer bug
      # when dealing with very large paint device.
      # See http://code.google.com/p/phantomjs/issues/detail?id=54.
      tileSize = 4096
      htiles = (image.width() + tileSize - 1) / tileSize
      vtiles = (image.height() + tileSize - 1) / tileSize
      for x in range(htiles):
          for y in range(vtiles):
              tileBuffer = QImage(tileSize, tileSize, QImage.Format_ARGB32)
              tileBuffer.fill(qRgba(255, 255, 255, 0))

              # Render the web page onto the small tile first
              painter.begin(tileBuffer)
              painter.setRenderHint(QPainter.Antialiasing, True)
              painter.setRenderHint(QPainter.TextAntialiasing, True)
              painter.setRenderHint(QPainter.SmoothPixmapTransform, True)
              painter.translate(-frameRect.left(), -frameRect.top())
              painter.translate(-x * tileSize, -y * tileSize)
              self.contentFrame.render(painter, QRegion(frameRect))
              painter.end()

              # Copy the tile to the main buffer
              painter.begin(image)
              painter.setCompositionMode(QPainter.CompositionMode_Source)
              painter.drawImage(x * tileSize, y * tileSize, tileBuffer)
              painter.end()

      self.contentPage.setViewportSize(viewportSize)

      image.save(fname)

      return True

    #@pyqtSlot(str, str,result='QVariant')

    @pyqtSlot(str,result='QVariant')
    def evaluateJavaScript(self, code):
      #args = []
      #for arg in arguments:
      #  arg = arg.toPyObject()
      #  tp = type(arg).__name__
      #  print arg,tp
      #  if tp == 'float':
      #    arg = unicode(arg)
      #  elif tp == "NoneType":
      #    arg = "null"
      #  elif tp == "QString":
      #    arg = unicode('"' + arg.replace("\"","\\\"") +'"')
      #  else:
      #    self.error("unkwnon type %s" % tp)
      #    self.lastError = "unkwnon type %s" % tp
      #    return
      #  args.append(arg)
      #
      #args = ",".join(args)

      function = '(%s)()' % ( code)
      
      self.phantom.debug("EVAL " + function)

      ret = self.contentPage.mainFrame().evaluateJavaScript(function)
      return ret

    @pyqtSlot()
    def stop(self):
      self.contentPage.triggerAction(QWebPage.Stop)
    @pyqtSlot(str, 'QVariant', 'QVariant')
    def sendEvent(self, type_, arg1, arg2):
      type_ = str(type_).lower()



      if type_ in ('mousedown', 'mouseup', 'mousemove'):
          if type(arg1).__name__ == "QVariant":
            arg1 = arg1.toInt()[0]
      
          if type(arg2).__name__ == "QVariant":
            arg2 = arg2.toInt()[0]

          eventType = QMouseEvent.Type(QEvent.None)
          button = Qt.MouseButton(Qt.LeftButton)
          buttons = Qt.MouseButtons(Qt.LeftButton)

          if type_ == 'mousedown':
              eventType = QEvent.MouseButtonPress
          elif type_ == 'mouseup':
              eventType = QEvent.MouseButtonRelease
          elif type_ == 'mousemove':
              eventType = QEvent.MouseMove
              button = buttons = Qt.NoButton

          assert eventType != QEvent.None

          event = QMouseEvent(eventType, QPoint(arg1, arg2), button, buttons, Qt.NoModifier)
          QApplication.postEvent(self.contentPage, event)
          QApplication.processEvents()

          return

      if type_ == 'click':
          if type(arg1).__name__ == "QVariant":
            arg1 = arg1.toInt()[0]
      
          if type(arg2).__name__ == "QVariant":
            arg2 = arg2.toInt()[0]
          self.sendEvent('mousedown', arg1, arg2)
          self.sendEvent('mouseup', arg1, arg2)
          return

      if type_ == 'keypress':
          if type(arg1).__name__ == "QVariant":
            arg1 = str(arg1.toPyObject())
      
          #if type(arg2).__name__ == "QVariant":
          #  arg2 = Qt.KeyboardModifiers(arg2.toInt()[0])

          for c in arg1:
            if c.islower():
              self.sendEvent('keydown', QVariant(c), QVariant(0))
              self.sendEvent('keyup', QVariant(c), QVariant(0))
            else:
              self.sendEvent('keydown', QVariant(c), QVariant(0x02000000))
              self.sendEvent('keyup', QVariant(c), QVariant(0x02000000))
          
          return

      if type_ in ('keydown', 'keyup' ):
        if type_ == "keydown":
          keyEventType = QKeyEvent.KeyPress
        else:
          keyEventType = QKeyEvent.KeyRelease
        
        if type(arg1).__name__ == "QVariant":
          text = QString(arg1.toString().at(0))
          key = text.at(0).toUpper().unicode()
        else:
          key = arg1
          text = arg1

        if type(arg2).__name__ == "QVariant":
          arg2 = Qt.KeyboardModifiers(arg2.toInt()[0])


        event = QKeyEvent(keyEventType, key, arg2,text)
        QApplication.postEvent(self.contentPage, event)
        QApplication.processEvents()






    @pyqtProperty('QVariantMap')
    def viewportSize(self):
        vps = self.contentPage.viewportSize()
        result = {
            'height': vps.height(),
            'width': vps.width()
        }
        return result

    @pyqtProperty('QVariantMap')
    def scrollPosition(self):
        scroll = self.m_scrollPosition
        result = {
            'left': scroll.x(),
            'top': scroll.y()
        }
        return result

    @scrollPosition.setter
    def scrollPosition(self, size):
        positions = {'left': 0, 'top': 0}
        for item in positions:
            try:
                positions[item] = int(size[item])
                if positions[item] < 0:
                    positions[item] = 0
            except (KeyError, ValueError):
                positions[item] = self.scrollPosition[item]
        self.m_scrollPosition = QPoint(positions['left'], positions['top'])
        self.m_mainFrame.setScrollPosition(self.m_scrollPosition)
예제 #29
0
class ThresholdingInterpreter( QObject ):
    # states
    FINAL             = 0
    DEFAULT_MODE      = 1 # normal navigation functionality
    THRESHOLDING_MODE = 2 # while pressing left mouse button allow thresholding
    NO_VALID_LAYER    = 3 # not a grayscale layer 
    
    @property
    def state( self ):
        return self._current_state

    def __init__( self, navigationController, layerStack, posModel ):
        QObject.__init__( self )
        self._navCtrl = navigationController
        self._navIntr = NavigationInterpreter( navigationController )
        self._layerStack = layerStack
        self._active_layer = None
        self._active_channel_idx = -1
        self._current_state = self.FINAL
        self._current_position = QPoint(0,0)
        # Setting default values, scaled on actual data later on 
        self._steps_mean = 10 
        self._steps_delta = self._steps_mean*2
        self._steps_scaling = 0.07
        self._range_max = 4096.0 # hardcoded, in the case drange is not set in the data file or in the dataSelectionDialogue
        self._range_min = -4096.0
        self._range = np.abs(self._range_max-self._range_min)
        self._channel_range = dict()
        self._posModel = posModel

    def start( self ):
        if self._current_state == self.FINAL:
            self._navIntr.start()
            self._current_state = self.DEFAULT_MODE
            self._init_layer()
        else:
            pass 
    
    def stop( self ):
        self._current_state = self.FINAL
        if self.valid_layer():
            self._active_layer.channelChanged.disconnect(self.channel_changed)
        self._navIntr.stop()            
        
    def eventFilter( self, watched, event ):
        etype = event.type()
        if self._current_state == self.DEFAULT_MODE:
            if etype == QEvent.MouseButtonPress \
                    and event.button() == Qt.LeftButton \
                    and event.modifiers() == Qt.NoModifier \
                    and self._navIntr.mousePositionValid(watched, event): 
                # TODO maybe remove, if we can find out which view is active
                self.set_active_layer()
                if self.valid_layer():
                    self._current_state = self.THRESHOLDING_MODE
                    self._current_position = watched.mapToGlobal( event.pos() )
                    return True
                else:
                    self._current_state = self.NO_VALID_LAYER
                return self._navIntr.eventFilter( watched, event )
            elif etype == QEvent.MouseButtonPress \
                    and event.button() == Qt.RightButton \
                    and event.modifiers() == Qt.NoModifier \
                    and self._navIntr.mousePositionValid(watched, event):
                self.set_active_layer()
                if self.valid_layer():
                    self.onRightClick_resetThreshold(watched, event)
                else:
                    pass # do nothing
                return True
            else:
                return self._navIntr.eventFilter( watched, event )
        elif self._current_state == self.NO_VALID_LAYER:
            self.set_active_layer()
            if self.valid_layer():
                self._current_state = self.DEFAULT_MODE
            return self._navIntr.eventFilter( watched, event )
        elif self._current_state == self.THRESHOLDING_MODE:
            if self._active_layer == None: # No active layer set, should not go here
                return self._navIntr.eventFilter( watched, event )
            if etype == QEvent.MouseButtonRelease and event.button() == Qt.LeftButton:
                self._current_state = self.DEFAULT_MODE
                self._active_layer = None
                self.onExit_threshold( watched, event )
                return True
            elif etype == QEvent.MouseMove and event.buttons() == Qt.LeftButton:
                self.onMouseMove_thresholding(watched, event)
                return True
            else:
                return self._navIntr.eventFilter( watched, event )
        else:
            # let the navigation interpreter handle common events
            return self._navIntr.eventFilter( watched, event )
    
    def onRightClick_resetThreshold(self, imageview, event):
        range = self.get_min_max_of_current_view(imageview)
        self._active_layer.set_normalize(0, (range[0],range[1]))
        self._channel_range[self._active_channel_idx] = (range[0],range[1])

    def set_active_layer(self):
        """
        determines the layer postion in the stack and the currently displayed
        channel. Needs to be called constantly, because the user can change the 
        position of the input layer within the stack
        """
        for idx, layer in enumerate(self._layerStack):
            if isinstance(layer, GrayscaleLayer):
                if layer.window_leveling:
                    self._active_layer = layer
                    self._active_channel_idx= layer._channel
                    return
        self._active_layer = None

    def _init_layer(self):
        self.set_active_layer()
        if self.valid_layer():
            self._active_layer.channelChanged.connect(self.channel_changed)
            if self.get_drange() != None:
                self._range_min, self._range_max = self.get_drange()
        
    def onExit_threshold( self, watched, event ):
        pass

    def get_drange(self):
        """ 
        returns tuple of drange (min, max) as set in hdf5 file or None 
        if nothing is specified
        """
        return self._active_layer._datasources[0]._rawSource._op5.Output.meta.drange

    def valid_layer(self):
        if isinstance(self._active_layer, GrayscaleLayer):
            return self._active_layer.window_leveling
        else:
            return False

    def channel_changed(self):
        self.set_active_layer()
        if self._active_channel_idx in self._channel_range:
            self._active_layer.set_normalize(0, self._channel_range[self._active_channel_idx])
        else:
            self._active_layer.set_normalize(0,(self._range_min, 
                                                self._range_max))

    def get_min_max_of_current_view(self, imageview):
        """
        Function returns min and max value of the current view 
        based on the raw data.
        Ugly hack, but all we got for now
        """
        shape2D = posView2D( list(self._posModel.shape5D[1:4]), 
                             axis=self._posModel.activeView )
        data_x, data_y = 0, 0
        data_x2, data_y2 = shape2D[0], shape2D[1]
        
        if self._posModel.activeView == 0:
            x_pos = self._posModel.slicingPos5D[1]
            slicing = [slice(0, 1), 
                       slice(x_pos, x_pos+1), 
                       slice(data_x, data_x2), 
                       slice(data_y, data_y2), 
                       slice(self._active_channel_idx, self._active_channel_idx+1)]
        if self._posModel.activeView == 1:
            y_pos = self._posModel.slicingPos5D[2]
            slicing = [slice(0, 1), 
                       slice(data_x, data_x2), 
                       slice(y_pos, y_pos+1), 
                       slice(data_y, data_y2), 
                       slice(self._active_channel_idx, self._active_channel_idx+1)]
        if self._posModel.activeView == 2:
            z_pos = self._posModel.slicingPos5D[3]
            slicing = [slice(0, 1), 
                       slice(data_x, data_x2), 
                       slice(data_y, data_y2), 
                       slice(z_pos, z_pos+1), 
                       slice(self._active_channel_idx, self._active_channel_idx+1)]
        request = self._active_layer._datasources[0].request(slicing)
        result = request.wait()
        return result.min(), result.max()

    def onMouseMove_thresholding(self, imageview, event):
        if self._active_channel_idx not in self._channel_range:
            range = self.get_min_max_of_current_view(imageview)
            range_lower = range[0]
            range_upper = range[1]
        else:
            range = self._channel_range[self._active_channel_idx]
            range_lower = range[0]
            range_upper = range[1]
        # don't know what version is more efficient
        # range_delta = np.sqrt((range_upper - range_lower)**2) 
        range_delta = np.abs(range_upper - range_lower)
        range_mean = range_lower + range_delta/2.0

        self._steps_mean = range_delta * self._steps_scaling
        self._steps_delta = self._steps_mean * 2
        pos = imageview.mapToGlobal( event.pos() )
        dx =  pos.x() - self._current_position.x()
        dy =  self._current_position.y() - pos.y()

        if dx > 0.0:
            # move mean to right
            range_mean += self._steps_mean
        elif dx < 0.0:
            # move mean to left
            range_mean -= self._steps_mean
        
        if dy > 0.0:
            # increase delta
            range_delta += self._steps_delta
        elif dy < 0.0:
            # decrease delta
            range_delta -= self._steps_delta

        # check the bounds, ugly use min max values actually present
        if range_mean < self._range_min:
            range_mean = self._range_min
        elif range_mean > self._range_max:
            range_mean = self._range_max
        
        if range_delta < 1:
            range_delta = 1
        elif range_delta > self._range: 
            range_delta = self._range

        a = range_mean - range_delta/2.0
        b = range_mean + range_delta/2.0

        if a < self._range_min:
            a = self._range_min
        elif a > self._range_max:
            a = self._range_max
        
        if b < self._range_min:
            b = self._range_min
        elif b > self._range_max:
            b = self._range_max

        assert a <= b 

        # TODO test if in allowed range (i.e. max and min of data)
        self._active_layer.set_normalize(0, (a,b))
        self._channel_range[self._active_channel_idx] = (a,b)
        self._current_position = pos
예제 #30
0
    def calculateRoute(self):
        """ Calculates the route and stores all route points in internal list.
        
        If start and end points have not changed since last last calculation, the route wont be recalculated unless forceRouteRecalculation() was called before.
        If route was recalculated function returns True otherwise False.
        """
        if not self._recalculateRouteFlag and self._route != None and len(
                self._route) > 1:
            if self._route[0] == self.sourcePoint() and self._route[
                    len(self._route) - 1] == self.targetPoint():
                # Nothing has changed, so route not recalculated
                return False

        # Recaclucating route

        # Whenever the start directions point at each other, the connection has to go through the center of the points
        throughCenter = False
        rowKind = False
        columnKind = False

        sourceDirection = self.sourceDirection()
        targetDirection = self.targetDirection()

        if self._type == "ORTHOGONAL":
            if sourceDirection == self.ConnectionDirection.RIGHT and targetDirection == self.ConnectionDirection.LEFT:
                throughCenter = True
                rowKind = True
            elif sourceDirection == self.ConnectionDirection.LEFT and targetDirection == self.ConnectionDirection.RIGHT:
                throughCenter = True
                rowKind = True
            elif sourceDirection == self.ConnectionDirection.DOWN and targetDirection == self.ConnectionDirection.UP:
                throughCenter = True
                columnKind = True
            elif sourceDirection == self.ConnectionDirection.UP and targetDirection == self.ConnectionDirection.DOWN:
                throughCenter = True
                columnKind = True

        self._route = []

        sP = QPoint(self.sourcePoint())  # start
        eP = QPoint(self.targetPoint())  # end
        self._route.append(sP)

        if throughCenter:
            # ORTHOGONAL
            centerP = (sP + eP) * 0.5
            firstP = self.nextPointByDistance(
                self._route, self.CONNECTOR_LENGTH * self.zoomFactor(),
                sourceDirection)
            lastP = self.getPointByDistance(
                eP, self.CONNECTOR_LENGTH * self.zoomFactor(), targetDirection)
            self._route.append(firstP)
            if rowKind:
                #if lastP.x() - firstP.x() > self.CONNECTOR_LENGTH * self.zoomFactor() * 0.5:
                if eP.x() - sP.x() > (self.CONNECTOR_LENGTH +
                                      1) * self.zoomFactor() * 2:
                    self._route.append(
                        self.nextPointByTarget(
                            self._route, centerP,
                            self.DrawOrientation.HORIZONTAL))
                    #self._route.append(centerP)
                    self._route.append(
                        self.nextPointByTarget(self._route, lastP,
                                               self.DrawOrientation.VERTICAL))
                else:
                    self._route.append(
                        self.nextPointByTarget(self._route, centerP,
                                               self.DrawOrientation.VERTICAL))
                    #self._route.append(centerP)
                    self._route.append(
                        self.nextPointByTarget(
                            self._route, lastP + QPoint(
                                -self.CONNECTOR_LENGTH * self.zoomFactor(), 0),
                            self.DrawOrientation.HORIZONTAL))
                    #self._route.append(self.nextPointByDistance(self._route, self.CONNECTOR_LENGTH * self.zoomFactor() , self.targetDirection()))
                    self._route.append(
                        self.nextPointByTarget(self._route, lastP,
                                               self.DrawOrientation.VERTICAL))

            elif columnKind:
                #print "    columnKind"
                route.append(
                    self.nextPointByTarget(self._route, centerP,
                                           self.DrawOrientation.VERTICAL))
                route.append(centerP)
                route.append(
                    self.nextPointByTarget(self._route, lastP,
                                           self.DrawOrientation.HORIZONTAL))
            else:
                logging.error(
                    "PointToPointConnection.calculateRoute() - Sorry connections going through the center have to be either rowKind or columKind."
                )

            self._route.append(lastP)
        else:
            # STRAIGHT or DIAGONAL
            if self._type == "DIAGONAL":
                width = abs(sP.x() - eP.x())
                height = abs(sP.y() - eP.y())
                if width > 0:
                    directionX = (sP.x() - eP.x()) / width
                else:
                    directionX = 0
                if height > 0:
                    directionY = (sP.y() - eP.y()) / height
                else:
                    directionY = 0
                if width > height:
                    diagonal = height / 2
                else:
                    diagonal = width / 2
                self._route.append(
                    QPoint(sP.x() - directionX * diagonal,
                           sP.y() - directionY * diagonal))
                self._route.append(
                    QPoint(sP.x() - directionX * (width - diagonal),
                           sP.y() - directionY * (height - diagonal)))

        self._route.append(eP)
        self._recalculateRouteFlag = False
        return True
예제 #31
0
class MSGLCanvas2D(QGLWidget):
    """
    Canvas GL plotting in 2 dimensions
    """

    MAX = 100.

    corner_ = 100.0
    zoom_ = 1.5
    xrot_ = 220
    yrot_ = 220
    trans_x_ = 0.0
    trans_y_ = 0.0

    def __init__(self, data, parent=None, **kw):
        """
        Constructor, initialization
        """

        QGLWidget.__init__(self, parent)
        self.setFormat(QGLFormat(QGL.SampleBuffers))
        self.setMinimumSize(500, 300)  #300
        self.setMouseTracking(True)
        self.setFocusPolicy(Qt.StrongFocus)

        self.data = data
        vertexes = []
        colors = []
        from utils.misc import IceAndFire
        maxY = max(map(max, [log10(el.y_data) for el in data]))
        maxX = max(map(max, [el.x_data for el in data]))
        rtmax = max([z.rtmin for z in data])
        for el in data:
            for i, x in enumerate(el.x_data):
                c = IceAndFire.getQColor(log10(el.y_data[i]) / maxY)
                colors.append(c)
                vertexes.append([(x * 2 * self.corner_) / maxX,
                                 (el.rt * 2 * self.corner_) / rtmax])
        from OpenGL.arrays.vbo import VBO

        self.vertexes = VBO(array(vertexes, 'f'))
        self.colors = VBO(array(colors, 'f'))

        self.mode = "None"  # "ZOOMING", "PANNING", "NONE"
        self.lastpos = QPoint()

        self.counter_trans_x = 0
        self.counter_trans_y = 0

        self.defaultColors = {
            'ticks': (0., 0., 0., 0.),
            'axes': (0., 0., 0., 0.),
            'curves': (0., 0., 1., 0.),
            'backgroundColor': (1., 1., 1., 1.)
        }

        #self.axes=self.drawAxes()
        self.transformationMatrix = self.setupTransformationMatrix(
            self.width(), self.height())

    def setupTransformationMatrix(self, w, h):
        """
        use a matrix to translate in the gl landmark
        """

        m = QMatrix()
        m.translate(-w / 2, h / 2)
        m.scale(300. / w, 300. / h)
        print w, h, w / 300., 1 - ((h / 300) - 1)
        #m.scale((self.width()*100)/300, -(self.height()*100)/300)
        #self.currentSize.x = w
        #self.currentSize.y = h
        return m

    def inGLCoordinate(self, point):
        return self.transformationMatrix.map(point)

    def resizeGL(self, w, h):
        """
        called when window is being resized
        """

        glViewport(0, 0, w, h)
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluOrtho2D(-self.corner_ * self.zoom_, self.corner_ * self.zoom_,
                   -self.corner_ * self.zoom_, self.corner_ * self.zoom_)

        #self.transformationMatrix = self.setupTransformationMatrix(w, h)

        glMatrixMode(GL_MODELVIEW)

    def initializeGL(self):
        """needed, initialize GL parameters"""

        #glClearColor(1.,1.,1.,1.)
        glDisable(GL_DEPTH_TEST)
        glEnable(GL_LINE_SMOOTH)
        glEnable(GL_POINT_SMOOTH)
        glHint(GL_LINE_SMOOTH_HINT, GL_NICEST)
        glLoadIdentity()  #model view by default

#        self.grid_lines = self.drawGridLines()
#        self.ticks =self.drawAxisTick()
#        self.axes = self.drawAxes()

    def paintGL(self):
        """Draw the scene, needed, called each time glDraw"""

        glClear(GL_COLOR_BUFFER_BIT)
        glTranslated(self.trans_x_, self.trans_y_, 0.)
        #addition
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluOrtho2D(-self.corner_ * self.zoom_, self.corner_ * self.zoom_,
                   -self.corner_ * self.zoom_, self.corner_ * self.zoom_)
        glMatrixMode(GL_MODELVIEW)
        #end addition
        #glCallList(self.grid_lines)
        #glCallList(self.ticks)
        #glCallList(self.axes)
        glLineWidth(30.0)
        self.scatterPlot()
#        if self.flags == "chrom":
#            self.drawAxisLegend("retention time[s]", "intensity[%]")
#            glCallList(self.lines)
#        elif self.flags == "spectrum":
#            self.drawAxisLegend("m/z", "intensity")

    def drawAxes(self, width=2., colour=(0., 0., 0.)):
        """
        Draw Axes 
        """
        #width must be a float
        axes = glGenLists(1)
        glNewList(axes, GL_COMPILE)
        glLineWidth(width)
        glColor(colour[0], colour[1], colour[2])
        glBegin(GL_LINES)
        #x_achse
        glVertex2d(-self.corner_, -self.corner_)
        glVertex2d(self.corner_, -self.corner_)
        #y-achse
        glVertex2d(-self.corner_, -self.corner_)
        glVertex2d(-self.corner_, self.corner_)
        glEnd()
        glEndList()
        return axes

    def drawLegends(self, pos):
        """
        draw legend at the specified position
        """
        pass

    def drawAxisLegend(self, x_label, y_label):
        """
        Draw Axis Legend
        """
        font = QFont("Typewriter")
        #RT axis legend
        font.setPixelSize(12)
        self.renderText(self.corner_, -self.corner_ - 20.0, 0.,
                        x_label)  # font
        self.renderText(-self.corner_ - 20.0, self.corner_, 0., y_label, font)

    def resetTranslations(self):
        """
        reset the different translation to 0
        """
        self.trans_x_ = 0.
        self.trans_y_ = 0.
        self.counter_trans_x = 0.
        self.counter_trans_y = 0.

    def normalizeAngle(self, angle):
        while (angle < 0):
            angle += 360 * 16
        while (angle > 360 * 16):
            angle -= 360 * 16


########DRAWING METHODS##################################################

    def drawLine(self, point_, point):
        glBegin(GL_LINES)
        glVertex2d(point_.x(), point_.y())
        glVertex2d(point.x(), point.y())
        glEnd()

    def drawRect(self, p_1, p_2, p_3=None, p_4=None):
        pass

    def drawOnePoint(self, point, colour=Qt.yellow):
        pass

    def scatterPlot(self):
        """ Draw Data (x, y)"""
        if self.vertexes is not None and self.colors is not None:
            self.vertexes.bind()
            glEnableClientState(GL_VERTEX_ARRAY)
            glVertexPointerf(self.vertexes)
            self.colors.bind()
            glEnableClientState(GL_COLOR_ARRAY)
            glColorPointerf(self.colors)
            glDrawArrays(GL_LINES, 0, len(self.vertexes))
            self.vertexes.unbind()
            self.colors.unbind()
            #self.textures.unbind()
            glDisableClientState(GL_VERTEX_ARRAY)
            glDisableClientState(GL_COLOR_ARRAY)

    def spectrumPlot(self, points):
        pass

    def histogramPlot(self, points, bin=5.):
        pass

    def barPlot(points, width=2.):
        pass

    ########MOUSE AND KEYBOARDS EVENTS###########################################################################

    def wheelEvent(self, event):
        if event.delta() > 0:
            self.zoom_ -= .05
        else:
            self.zoom_ += .05
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluOrtho2D(-self.corner_ * self.zoom_, self.corner_ * self.zoom_,
                   -self.corner_ * self.zoom_, self.corner_ * self.zoom_)
        self.updateGL()
        glMatrixMode(GL_MODELVIEW)
        event.accept()

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Plus:
            self.zoom_ -= .1
            glMatrixMode(GL_PROJECTION)
            glLoadIdentity()
            gluOrtho2D(-self.corner_ * self.zoom_, self.corner_ * self.zoom_,
                       -self.corner_ * self.zoom_, self.corner_ * self.zoom_)
            glMatrixMode(GL_MODELVIEW)

        if event.key() == Qt.Key_Minus:
            self.zoom_ += .1
            glMatrixMode(GL_PROJECTION)  #// You had GL_MODELVIEW
            glLoadIdentity()
            gluOrtho2D(-self.corner_ * self.zoom_, self.corner_ * self.zoom_,
                       -self.corner_ * self.zoom_, self.corner_ * self.zoom_)
            glMatrixMode(GL_MODELVIEW)

        if event.key() == Qt.Key_Up:
            self.trans_y_ += 2
            self.counter_trans_y += 2

        if event.key() == Qt.Key_Down:
            self.trans_y_ -= 2
            self.counter_trans_y -= 2

        if event.key() == Qt.Key_Left:
            self.trans_x_ -= 2
            self.counter_trans_x -= 2

        if event.key() == Qt.Key_Right:
            self.trans_x_ += 2
            self.counter_trans_x += 2

        if event.key() == Qt.Key_Z:
            self.mode = "ZOOMING"
            if self.counter_trans_x < 0 and self.counter_trans_y < 0:
                while self.counter_trans_x < 0 and self.counter_trans_y < 0:
                    self.trans_x_ = self.counter_trans_x
                    self.trans_y_ = self.counter_trans_y
                    self.updateGL()
                    self.counter_trans_x += 1
                    self.counter_trans_y += 1

            if self.counter_trans_x > 0 and self.counter_trans_y < 0:
                while self.counter_trans_x < 0 and self.counter_trans_y < 0:
                    self.trans_x_ = self.counter_trans_x
                    self.trans_y_ = self.counter_trans_y
                    self.updateGL()
                    self.counter_trans_x -= 1
                    self.counter_trans_y += 1

            if self.counter_trans_x < 0 and self.counter_trans_y > 0:
                while self.counter_trans_x < 0 and self.counter_trans_y < 0:
                    self.trans_x_ = self.counter_trans_x
                    self.trans_y_ = self.counter_trans_y
                    self.updateGL()
                    self.counter_trans_x += 1
                    self.counter_trans_y -= 1

            if self.counter_trans_x < 0 and self.counter_trans_y > 0:
                while self.counter_trans_x < 0 and self.counter_trans_y < 0:
                    self.trans_x_ = self.counter_trans_x
                    self.trans_y_ = self.counter_trans_y
                    self.updateGL()
                    self.counter_trans_x -= 1
                    self.counter_trans_y -= 1

            if self.zoom_ != 1.5:
                self.zoom = 1.5
                #self.updateGL()
        self.updateGL()
        self.resetTranslations()

    def mousePressEvent(self, event):
        if self.mode == "ZOOMING":
            self.mode = "None"
            self.computeSelection()
        else:
            self.lastpos = QPoint(event.pos())
            self.setCursor(QCursor(Qt.ClosedHandCursor))

        #if event.buttons() ==  Qt.RightButton:
        #    self.mode = "PANNING"

    def computeSelection(self):
        print "selected"

    def mouseMoveEvent(self, event):
        dx = event.x() - self.lastpos.x()
        dy = event.y() - self.lastpos.y()

        if self.mode == "ZOOMING":
            font = QFont("Typewriter")
            self.renderText(-self.corner_ - 30.0, self.corner_, 0.,
                            "ZOOMING MODE ACTIVATED", font)
            self.updateGL()
            glColor(0., 0., 1., .5)
            XMAX = 900.
            XMIN = 180.
            pointer_x = (self.lastpos.x() * 200.) / XMAX
            norm_dx = (dx * 200.) / XMAX
            """
            if pointer_x > 100. or pointer_x < 100. \
                or norm_dx >100. or norm_dx<-100.:
                event.ignore()
            """

            glBegin(GL_QUADS)
            glVertex2d(pointer_x, -100.)
            glVertex2d(pointer_x + norm_dx, -100.)
            glVertex2d(pointer_x + norm_dx, 100.)
            glVertex2d(pointer_x, 100.)
            glEnd()

            self.updateGL()  #update for seeing the rectangle

        mapping = self.mapFromGlobal
        cursorPos = self.inGLCoordinate(mapping(self.cursor().pos()))
        QToolTip.showText(self.cursor().pos(),
                          "x:"+str(cursorPos.x())+ \
                          ", y:"+str(cursorPos.y())
                          )

        if self.mode == "None":
            if event.buttons() == Qt.LeftButton:
                self.trans_y_ -= dy / 5
                self.counter_trans_y -= dy / 5
                self.trans_x_ += dx / 5
                self.counter_trans_x += dx / 5
            self.lastpos = QPoint(event.pos())
            self.glDraw()
            self.resetTranslations()

    def mouseReleaseEvent(self, event):
        self.setCursor(QCursor(Qt.ArrowCursor))
예제 #32
0
 def calculateRoute(self):
     """ Calculates the route and stores all route points in internal list.
     
     If start and end points have not changed since last last calculation, the route wont be recalculated unless forceRouteRecalculation() was called before.
     If route was recalculated function returns True otherwise False.
     """
     if not self._recalculateRouteFlag and self._route != None and len(self._route) > 1:
         if self._route[0] == self.sourcePoint() and self._route[len(self._route) - 1] == self.targetPoint():
             # Nothing has changed, so route not recalculated
             return False
     
     # Recaclucating route
     
     # Whenever the start directions point at each other, the connection has to go through the center of the points
     throughCenter = False
     rowKind = False
     columnKind = False
     
     sourceDirection = self.sourceDirection()
     targetDirection = self.targetDirection()
     
     if self._type == "ORTHOGONAL":
         if sourceDirection == self.ConnectionDirection.RIGHT and targetDirection == self.ConnectionDirection.LEFT:
             throughCenter = True
             rowKind = True
         elif sourceDirection == self.ConnectionDirection.LEFT and targetDirection == self.ConnectionDirection.RIGHT:
             throughCenter = True
             rowKind = True
         elif sourceDirection == self.ConnectionDirection.DOWN and targetDirection == self.ConnectionDirection.UP:
             throughCenter = True
             columnKind = True
         elif sourceDirection == self.ConnectionDirection.UP and targetDirection == self.ConnectionDirection.DOWN:
             throughCenter = True
             columnKind = True
     
     self._route = []
     
     sP = QPoint(self.sourcePoint())        # start
     eP = QPoint(self.targetPoint())          # end
     self._route.append(sP)
     
     
     if throughCenter:
         # ORTHOGONAL
         centerP = (sP + eP) * 0.5
         firstP = self.nextPointByDistance(self._route, self.CONNECTOR_LENGTH * self.zoomFactor(), sourceDirection)
         lastP = self.getPointByDistance(eP, self.CONNECTOR_LENGTH * self.zoomFactor() , targetDirection)
         self._route.append(firstP)
         if rowKind:
             #if lastP.x() - firstP.x() > self.CONNECTOR_LENGTH * self.zoomFactor() * 0.5:
             if eP.x() - sP.x() > (self.CONNECTOR_LENGTH +1) * self.zoomFactor() * 2:
                 self._route.append(self.nextPointByTarget(self._route, centerP, self.DrawOrientation.HORIZONTAL))
                 #self._route.append(centerP)
                 self._route.append(self.nextPointByTarget(self._route, lastP, self.DrawOrientation.VERTICAL))
             else:
                 self._route.append(self.nextPointByTarget(self._route, centerP, self.DrawOrientation.VERTICAL))
                 #self._route.append(centerP)
                 self._route.append(self.nextPointByTarget(self._route, lastP +QPoint(-self.CONNECTOR_LENGTH * self.zoomFactor(), 0), self.DrawOrientation.HORIZONTAL))
                 #self._route.append(self.nextPointByDistance(self._route, self.CONNECTOR_LENGTH * self.zoomFactor() , self.targetDirection()))
                 self._route.append(self.nextPointByTarget(self._route, lastP, self.DrawOrientation.VERTICAL))
                 
         elif columnKind:
             #print "    columnKind"
             route.append(self.nextPointByTarget(self._route, centerP, self.DrawOrientation.VERTICAL))
             route.append(centerP)
             route.append(self.nextPointByTarget(self._route, lastP, self.DrawOrientation.HORIZONTAL))
         else:
             logging.error("PointToPointConnection.calculateRoute() - Sorry connections going through the center have to be either rowKind or columKind.")
             
         self._route.append(lastP)
     else:
         # STRAIGHT or DIAGONAL
         if self._type == "DIAGONAL":
             width = abs(sP.x() - eP.x())
             height = abs(sP.y() - eP.y())
             if width > 0:
                 directionX = (sP.x() - eP.x()) / width
             else:
                 directionX = 0
             if height > 0:
                 directionY = (sP.y() - eP.y()) / height
             else:
                 directionY = 0
             if width > height:
                 diagonal = height / 2
             else:
                 diagonal = width / 2
             self._route.append(QPoint(sP.x() - directionX * diagonal, sP.y() - directionY * diagonal))
             self._route.append(QPoint(sP.x() - directionX * (width - diagonal), sP.y() - directionY * (height - diagonal)))
     
     self._route.append(eP) 
     self._recalculateRouteFlag = False
     return True
예제 #33
0
class OGLViewer (QGLWidget):
    '''
    OpenGL viewer class
    '''
    
    def __init__ (self, parent = None):
        '''
        Viewer's Constructor
        '''
        frmt = QGLFormat ()
        frmt.setSampleBuffers (True)
        
        super (OGLViewer, self).__init__ (frmt, parent)
        
        #self.setMouseTracking (True)
        self.__mouse = QCursor ()
        self.setCursor (Qt.OpenHandCursor)
        self.setFocusPolicy (Qt.ClickFocus)
        
        self.__Ctrl_or_Meta_key_pressed = False
        self.__Alt_key_pressed = False
        
        self.__w = 720
        self.__h = 450
        
        self._init_camera_vars ()
        self._init_objec_vars  ()
        
        # matrix changed signal. The signal's payload is the matrix itself.
        self.__GLMatrixChanged = SIGNAL ("MatrixChanged (PyQt_PyObject)")
        
        self.__compo_light_pos = QVector3D (.3,.2,.1)
        self.__AmbientMaterial = QVector3D ( .2, .2, .2)
    
    
    def _init_camera_vars (self):
        '''
        static method. It initializes the math variables.
        '''
        self.__compo_mtools = MathTools.Tools ()
        
        self.__curr_angles  = QPoint (0,0)
        self.__last_pos     = QPoint (0,0)
        self.__delta        = QPoint (0,0)
        self.__orig         = QVector3D (0.0, 0.0, 0.0)
        self.__cam_dist     = 0.0
        self.__z_near       = 0.1
        self.__z_far        = 2000.0
        self.__fovy         = 45.0
        self.__angle        = self.__compo_mtools.getAngle (self.__fovy)
        
        self.__norm_mtx     = QMatrix4x4 () #(GLdouble * 16)()
        self.__norm_mtx.setToIdentity ()
        
        self.__mtx          = QMatrix4x4 () #(GLdouble * 16)()
        self.__mtx.setToIdentity ()
        
        self.__aspect_ratio = float(self.__w)/float(self.__h)
        
        self.__camera_list  = []
    
    def _init_objec_vars (self):
        
        self.__arrows_list  = []
        self.__arrow_len    = 2.0
        
        self.__lines_list   = []
        self.__l_param      = 200.0
        
        self.__intersections_list = []
        
        self.__poly_model   = None
        self.__poly_list    = [] # by polygon I mean triangle.
    
    def initializeGL (self):
        '''
        usual OpenGL method
        '''
        glClearColor (0.93, 0.93, 0.93, 1.0)   
        glClearDepth (1.0)
        
        glMatrixMode (GL_PROJECTION)
        glLoadIdentity()
        gluPerspective (self.__fovy, float(self.__w)/float(self.__h), self.__z_near, self.__z_far)
        
        self.refreshMatrices ()
    
    def resizeGL (self, w, h):
        '''
        usual OpenGL method
        '''
        self.__w = w
        self.__h = h
        
        self.__aspect_ratio = float (self.__w)/float(self.__h)
        
        glMatrixMode (GL_MODELVIEW)
        glLoadIdentity ()
        gluPerspective (self.__fovy, self.__aspect_ratio, self.__z_near, self.__z_far)
        glViewport (0, 0, self.__w, self.__h)
        
        gluLookAt  (0, 0,-1,  # CameraPos
                    0, 0 ,0,  # CameraLookAt
                    0, 1 ,0)  # CameraUp
    
    def paintGL (self):
        '''
        usual OpenGL method
        '''
        self.__delta = QPoint (0,0)
        
        q = self.__mouse.pos()
        if self.__Ctrl_or_Meta_key_pressed ^ self.__Alt_key_pressed: #  xor (strictly one or the other)
            
            if self.__Ctrl_or_Meta_key_pressed:
                
                # rotation
                
                self.__delta = q - self.__last_pos
                
            else:
                
                # translation
                
                # transform mouse deltas and camera's local axes so that it'll look like as if the camera gets
                # translated based on the local axes x and y. What really happens is that the origin shifts along.
                # The resulting behaviour reminds of the Maya Camera Track Tool.
                d_x = q.x() - self.__last_pos.x()
                d_y = q.y() - self.__last_pos.y()
                
                zero = 0.0 #GLdouble (0.0)
                m_ref = self.__mtx.data () # retrieves the 16 items in this matrix and copies them to values in row-major order.
                vec_x = - m_ref[0]*d_x + m_ref[4]*d_y + zero*m_ref[8]
                vec_y = - m_ref[1]*d_x + m_ref[5]*d_y + zero*m_ref[9]
                vec_z = - m_ref[2]*d_x + m_ref[6]*d_y + zero*m_ref[10]
                
                mult = 0.03
                self.__orig.setX (self.__orig.x() + mult*vec_x)
                self.__orig.setY (self.__orig.y() + mult*vec_y)
                self.__orig.setZ (self.__orig.z() + mult*vec_z)
            
            # fire signal after done changing the model matrix.
            self.emit (self.__GLMatrixChanged, self.__mtx)
        
        self.__last_pos = q
        
        self.__curr_angles += self.__delta
        
        if glCheckFramebufferStatus (GL_FRAMEBUFFER) == 36053:  # 36053 = GL_FRAMEBUFFER_COMPLETE
            
            glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
            glLoadIdentity ()
            
            # Set the camera orientation :
            glMatrixMode (GL_MODELVIEW)
            glLoadIdentity ()
            
            gluLookAt (self.__orig.x(), self.__orig.y(), self.__orig.z() - 40,  # CameraPos
                       self.__orig.x(), self.__orig.y(), self.__orig.z(),       # CameraLookAt
                                   0.0,             1.0,             1.0)       # CameraUp
            
            # Rotate and move camera forward or backward.
            glTranslatef (0, 0, -self.__cam_dist)
            glTranslatef (self.__orig.x(), self.__orig.y(), self.__orig.z())    # rotation around current origin.
            glRotatef    (-30 - self.__curr_angles.y() * 0.15,  1, 0, 0)        # rotate around axis x.
            glRotatef    (-30 + self.__curr_angles.x() * 0.1,   0, 1, 0)        # rotate around axis y.
            glTranslatef (-self.__orig.x(), -self.__orig.y(), -self.__orig.z()) # rotation around current origin.
            
            self.refreshMatrices ()
            
            self.displayObjects ()
            self.displayArrows ()
            self.displayLines ()
            self.displayIntersections ()
            
            self.drawGrid ()
            self.drawFixedOriginAxes ()
            self.drawCurrentOriginAxes ()
            
            self.displayCamera ()
    
    def refreshMatrices (self):
        
        tmp        = glGetDoublev (GL_MODELVIEW_MATRIX) # this returns a list of lists BUT QMatrix4x4 accepts a list of floats.
        tmp_qmtx   = QMatrix4x4 ([item for sublist in tmp for item in sublist]) # flattens the list of lists out in a single list.
        
        self.__mtx = tmp_qmtx
        
        tmp_tuple  = tmp_qmtx.inverted ()
        self.__norm_mtx = (tmp_tuple[0]).transposed () # assumption : matrix always invertible so I'm not going to check the boolean tmp_tuple[1].
    
    def run (self):
        '''
        method refreshed cyclically by a timer when it is in focus.
        When out of focus, the timer stops calling it and so freezing
        the image to what it looked like when last used.
        '''
        self.paintGL () # render actual frame
        self.swapBuffers ()
    
    def addCamera (self):
        
        self.__compo_mtools.setNormalMatrix (self.__norm_mtx)
        
        angle_by_aspect_ratio = self.__angle * self.__aspect_ratio
        inv_w = 1.0/self.__w
        inv_h = 1.0/self.__h
        m = -1.0
        
        w_param = (inv_w-1) * angle_by_aspect_ratio
        h_param = (1-inv_h) * self.__angle
        
        # compute center + corners
        cam_centre   = self.__compo_mtools.cameraToWorldTransform (0, 0, 0)
        top_left     = self.__compo_mtools.cameraToWorldTransform ( w_param,  h_param, m)
        top_right    = self.__compo_mtools.cameraToWorldTransform ( w_param, -h_param, m)
        bottom_left  = self.__compo_mtools.cameraToWorldTransform (-w_param,  h_param, m)
        bottom_right = self.__compo_mtools.cameraToWorldTransform (-w_param, -h_param, m)
        
        self.__camera_list.append ([cam_centre, top_left, top_right, bottom_left, bottom_right])
    
    # - - -  viewer graphics  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    
    def displayCamera (self):
        
        glLineWidth (1.0)
        for cam in self.__camera_list:
            
            cc=cam[0];  tl=cam[1];  tr=cam[2];  bl=cam[3];  br=cam[4]
            
            glBegin (GL_LINES)
            glColor3f  (0.6, 0.6, 0.6)
            glVertex3f (cc[0],cc[1],cc[2]);   glVertex3f (tl[0],tl[1],tl[2])
            glVertex3f (cc[0],cc[1],cc[2]);   glVertex3f (tr[0],tr[1],tr[2])
            glVertex3f (cc[0],cc[1],cc[2]);   glVertex3f (br[0],br[1],br[2])
            glVertex3f (cc[0],cc[1],cc[2]);   glVertex3f (bl[0],bl[1],bl[2])
            glVertex3f (tl[0],tl[1],tl[2]);   glVertex3f (tr[0],tr[1],tr[2])
            glVertex3f (tr[0],tr[1],tr[2]);   glVertex3f (br[0],br[1],br[2])
            glVertex3f (br[0],br[1],br[2]);   glVertex3f (bl[0],bl[1],bl[2])
            glVertex3f (bl[0],bl[1],bl[2]);   glVertex3f (tl[0],tl[1],tl[2])
            glEnd ()
    
    def displayObjects (self):
        
        glClear (GL_COLOR_BUFFER_BIT)
        
        glEnable (GL_DEPTH_TEST)
        glDepthMask (GL_TRUE)
        #glEnable (GL_CULL_FACE)
        
        for poly in self.__poly_list:
            
            p0 = poly[0];  p1 = poly[1];  p2 = poly[2]
            
            glBegin (GL_TRIANGLES)
            col = .4 + 0.5*QVector3D.dotProduct (poly[3], self.__compo_light_pos)
            glColor3f   (col, col, col)
            glVertex3f (p0.x(), p0.y(), p0.z())
            glVertex3f (p1.x(), p1.y(), p1.z())
            glVertex3f (p2.x(), p2.y(), p2.z())
            glEnd ()
    
    def displayIntersections (self):
        
        for intsect in self.__intersections_list:
            
            p = intsect[0]
            c = intsect[1]
            # Draw a translated solid sphere
            glPushMatrix ()
            glTranslatef (p[0], p[1], p[2])
            glColor3f    (c[0], c[1], c[2])
            glutSolidSphere (GLdouble (0.03), 9, 9)
            glPopMatrix ()
    
    def displayLines (self):
        
        glLineWidth (1.0)
        for line in self.__lines_list:
            
            p = line[0]       # line initial position  (3-list)
            d = line[1]       # line direction (3-list)
            t = str(line[2])  # line type (o:open line, p:point-to-point line)
            
            glBegin (GL_LINES)
            glColor3ub (255, 255, 255)
            glVertex3f (p[0], p[1], p[2])
            
            # open line
            if   t=='o':
                glVertex3f (self.__l_param*d[0] + p[0],
                            self.__l_param*d[1] + p[1],
                            self.__l_param*d[2] + p[2])
            # point-to-point line
            elif t=='p':
                glVertex3f (d[0], d[1], d[2])
            
            else: raise sys.exit ('*** Unrecognised line type : "' + t + '"')
            
            glEnd ()
    
    def displayArrows (self):
        
        for arrow in self.__arrows_list:
            
            p = arrow[0]      # arrow position  (3-list)
            d = arrow[1]      # arrow direction (3-list)
            t = str(arrow[2]) # arrow type (i:inwards, o:outwards)
            
            # scale parameters
            scale_x = 0.01
            scale_y = scale_x
            scale_z = 0.5
            t_z     = scale_z * self.__arrow_len
            
            # arrow type
            if   t=='o': add_t = 0
            elif t=='i': add_t = -t_z*2.5
            else: raise sys.exit ('*** Unrecognised arrow type : "' + t + '"')
            
            glPushMatrix ()
            
            # arrow shaft
            glColor3f (0.5, 0.5, 0)
            glTranslatef (p[0], p[1], p[2])
            angles_from_orient = self.__compo_mtools.alignZAxisToVector (d[0], d[1], d[2])
            glRotatef (                  180,  0, 0, 1)
            glRotatef (angles_from_orient[1],  0, 1, 0)
            glRotatef (angles_from_orient[0],  1, 0, 0)
            glScale (scale_x, scale_y, scale_z)
            glTranslatef (0, 0, t_z+add_t)
            glutSolidCube (GLdouble(self.__arrow_len))
            
            # arrow head
            # REMEMBER ! The head's transformations are built on top of the arrow shaft's and are NOT independent !
            # The reason for doing that is that the user can change the scale of the arrow from UI's slider.
            glColor3f (0.6, 0.6, 0)
            glTranslatef (0, 0, t_z)
            glutSolidCone (GLdouble(t_z*5), GLdouble(t_z*0.5), GLint(6), GLint(2))
            
            glPopMatrix ()
    
    def drawGrid (self):
        
        glLineWidth (1.0)
        for i in range (-10, 11):
            glBegin (GL_LINES)
            glColor3ub (185, 185, 185)
            glVertex3f (-10, 0, i)
            glVertex3f (10, 0, i)
            glVertex3f (i, 0,-10)
            glVertex3f (i, 0, 10)
            glEnd ()
    
    def drawFixedOriginAxes (self):
        
        glLineWidth (2.0)
        glBegin (GL_LINES)
        glColor3ub (250, 0, 0); glVertex3f (0, 0, 0); glVertex3f (0, 0, 5)
        glColor3ub (255, 150, 150); glVertex3f (0, 0, 5); glVertex3f (0, 0, 10); glEnd ()
        glBegin (GL_LINES)
        glColor3ub (0, 250, 0); glVertex3f (0, 0, 0); glVertex3f (0, 5, 0)
        glColor3ub (150, 255, 150); glVertex3f (0, 5, 0); glVertex3f (0, 10, 0); glEnd ()
        glBegin (GL_LINES)
        glColor3ub (0, 0, 250); glVertex3f (0, 0, 0); glVertex3f (5, 0, 0)
        glColor3ub (150, 150, 255); glVertex3f (5, 0, 0); glVertex3f (10, 0, 0); glEnd ()
    
    def drawCurrentOriginAxes (self):
        
        glPointSize (6.0)
        glBegin (GL_POINTS)
        glColor3f (0.0,1.0,1.0)
        glVertex3f (self.__orig.x(), self.__orig.y(), self.__orig.z());   glEnd ()
        
        glBegin (GL_LINES); glColor3ub (250, 0, 0)
        glVertex3f (self.__orig.x(), self.__orig.y(), self.__orig.z())
        glVertex3f (self.__orig.x(), self.__orig.y(), self.__orig.z()+5); glEnd ()
        glBegin (GL_LINES); glColor3ub (0, 250, 0);
        glVertex3f (self.__orig.x(), self.__orig.y(), self.__orig.z())
        glVertex3f (self.__orig.x(), self.__orig.y()+5, self.__orig.z()); glEnd ()
        glBegin (GL_LINES); glColor3ub (0, 0, 250);
        glVertex3f (self.__orig.x(), self.__orig.y(), self.__orig.z())
        glVertex3f (self.__orig.x()+5, self.__orig.y(), self.__orig.z()); glEnd ()
    
    # - - -  listeners  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    
    def changeArrowsSize (self, new_size):
        if len(self.__arrows_list) > 0:
            self.__arrow_len = new_size
        
    def addArrow (self, pos, orient, arrow_type):
        self.__arrows_list.append ([pos, orient, arrow_type])
        
    def addLine (self, pos, orient_or_second_point, line_type):
        self.__lines_list.append ([pos, orient_or_second_point, line_type])
    
    def addIntersection (self, pos, icolor):
        self.__intersections_list.append ([pos, icolor])
    
    def keyPressEvent (self, e):
        if e.key() == Qt.Key_Control or e.key() == Qt.Key_Meta:  self.__Ctrl_or_Meta_key_pressed = True
        if e.key() == Qt.Key_Alt:  self.__Alt_key_pressed = True
    
    def keyReleaseEvent (self, e):
        if e.key() == Qt.Key_Control or e.key() == Qt.Key_Meta:  self.__Ctrl_or_Meta_key_pressed = False
        if e.key() == Qt.Key_Alt:  self.__Alt_key_pressed = False
    
    def wheelEvent (self, e):
        if self.__Ctrl_or_Meta_key_pressed:
            self.__cam_dist += e.delta() * 0.01
    
    # the three methods below are for regulate the OpenGL widget's FPS based on the focus received by the user.
    def setUi_Form      (self, uif): self.uiform = uif
    def focusInEvent    (self, e):   self.uiform.speedUpGLFrameRate ()
    def focusOutEvent   (self, e):   self.uiform.freezeGLFrameRate ()
    
    def getFovy         (self): return self.__fovy
    def getMatrix       (self): return self.__mtx
    def getNormalMatrix (self): return self.__norm_mtx
    
    def setModel        (self, model):
        self.__poly_model = model
        self.__poly_list  = model.getPolyListCopy ()
예제 #34
0
class CImprovedButton(QToolButton):
    def __init__(self, parent=None):
        QToolButton.__init__(self, parent)

        #TESTO ALTERNATIVO
        #Spesso se il pulsante ha icona troppo grossa e quando per ragioni di spazio o altro non si può spostare
        #o ridimensionare il pulsante stesso, la label ha posizioni assurde e schifose. Aggiungerne una "+ controllabile"
        #è l'unico modo..
        self.__fixed_label = QLabel("alternative label", self)
        self.__fixed_label.move(0, self.geometry().height() - 35)
        self.__fixed_label.resize(self.geometry().width(), self.__fixed_label.geometry().height())
        self.__fixed_label.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
        self.__font = QtGui.QFont("Arial", 10)
        self.__fixed_label.setFont(self.__font)
        self.__fixed_label.show()

        #INDICATORE STILE iOS
        self.__indicator = QLabel("0", self)
        self.__indicator.setStyleSheet("border-image: url(':/images/backgrounds/indicator.png'); padding-right:1px; color: white;")
        self.__indicator.geometry().setWidth(25)
        self.__indicator.geometry().setHeight(20)
        self.__indicator.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
        self.__indicator.setVisible(False)
        self.setIndicatorPos(QPoint(self.width() - self.__indicator.width(), 0)) #default top-right corner
        #Quando il pulsante viene ridimensionato (designer o meno) devo anche sistemare la label di conseguenza
        self.resizeEvent = self.__onResize
        self.__indicator.resizeEvent = self.__on_indicator_Resize

        self.setToolButtonStyle(QtCore.Qt.ToolButtonIconOnly)

        self.clicked.connect(self.stopAllAnimations)

        #BLINK
        self.__blink_timer = QTimer(parent)
        self.__blink_timer.timeout.connect(self.__on_blink_timer)
        self.__blink_timer_interval = 1000

        #FADING
        self.__opacity_effect = QGraphicsOpacityEffect()
        self.__fading_timer = QTimer(parent)
        self.__fading_timer.timeout.connect(self.__on_fading_timer)
        self.__FADE_TYPE = Enum("IN", "OUT")
        self.__fade_time = 20
        self.__opacity = 1.0
        self.__opacity_fading_coefficient = 0.02
        self.__selected_fade_type = self.__FADE_TYPE.IN

        # ANIMAZIONI GROW
        self.__animationGrow = QPropertyAnimation(self, "iconSize", self)
        self.__animationGrow.setDuration(1000)
        self.__animationGrow.setEasingCurve(QEasingCurve.Linear)
        self.__animationGrow.finished.connect(self.__on_growed)

        self.__animationShrink = QPropertyAnimation(self, "iconSize", self)
        self.__animationShrink.setDuration(1000)
        self.__animationShrink.setEasingCurve(QEasingCurve.Linear)
        self.__animationShrink.finished.connect(self.__on_shrinked)

        self.__defaultIconDimension = 60
        self.__iconGrowsBy = 40
        self.__growing = False

        # ANIMAZIONI BOUNCE
        self.__animationUp = QPropertyAnimation(self, "pos", self)
        self.__animationUp.setDuration(200)
        self.__animationUp.setEasingCurve(QEasingCurve.Linear)
        self.__animationUp.finished.connect(self.__on_top_reached)

        self.__animationBounce = QPropertyAnimation(self, "pos", self)
        self.__animationBounce.setDuration(1000)
        self.__animationBounce.setEasingCurve(QEasingCurve.OutBounce)
        self.__animationBounce.finished.connect(self.__on_bounce_finished)

        self.__bouncing = False
        self.__startPos = QPoint(self.pos().x(), self.pos().y())

        #PIXMAP & MASCHERA
        self.__pmap = QPixmap(self.size())
        self.__pmap_fname = ""
        self.__show_mask_preview = False

    def setDefaultIconSize(self, value):
        """ Sets default icon size when growing stops.
        @param value: size (both width and height)
        @type value: int
        """
        self.__defaultIconDimension = value

    def getDefaultIconSize(self):
        return self.__defaultIconDimension

    defaultIconSize = QtCore.pyqtProperty("int", getDefaultIconSize, setDefaultIconSize)

    def setFixetTextVisibility(self, bool):
        """ Sets if fixed text is visible or not.
        @param bool: visible or not
        @type bool: bool
        """
        self.__fixed_label.setVisible(bool)

    def getFixetTextVisibility(self):
        return self.__fixed_label.isVisible()

    fixetTextVisibility = QtCore.pyqtProperty("bool", fget=getFixetTextVisibility, fset=setFixetTextVisibility)

    def setFixedText(self, txt):
        """ Sets text on the button.
        @param txt: text
        @type txt: string
        """
        self.__fixed_label.setText(txt)

    def getFixedText(self):
        return self.__fixed_label.text()

    fixedText = QtCore.pyqtProperty("QString", getFixedText, setFixedText)

    def setFixedTextPos(self, qpoint):
        """ Sets text position in the button.
        @param qpoint: Position RELATIVE. 0,0 is top left corner of the button.
        @type qpoint: QPoint
        """
        self.__fixed_label.move(qpoint)

    def getFixedTextPos(self):
        return self.__fixed_label.pos()

    fixedTextPos = QtCore.pyqtProperty("QPoint", getFixedTextPos, setFixedTextPos)

    def setFixedTextFont(self, font):
        """ Sets text font.
        @param font: Font for fixed text.
        @type font: QFont
        """
        self.__font = font
        self.__fixed_label.setFont(self.__font)

    def getFixedTextFont(self):
        return self.__font

    fixedTextFont = QtCore.pyqtProperty("QFont", getFixedTextFont, setFixedTextFont)

    #FUNZIONI INDICATORE
    def setIndicatorVisibility(self, bool):
        """ Sets if indicator is visible or not.
        @param bool: visible or not
        @type bool: bool
        """
        self.__indicator.setVisible(bool)

    def getIndicatorVisibility(self):
        return self.__indicator.isVisible()

    indicatorVisibility = QtCore.pyqtProperty("bool", fget=getIndicatorVisibility, fset=setIndicatorVisibility)

    def setIndicatorPos(self, qpoint):
        """ Sets indicator position in the button.
        @param qpoint: Position RELATIVE. 0,0 is top left corner of the button.
        @type qpoint: QPoint
        """
        self.__indicator.move(qpoint)

    def getIndicatorPos(self):
        return self.__indicator.pos()

    indicatorPos = QtCore.pyqtProperty("QPoint", getIndicatorPos, setIndicatorPos)

    def setIndicatorSize(self, size):
        """ Sets indicator size.
        @param size: Size
        @type size: QSize
        """
        self.__indicator.resize(size)

    def getIndicatorSize(self):
        return self.__indicator.size()

    indicatorSize = QtCore.pyqtProperty("QSize", getIndicatorSize, setIndicatorSize)

    def setIndicatorFont(self, font):
        """ Sets indicator text font.
        @param font: Font for indicator text.
        @type font: QFont
        """
        self.__indicator.setFont(font)

    def getIndicatorFont(self):
        return self.__indicator.font()

    indicatorFont = QtCore.pyqtProperty("QFont", getIndicatorFont, setIndicatorFont)


    ## FUNZIONI PER BLINK
    def __on_blink_timer(self):
        self.setVisible(not (self.isVisible()))

    def setBlinking(self, blink):
        """ Sets if the button have to blink or not.
        @param blink: blinking or not
        @type blink: bool
        """
        if blink:
            self.__blink_timer.setInterval(self.__blink_timer_interval)
            self.__blink_timer.start()
        else:
            self.__blink_timer.stop()
            self.setVisible(True)

    def setBlinkInterval(self, value):
        """ Sets blink interval.
        @param blink: blink interval (msec)
        @type blink: int
        """
        self.__blink_timer_interval = value

    def getBlinkInterval(self):
        return self.__blink_timer_interval

    blinkInterval = QtCore.pyqtProperty("int", getBlinkInterval, setBlinkInterval)


    ##FUNZIONI PER FADING
    def fadeIn(self):
        """
         Button fades in from completely invisible to completely visible.
        """
        self.__opacity = 0.0
        self.__selected_fade_type = self.__FADE_TYPE.IN
        self.__fading_timer.start(self.__fade_time)

    def fadeOut(self):
        """
         Button fades out from completely visible to completely invisible.
        """
        self.__selected_fade_type = self.__FADE_TYPE.OUT
        self.__fading_timer.start(self.__fade_time)

    def setFadeTime(self, value):
        """ Sets fading time. Everytime interval is reached, alpha is increased (or decreased) by __opacity_fading_coefficient.
        @param value: fade time (msec)
        @type value: int
        """
        self.__fade_time = value

    def getFadeTime(self):
        return self.__fade_time

    fadeInterval = QtCore.pyqtProperty("int", getFadeTime, setFadeTime)

    def setFadeCoefficient(self, value):
        """ Sets fading coefficient. Alpha is increased (or decreased) by this value.
        @param value: coefficient (min 0.0 - max 1.0)
        @type value: float
        """
        self.__opacity_fading_coefficient = value

    def getFadeCoefficient(self):
        return self.__opacity_fading_coefficient

    fadeCoefficient = QtCore.pyqtProperty("double", getFadeCoefficient, setFadeCoefficient)

    def __on_fading_timer(self):
        if self.__selected_fade_type == self.__FADE_TYPE.OUT:
            if self.__opacity > 0:
                self.__opacity -= self.__opacity_fading_coefficient
                self.__opacity_effect.setOpacity(self.__opacity)
                self.setGraphicsEffect(self.__opacity_effect)
            else:
                self.__fading_timer.stop()

        if self.__selected_fade_type == self.__FADE_TYPE.IN:
            if self.__opacity <= 1.0:
                self.__opacity += self.__opacity_fading_coefficient
                self.__opacity_effect.setOpacity(self.__opacity)
                self.setGraphicsEffect(self.__opacity_effect)
            else:
                self.__fading_timer.stop()

    # FUNZIONI PER GROW\SHRINK
    def __on_growed(self):
        self.__animationShrink.setStartValue(QSize(self.iconSize().width(), self.iconSize().height()))
        self.__animationShrink.setEndValue(
            QSize(self.iconSize().width() - self.__iconGrowsBy, self.iconSize().height() - self.__iconGrowsBy))
        self.__animationShrink.start()

    def __on_shrinked(self):
        self.__animationGrow.setStartValue(QSize(self.iconSize().width(), self.iconSize().height()))
        self.__animationGrow.setEndValue(
            QSize(self.iconSize().width() + self.__iconGrowsBy, self.iconSize().height() + self.__iconGrowsBy))
        self.__animationGrow.start()

    def startGrow(self):
        """
         Button ICON starts to grow and shrink to standard value when maximum size (configured) is reached
        """
        if self.__growing:
            return
        self.__animationGrow.setStartValue(QSize(self.iconSize().width(), self.iconSize().height()))
        self.__animationGrow.setEndValue(
            QSize(self.iconSize().width() + self.__iconGrowsBy, self.iconSize().height() + self.__iconGrowsBy))
        self.__animationGrow.start()
        self.__growing = True

    def stopGrow(self):
        if self.__animationGrow.startValue().toSize() != QSize(0,
                                                               0) and self.__animationShrink.startValue().toSize() != QPoint(
                0, 0):
            self.__animationGrow.stop()
            self.__animationShrink.stop()
            self.setIconSize(QSize(self.__defaultIconDimension, self.__defaultIconDimension))
            self.__growing = False
            
    #FUNZIONI PER BOUNCE
    def startBounce(self):
        """
         Button starts to bounce requiring attention.
        """
        if self.__bouncing:
            return
        self.__startPos = QPoint(self.pos().x(), self.pos().y())
        self.__animationUp.setStartValue(QPoint(self.__startPos.x(), self.__startPos.y()))
        self.__animationUp.setEndValue(QPoint(self.__startPos.x(), self.__startPos.y() - self.geometry().height()))
        self.__animationUp.start()
        self.__bouncing = True
        
    def stopBounce(self):
        if self.__animationUp.startValue().toPoint() != QPoint(0,0) and self.__animationBounce.startValue().toPoint() != QPoint(0,0):
            self.__animationBounce.stop()
            self.__animationUp.stop()
            self.setGeometry(self.__startPos.x(), self.__startPos.y(), self.geometry().width(), self.geometry().height())
            self.__bouncing = False

    def __on_top_reached(self):
        self.__animationBounce.setStartValue(QPoint(self.pos().x(), self.pos().y()))
        self.__animationBounce.setEndValue(QPoint(self.__startPos.x(), self.__startPos.y()))
        self.__animationBounce.start()

    def __on_bounce_finished(self):
        self.__animationUp.start()

    def stopAllAnimations(self):
        self.stopBounce()
        self.stopGrow()

    #FUNZIONI PER PIXMAP & MASCHERA
    def setPixmapFile(self, image_file):
        self.__pmap = image_file
        self.__pmap.scaled(self.size())
        #NB: Il pixmap deve essere BIANCO e NERO. Con heuristicMask il primo pixel in alto a sinistra (0,0) viene
        #usato per decidere il colore trasparente, tutto il resto è visibile.

    def getPixmapFile(self):
        return self.__pmap

    pixmapFile = QtCore.pyqtProperty("QPixmap", getPixmapFile, setPixmapFile)

    def applyMask(self, bool):
        self.__show_mask_preview = bool
        if bool:
            self.setMask(QBitmap(self.__pmap.createHeuristicMask().scaled(self.size())))
        else:
            self.setMask(QBitmap())

    def getMask(self):
        return self.__show_mask_preview

    appliedMask = QtCore.pyqtProperty("bool", fget=getMask, fset=applyMask)

    def __onResize(self, event):
        self.__fixed_label.move(0, self.geometry().height() - 35)
        self.__fixed_label.resize(self.geometry().width(), self.__fixed_label.geometry().height())
        self.setIndicatorPos(QPoint(self.width() - self.__indicator.width(), 0))
        self.__pmap.scaled(self.size())
        if self.__show_mask_preview:
            self.setMask(QBitmap(self.__pmap.createHeuristicMask().scaled(self.size())))

    def __on_indicator_Resize(self, event):
        self.setIndicatorPos(QPoint(self.width() - self.__indicator.width(), 0))
예제 #35
0
class OIBlock(QWidget):
    border_color = QColor(137, 117, 89)
    padding = 0.05
    radius = 0.08

    def __init__(self, block, parent):
        QWidget.__init__(self, parent)
        self.__nodes = []
        self.__block = block
        self._resizable = True
        self.__block.repaint.connect(self.repaint)
        self._bg_color = QColor(159, 160, 144, 255)
        self._fg_color = QColor(255, 255, 255)
        self.setGeometry(block.get_geometry(Info.dpi))
        self.__action = Action.NONE
        self.__status = Mode.EDIT_LOGIC
        self.__corner_path = None
        self.__origin = None
        self.__translation = QPoint()
        if self._resizable:
            self.__init_corner()
        self.__init_nodes()
        self.__init_listeners()
        self.setMouseTracking(True)

    def __init_nodes(self):
        y = .45
        x = .01
        for k in self.__block.inputs:
            i = self.__block.inputs[k]
            n = OINode(QPointF(x, y), Alignment.Left, i)
            self.__nodes.append(n)
            y += 0.05 + n.size
        x = self.width() / Info.dpi - .12
        y = 0.45
        for k in self.__block.outputs:
            o = self.__block.outputs[k]
            n = OINode(QPointF(x, y), Alignment.Right, o)
            self.__nodes.append(n)
            y += .05 + n.size

    def __init_listeners(self):
        self.__block.selected.connect(self.select)
        self.__block.settings['Width'].value_update.connect(self.geometry_update)
        self.__block.settings['Height'].value_update.connect(self.geometry_update)
        self.__block.settings['X'].value_update.connect(self.geometry_update)
        self.__block.settings['Y'].value_update.connect(self.geometry_update)

    def select(self, val: bool):
        if val:
            effect = QGraphicsDropShadowEffect()
            effect.setBlurRadius(20)
            effect.setXOffset(0)
            effect.setYOffset(0)
            effect.setColor(QColor(0, 0, 0, 180))
            self.setGraphicsEffect(effect)
            self.raise_()
        else:
            eff = self.graphicsEffect()
            del eff
            self.setGraphicsEffect(None)

    def geometry_update(self):
        r = self.__block.get_geometry(Info.dpi)
        r.translate(self.__translation)
        self.setGeometry(r)
        self.__update_nodes()

    def __update_nodes(self):
        x = self.width() / Info.dpi - .12
        for n in self.__nodes:
            if n.alignment == Alignment.Right:
                y = n.pos.y()
                n.pos = QPointF(x, y)
        self.repaint()

    def selected(self):
        return self.__block.is_selected()

    def bg(self):
        return self._bg_color

    def title_bg(self):
        return self._bg_color.light(80)

    def block(self):
        return self.__block

    def _paint(self, p: QPainter):
        self._paint_bg(p)
        self._paint_title(p)
        p.setPen(QPen(self.pen().brush(), 0.01 * Info.dpi))
        self._paint_nodes(p)
        # self._paint_outs(p)
        # self._paint_content(p)

    def pen(self):
        p = QPen(OIBlock.border_color.lighter().lighter() if self.selected() else OIBlock.border_color, .02 * Info.dpi)
        return p

    def _paint_bg(self, p: QPainter):
        dpi = Info.dpi
        pen = self.pen()
        p.setRenderHint(QPainter.Antialiasing, True)
        p.setPen(pen)
        p.setBrush(self.bg())
        p.drawRoundedRect(OIBlock.padding * dpi, OIBlock.padding * dpi, self.width() - 2 * OIBlock.padding * dpi,
                          self.height() - 2 * OIBlock.padding * dpi, OIBlock.radius * dpi, OIBlock.radius * dpi)
        p.setBrush(self.title_bg())
        p.drawRoundedRect(OIBlock.padding * dpi, OIBlock.padding * dpi, self.width() - 2 * OIBlock.padding * dpi,
                          .35 * dpi + OIBlock.padding * dpi, OIBlock.radius * dpi,
                          OIBlock.radius * dpi)
        p.setBrush(self.bg())
        p.setPen(QColor(0, 0, 0, 0))
        p.drawRect(0.01 * dpi + OIBlock.padding * dpi, 0.35 * dpi + OIBlock.padding * dpi,
                   self.width() - 0.02 * dpi - 2 * OIBlock.padding * dpi, 0.10 * dpi)
        p.setPen(pen)
        if self._resizable:
            if self.__corner_path is None:
                self.__init_corner()
            p.setBrush(pen.brush())
            p.drawPath(self.__corner_path.translated(self.width(), self.height()))

    def _paint_title(self, p: QPainter):
        dpi = Info.dpi
        p.drawLine(OIBlock.padding * dpi, 0.35 * dpi + OIBlock.padding * dpi,
                   self.width() - (0.01 + OIBlock.padding) * dpi,
                   0.35 * dpi + OIBlock.padding * dpi)
        p.setPen(self._fg_color)
        f = p.font()
        f.setPointSize(10)
        f.setBold(True)
        p.setFont(f)
        p.drawText(
            QRectF((0.04 + OIBlock.padding) * dpi, (OIBlock.padding + .01) * dpi, self.width() - .12 * dpi, .25 * dpi),
            str(self.__block.name()))
        f.setBold(False)
        f.setPointSize(8)
        p.setPen(QColor(self._fg_color.red(), self._fg_color.green(), self._fg_color.blue(), 100))
        p.setFont(f)
        p.drawText(
            QRectF((.04 + OIBlock.padding) * dpi, (.17 + OIBlock.padding) * dpi, self.width() - .12 * dpi, .15 * dpi),
            str(self.__block.type_name()))

    def __init_corner(self):
        path = QPainterPath()
        dpi = Info.dpi
        path.moveTo(-OIBlock.padding * 1.2 * dpi, (-.15 - OIBlock.padding * 1.2) * dpi)
        path.lineTo((-.15 - OIBlock.padding * 1.2) * dpi, -OIBlock.padding * 1.2 * dpi)
        path.lineTo(-OIBlock.padding * 1.2 * dpi, -OIBlock.padding * 1.2 * dpi)
        path.closeSubpath()
        self.__corner_path = path

    def _paint_nodes(self, p: QPainter):
        for n in self.__nodes:
            n.paint(p)
        return

    def _paint_content(self, p: QPainter):
        # nothing to do
        return

    def paintEvent(self, e: QPaintEvent):
        if e.isAccepted():
            p = QPainter(self)
            self._paint(p)

    def _check_corner(self, pos):
        path = self.__corner_path.translated(self.width(), self.height())
        return path.contains(pos)

    def _check_action(self, action):
        if self.__action != Action.NONE and action != Action.NONE:
            return False
        return True

    def _check_nodes(self, p:QPoint):
        for n in self.__nodes:
            if n.contains(p):
                return n
        return None

    def mousePressEvent(self, e: QMouseEvent):
        self.__block.select()
        n = self._check_nodes(e.pos())
        if n is not None:
            print('Node found')
            return
        if e.button() == Qt.LeftButton:
            if self._resizable:
                if self._check_corner(e.pos()) and self._check_action(Action.RESIZE):
                    self.__origin = e.pos()
                    self.__action = Action.RESIZE
                    self.setCursor(Qt.SizeFDiagCursor)
                    return
            if self._check_action(Action.DRAG):
                self.__origin = e.pos()
                self.__action = Action.DRAG
                self.setCursor(Qt.DragMoveCursor)

    def mouseMoveEvent(self, e: QMouseEvent):
        if self.__action == Action.DRAG:
            dx = e.x() - self.__origin.x()
            dy = e.y() - self.__origin.y()
            self.set_pos(self.x() + dx, self.y() + dy)
        elif self.__action == Action.RESIZE:
            self.set_size(e.x(), e.y())
        else:
            if self._resizable and self.__corner_path.translated(self.width(), self.height()).contains(e.pos()):
                self.setCursor(Qt.SizeFDiagCursor)
            else:
                self.setCursor(Qt.ArrowCursor)

    def mouseReleaseEvent(self, e: QMouseEvent):
        self.__action = Action.NONE
        self.setCursor(Qt.ArrowCursor)

    def set_size(self, w, h):
        w1 = w / Info.dpi
        h1 = h / Info.dpi
        W = self.__block.settings['Width'].value()
        H = self.__block.settings['Height'].value()
        if w1 < W.min:
            w1 = W.min
        elif w1 > W.max:
            w1 = W.max
        if h1 < H.min:
            h1 = H.min
        elif h1 > H.max:
            h1 = H.max

        self.__block.set_setting('Width', w1)
        self.__block.set_setting('Height', h1)

    def set_pos(self, x, y):
        x = x - self.__translation.x()
        y = y - self.__translation.y()
        self.__block.set_setting('X', x / Info.dpi)
        self.__block.set_setting('Y', y / Info.dpi)

    def translate(self, p):
        self.__translation = p
        self.geometry_update()
예제 #36
0
class MSGLCanvas3D(QGLWidget):
    """Canvas GL plotting in 3 dimensions spectra"""

    corner = 100.0
    near = 0.0
    far = 600.0
    zoom = 1.5
    xrot = 220
    yrot = 220
    zrot = 0
    trans_x = 0.0
    trans_y = 0.0

    def __init__(
        self,
        vertexes,
        colors,
        parent=None,
        **kw
    ):  #vertexes, colors, texturePath='graphics/Texture-Example.jpg', parent=None):#spl, peak=None, parent=None):
        """
        Constructor, initialization
        kw:
            -texturePath:pathway to the file to text
            -textures: coord textures to apply
            -parent:the parent widget
        """
        QGLWidget.__init__(self, parent)
        self.setFormat(QGLFormat(QGL.SampleBuffers))
        self.setMinimumSize(500, 300)
        self.setMouseTracking(True)
        self.setFocusPolicy(Qt.StrongFocus)

        #        if not 'texturePath'in kw.keys() and not 'textures' in kw.keys():
        #            pass
        #            #print ('Could not apply texture, no coordinates')
        #        else:
        #            try:
        #                self._imageID = self.loadImage(kw.get('texturePath'))
        #                self.textures = textures
        #            except OSError:
        #                print ('Could not apply texture, no coordinates')

        self.vertexes = vertexes
        self.colors = colors

        #self.axes=None
        self.zoom_mode = False
        self.pan_mode = True
        #self.axes = self.makeAxes()

        self.parameters = {
            'axes_color': 'b',
            'axes_line_width': 3.,
            'draw_line_width': 1.,
            'colormap': True,
            'fish_eye': False,
            'cell_shading': False
        }
        self.lastpos = QPoint()

    def loadImage(self, imageName):
        im = open(imageName)
        try:
            ix, iy, image = im.size[0], im.size[1], im.tostring(
                "raw", "RGBA", 0, -1)
        except SystemError:
            ix, iy, image = im.size[0], im.size[1], im.tostring(
                "raw", "RGBX", 0, -1)
        ID = glGenTextures(1)
        glBindTexture(GL_TEXTURE_2D, ID)
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
        glTexImage2D(GL_TEXTURE_2D, 0, 3, ix, iy, 0, GL_RGBA, GL_UNSIGNED_BYTE,
                     image)
        return ID

    def setupTexture(self):
        glEnable(GL_TEXTURE_2D)
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL)
        glBindTexture(GL_TEXTURE_2D, self.imageID)

    def texturesCalc(self):
        from OpenGL.arrays.vbo import VBO
        basis = [[0., 0.], [0., 1.]]
        hola = []

        length = len(self.vertexes)
        for i in range(length / 2):
            hola += basis
        return VBO(array(hola))

    def recalcVertexesAndColors(self, colormap, **kwargs):
        pass

    def resizeGL(self, w, h):
        """called when window is being resized"""
        glViewport(0, 0, w, h)
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        glOrtho(-self.corner * self.zoom, self.corner * self.zoom,
                -self.corner * self.zoom, self.corner * self.zoom, self.near,
                self.far)
        #gluPerspective(70,w/h, 1,1000)
        glMatrixMode(GL_MODELVIEW)

    def initializeGL(self):
        """opengl options"""
        #glClearColor(1., 1., 1., 1.)
        #glClearColor(0.,0.,0.)
        glEnable(GL_DEPTH_TEST)
        #glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
        glEnable(GL_LINE_SMOOTH)
        #glEnable(GL_POINT_SMOOTH)
        #glHint (GL_LINE_SMOOTH_HINT, GL_NICEST)#
        #glDepthFunc(GL_LEQUAL)
        glEnable(GL_CULL_FACE)

        #glCullFace(GL_BACK)
        #glEnable(GL_LIGHTING)
        #glLightfv(GL_LIGHT0, GL_DIFFUSE,(0.8, 0.8, 0.8, 1))
        #glEnable(GL_LIGHT0)
        #glEnable(GL_COLOR_MATERIAL)
        #glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE)
        #self.shader = compileProgram(vertex_shader, frag_shader)#vertex_shader)#shader
        #self.drawAxisLegend()

    def paintGL(self):
        """needed, called each time glDraw"""
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        glLoadIdentity()
        glTranslated(0.0, 0.0, -3.0 * self.corner)
        glRotated(self.xrot / 16.0, 1.0, 0.0, 0.0)
        glRotated(self.yrot / 16.0, 0.0, 1.0, 0.0)
        glRotated(self.zrot / 16.0, 0.0, 0.0, 1.0)
        glTranslated(self.trans_x, self.trans_y, 3.0 * self.corner)
        #testing
        #glEnable(GL_DEPTH_TEST)
        #glEnable(GL_BLEND)
        #glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

        #self.setupTexture()
        #self.textures = self.texturesCalc()
        self.drawScene()
        #if self.zoom_mode:
        #    self.drawQuad()

    def renderTextModes(self):
        self.renderText(10,
                        10,
                        'mode:%s' % "zoom" if self.zoom_mode else 'mode:%s' %
                        "pan",
                        font=QFont())
        self.renderText(10, 20, 'selection mode:%s' % str(False), font=QFont())

    def drawScene(self):
        #
        self.renderTextModes()
        glLineWidth(1.)
        #glUseProgram(self.shader)
        if self.vertexes is not None and self.colors is not None:
            self.vertexes.bind()
            glEnableClientState(GL_VERTEX_ARRAY)
            glVertexPointerf(self.vertexes)
            self.colors.bind()
            glEnableClientState(GL_COLOR_ARRAY)
            glColorPointerf(self.colors)
            """        
            self.textures.bind()
            glEnableClientState(GL_TEXTURE_COORD_ARRAY)
            glTexCoordPointerf(self.textures)
            """
            glDrawArrays(GL_LINES, 0, len(self.vertexes))

            self.vertexes.unbind()
            self.colors.unbind()
            #self.textures.unbind()
            glDisableClientState(GL_VERTEX_ARRAY)
            glDisableClientState(GL_COLOR_ARRAY)
            #glDisableClientState(GL_TEXTURE_COORD_ARRAY)
            #glUseProgram(0)
        #glUseProgram(0)
        #if hasattr(self, 'axes'):
        #glCallList(self.axes)
        #glCallList(self.surface)
        #self.drawAxisLegend()

    def makeAxes(self):
        """Draw Axes """
        glLineWidth(2.0)
        glColor(0., 0., 1.)
        lspectr = glGenLists(1)
        glNewList(lspectr, GL_COMPILE)
        glBegin(GL_LINES)
        #glEnable(GL_LINE_STIPPLE)
        #glLineStipple(1, 1)
        glVertex3d(self.corner, -self.corner, -self.near - 2 * self.corner)
        glVertex3d(self.corner, self.corner, -self.near - 2 * self.corner)

        glVertex3d(self.corner, -self.corner, -self.far + 2 * self.corner)
        glVertex3d(self.corner, +self.corner, -self.far + 2 * self.corner)

        glVertex3d(-self.corner, -self.corner, -self.far + 2 * self.corner)
        glVertex3d(-self.corner, +self.corner, -self.far + 2 * self.corner)

        glVertex3d(-self.corner, +self.corner, -self.far + 2 * self.corner)
        glVertex3d(self.corner, +self.corner, -self.far + 2 * self.corner)

        glVertex3d(+self.corner, +self.corner, -self.far + 2 * self.corner)
        glVertex3d(+self.corner, +self.corner, -self.near - 2 * self.corner)
        #glDisable(GL_LINE_STIPPLE)

        glVertex3d(+self.corner, -self.corner, -self.far + 2 * self.corner)
        glVertex3d(+self.corner, -self.corner, -self.near - 2 * self.corner)

        glVertex3d(-self.corner, -self.corner, -self.far + 2 * self.corner)
        glVertex3d(self.corner, -self.corner, -self.far + 2 * self.corner)

        glEnd()
        glEndList()
        return lspectr

    def drawAxisLegend(self):
        """Draw Axis Legend"""

        font = QFont("Typewriter")
        font.setPixelSize(10)

        #RT axis legend
        font.setPixelSize(12)
        self.qglColor(Qt.blue)
        mz_label = "retention time [s]"
        rt_label = "m/z"
        self.renderText(0.0, -self.corner - 20.0,
                        -self.near - 2 * self.corner + 20.0, rt_label, font)
        self.renderText(-self.corner - 20.0, -self.corner - 20.0,
                        -self.near - 3 * self.corner, mz_label, font)
        self.renderText(-self.corner - 20.0, self.corner + 10.0,
                        -self.near - 2 * self.corner + 20.0, "intensity %",
                        font)
        font.setPixelSize(10)

#        #for rt number
#        for i in xrange (0,len(self.rtList), 100):
#            text = str(math.ceil(((self.rtList[i][0])*self.max_rt )/ self.max_rt))
#            self.renderText(-self.corner,
#                            -self.corner -5.0,
#                            -self.near-2*self.corner - self.rtList[i][0],
#                            text,
#                            font)

#        for i in xrange (0, len(self.massList[0]), 100):
#            text = str(math.ceil(((self.massList[0][i])*self.max_mass )/ 2*self.corner))
#            self.renderText( self.corner,
#                             self.corner -5.0,
#                            -self.near-2*self.corner - self.massList[0][i],
#                            text,
#                            font)
#        #for mz number

    def resetTranslations(self):
        """reset the different translation to 0"""

        self.trans_x = 0.
        self.trans_y = 0.

    def normalizeAngle(self, angle):
        """taken from qt documentation"""

        while (angle < 0):
            angle += 360 * 16
        while (angle > 360 * 16):
            angle -= 360 * 16
        return angle

    def computeSelection(self):
        pass

    #===============================================================================
    #              MOUSE AND KEYBOARDS EVENTS
    #===============================================================================
    def wheelEvent(self, event):
        if event.delta() > 0:
            self.zoom -= .05

        else:
            self.zoom += .05
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        glOrtho(-self.corner * self.zoom, self.corner * self.zoom,
                -self.corner * self.zoom, self.corner * self.zoom, self.near,
                self.far)
        glMatrixMode(GL_MODELVIEW)
        self.updateGL()
        event.accept()

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Minus:
            self.zoom -= .1
            glMatrixMode(GL_PROJECTION)
            glLoadIdentity()
            glOrtho(-self.corner * self.zoom, self.corner * self.zoom,
                    -self.corner * self.zoom, self.corner * self.zoom,
                    self.near, self.far)
            glMatrixMode(GL_MODELVIEW)

        if event.key() == Qt.Key_Plus:
            self.zoom += .1
            glMatrixMode(GL_PROJECTION)  #// You had GL_MODELVIEW
            glLoadIdentity()
            glOrtho(-self.corner * self.zoom, self.corner * self.zoom,
                    -self.corner * self.zoom, self.corner * self.zoom,
                    self.near, self.far)
            glMatrixMode(GL_MODELVIEW)

        if event.key() == Qt.Key_Z:
            #store all values
            self.zoom_mode = True

            glMatrixMode(GL_MODELVIEW)
            glLoadIdentity()
            font = QFont("Typewriter")
            self.renderText(0., 0., 0., "zooming mode", font)
            #little animation
            #a = -5
            #count = 0
            if self.yrot < 1444:
                while self.yrot < 1444:  #and self.xrot < ref_rotx_:
                    #count += 1
                    self.xrot -= 20
                    self.yrot += 20
                    #if self.zoom > a:
                    #    self.zoom-=1
                    self.updateGL()

            elif self.yrot > 1444:
                while self.yrot < 1444:  #and self.xrot < ref_rotx_:
                    #count += 1
                    self.xrot -= 20
                    self.yrot -= 20
                    #if self.zoom > a:
                    #    self.zoom-=1
                    self.updateGL()
            """
            count_ = 0
            tmp = self.xrot
            while  tmp < 1422:
                count_+=1
                tmp += 1
            b = count / count_
            count__ = 0
            """
            while self.xrot < 1422:
                #count__+=1
                self.xrot += 20
                #if self.zoom < 1: #and count__%b == 0:
                #    self.zoom+=1
                self.updateGL()

        if event.key() == Qt.Key_Up:
            self.trans_y += 10
        if event.key() == Qt.Key_Down:
            self.trans_y -= 10
        if event.key() == Qt.Key_Left:
            self.trans_x -= 10
        if event.key() == Qt.Key_Right:
            self.trans_x += 10

        self.updateGL()

    def mousePressEvent(self, event):
        self.lastpos = QPoint(event.pos())
#        modelview, projection =[], []
#        z =1
#        x, y =event.x(), event.y()
#        projection =glGetDoublev(GL_PROJECTION_MATRIX)
#        modelview= glGetDoublev(GL_MODELVIEW_MATRIX)
#        viewport=glGetIntegerv(GL_VIEWPORT)
#        glReadPixels( x, viewport[3]-y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, z )
#        objx, objy, objz =gluUnProject( x, viewport[3]-y, z, modelview, projection, viewport)
#        print objx, objy, objz

    def mouseMoveEvent(self, event):

        dx = event.x() - self.lastpos.x()
        dy = event.y() - self.lastpos.y()

        if not self.zoom_mode:
            if event.buttons() == Qt.LeftButton:
                a = self.normalizeAngle(self.xrot + 8 * dy)
                b = self.normalizeAngle(self.yrot + 8 * dx)
                self.xrot = a  #self.xrot + 8 * dy
                self.yrot = b  #self.yrot + 8 * dx

            if event.buttons() == Qt.RightButton:
                self.setCursor(QCursor(Qt.ClosedHandCursor))
                self.trans_y -= dy / 5
                self.trans_x += dx / 5

            self.lastpos = QPoint(event.pos())
            self.updateGL()

    def drawQuad(self):
        '''change to accept arguments pass'''
        glColor(0., 0., 1.)
        glLineWidth(4.0)
        pointer_x = self.lastpos.x() / 200.  #self.corner
        pointer_y = self.lastpos.y() / 200.  #/(self.corner)
        norm_dx = dx / 200.  #/(self.corner)
        norm_dy = dy / 200.  #/(self.corner)
        #print -self.corner, pointer_x, pointer_y, norm_dx, norm_dy
        glBegin(GL_QUADS)
        glVertex3f(-self.corner + pointer_x, -self.corner + pointer_y,
                   -self.near + 2 * self.corner)

        glVertex3f(-self.corner + pointer_x + norm_dx,
                   -self.corner + pointer_y, -self.near + 2 * self.corner)

        glVertex3f(-self.corner + pointer_x + norm_dx,
                   -self.corner + pointer_y + norm_dy,
                   -self.near + 2 * self.corner)

        glVertex3f(-self.corner + pointer_x, -self.corner + pointer_y,
                   -self.near + 2 * self.corner)
        glEnd()
        self.lastpos = QPoint(event.pos())
        #redraw eachtime mouse 's moving
        self.updateGL()

    def mouseReleaseEvent(self, event):
        self.setCursor(QCursor(Qt.ArrowCursor))
        if self.zoom_mode:
            self.computeSelection()
        self.zoom_mode = False

    def closeEvent(self, event):
        self.releaseKeyboard()
예제 #37
0
 def mouseMoveEvent(self, event):
     delta = QPoint(event.globalPos() - self.oldPos)
     #print(delta)
     self.move(self.x() + delta.x(), self.y() + delta.y())
     self.oldPos = event.globalPos()
예제 #38
0
class TwoDPlotWidget(pg.PlotWidget):
    """
    Widget to display a two dimensional graph
    based on elements with (x,y) coordinates.
    The widget allow to select a rectangular region of elements
    by their coordinates
    """
    def __init__(self, parent=None):
        pg.PlotWidget.__init__(self, parent)

        plot_item = self.getPlotItem()
        view_box = plot_item.getViewBox()
        view_box.mouseDragEvent = lambda ev, axis=0: False

        # variables for rectangular selection manipulation
        self.mousePressed = False
        self.lastPoint = QPoint(0, 0)
        self.oldX, self.oldY = 0, 0
        self.ElementSelectionRect = QtGui.QGraphicsRectItem(
            QtCore.QRectF(0, 0, 0, 0))
        self.ElementSelectionRect.setPen(
            QtGui.QPen(QtGui.QColor(255, 255, 255)))

    # region Mouse Events

    def mousePressEvent(self, ev):
        pg.PlotWidget.mousePressEvent(self, ev)
        if ev.button() == QtCore.Qt.LeftButton:
            self.mousePressed = True

            # get the local graph coordinate point from the pixel
            # where the cursor was pressed update last point
            self.lastPoint = self.getPlotItem().getViewBox().mapSceneToView(
                QtCore.QPointF(ev.x(), ev.y()))
            self.ElementSelectionRect.setRect(self.lastPoint.x(),
                                              self.lastPoint.y(), 0, 0)
            self.update()

    def mouseReleaseEvent(self, ev):
        """
        Widget response for a mouse release event.
        :param ev:
        """
        pg.PlotWidget.mouseReleaseEvent(self, ev)
        self.mousePressed = False

    def mouseMoveEvent(self, ev):
        pg.PlotWidget.mouseMoveEvent(self, ev)
        if self.mousePressed:
            # update (if necessary) the coordinates of the visual rectangle.
            self.__updateSelectionRect(ev)
            self.update()

    # endregion

    # region Axis Settings

    def setAxisLabel(self, axis_location="bottom", label="", **extra_args):
        """
        Set the label on the x or y axis
        :param axis_location: the location of the axis to set the label. (One of "bottom", "left")
        :param label: The label to set  (str)
        :param extra_args: dict with extra arguments to give to the axis item setLabel.
        :return:
        """
        if axis_location not in ["bottom", "left"]:
            raise ValueError("axis location must one of 'bottom' or 'left'")

        self.getPlotItem().getAxis(axis_location).setLabel(label, **extra_args)

    def setAxisFont(self, axis_location="bottom", font=None):
        """
        Set the font on the x or y axis
        :param axis_location: the location of the axis to set the label. (One of "bottom", "left")
        :param font: The font to set  (QFont)
        :return:
        """
        if axis_location not in ["bottom", "left"]:
            raise ValueError("axis location must one of 'bottom' or 'left'")

        if font is not None:
            self.getPlotItem().getAxis(axis_location).setTickFont(font)

    def showGrid(self, x=True, y=True):
        """
        Set the visibility of grid on the widget
        :param x: The x grid visibility
        :param y: The y grid visibility
        :return:
        """
        self.getPlotItem().showGrid(x=x, y=y)

    # endregion

    # region Selection Rectangle

    def removeSelectionRect(self):
        """
        Removes (if exist) the visual rectangle of the widget.
        """
        if self.ElementSelectionRect in self.items():
            self.removeItem(self.ElementSelectionRect)

    def addSelectionRect(self):
        """
        Adds a visual rectangle in the widget to select elements
        """
        if self.ElementSelectionRect not in self.items():
            self.addItem(self.ElementSelectionRect)

    def __updateSelectionRect(self, ev):
        """
        Update the selection rectangle figure with the information of a new gui
        event like mouse press
        :param ev: The event of the gui system
        """
        point = self.getPlotItem().getViewBox().mapSceneToView(
            QtCore.QPointF(ev.x(), ev.y()))
        x, y = point.x(), point.y()
        self.ElementSelectionRect.setRect(self.lastPoint.x(),
                                          self.lastPoint.y(),
                                          x - self.lastPoint.x(),
                                          y - self.lastPoint.y())

    # endregion

    def setRange(self, xRange=(0, 0), yRange=(0, 0)):
        """
        Set the visible range of the widget
        :return:
        """
        self.getPlotItem().setRange(xRange=xRange, yRange=yRange)
예제 #39
0
파일: EchoSet.py 프로젝트: yougukepp/radar
class EchoSet(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.mCenter = QPoint(0, 0)
        self.mRadius = 0
        self.mEchoLines = []
        self.mEchoLinesIndex = 0

        self.SetCenter(QPoint(0, 0))
        self.SetRadius(0)
        self.SetRange("50m")
        self.SetHdt(0)

        # 制作回波线角度表,用于提升性能
        step = 2.0 * gPI / gEchoLineCountAFrame
        self.mCosAngleTable = []
        self.mSinAngleTable = []
        for i in range(0, gEchoLineCountAFrame):
            self.mCosAngleTable.append(0)
            self.mSinAngleTable.append(0)
        for i in range(0, gEchoLineCountAFrame):
            angle = i * step - 90 * g1Deg
            self.mCosAngleTable[i] = math.cos(angle)
            self.mSinAngleTable[i] = math.sin(angle)

    def SetData(self, echoSetStrs):
        for echoStr in echoSetStrs:
            echoLine = EchoLine(echoStr)
            self.mEchoLines.append(echoLine)

    # 绘制时的圆心坐标
    def SetCenter(self, center):
        self.mCenter = center

    # 绘制半径
    def SetRadius(self, radius):
        self.mRadius = radius * gRadarEchoScale

    # 设置量程
    def SetRange(self, radarRange):
        assert radarRange in gRangeTable, "量程表中没有量程:" + radarRange
        self.mRangeName = radarRange
        self.mRange = gRangeTable[radarRange][0]
        self.mPrecision = gRangeTable[radarRange][1]

    # 设置船艏向
    def SetHdt(self, hdt):
        self.mHdt = 0

    # 绘制
    def Draw(self, p):
        self.__DrawAEchoLine(p, self.mEchoLinesIndex)
        self.__DrawShipHeadLine(p)
        self.__DrawDisCircle(p)
        self.__DrawRangeCicle(p)
        self.__DrawSysInfo(p)

        self.mEchoLinesIndex += 1
        indexMax = len(self.mEchoLines)
        if self.mEchoLinesIndex == indexMax:
            self.mEchoLinesIndex = 0

    # 绘制量程范围
    def __DrawRangeCicle(self, p):
        pen = QPen(QColor(0, 255, 0))
        p.setPen(pen)

    # 绘制距标圈
    def __DrawDisCircle(self, p):
        pen = QPen(QColor(0, 150, 0))
        p.setPen(pen)
        p.setBrush(Qt.NoBrush)

        r = self.mRadius
        rHalf = 0.5 * r
        rHalfOne = 1.5 * r
        self.__DrawCircle(p, self.mCenter, r)
        self.__DrawCircle(p, self.mCenter, rHalf)
        self.__DrawCircle(p, self.mCenter, rHalfOne)

    # 绘制船艏线
    def __DrawShipHeadLine(self, p):
        pen = QPen(QColor(255, 255, 255))
        p.setPen(pen)

        angle = self.mHdt - 90 * g1Deg

        xStart = int(self.mCenter.x())
        yStart = int(self.mCenter.y())
        xEnd = int(self.mRadius * math.cos(angle) + xStart)
        yEnd = int(self.mRadius * math.sin(angle) + yStart)

        p.drawLine(xStart, yStart, xEnd, yEnd)

        brush = QBrush(QColor(255, 255, 255), Qt.SolidPattern)
        p.setBrush(brush)

        angle = self.mHdt + 90 * g1Deg
        ang = angle - 30 * g1Deg
        cos_a = math.cos(ang)
        sin_a = math.sin(ang)
        x1 = xEnd + gShipLegendLen * cos_a
        y1 = yEnd - gShipLegendLen * sin_a

        ang = angle + 30 * g1Deg
        cos_a = math.cos(ang)
        sin_a = math.sin(ang)
        x2 = xEnd + gShipLegendLen * cos_a
        y2 = yEnd - gShipLegendLen * sin_a

        p1 = QPointF(xEnd, yEnd)
        p2 = QPointF(x1, y1)
        p3 = QPointF(x2, y2)
        p.drawPolygon(p1, p2, p3)

    # 绘制系统信息
    def __DrawSysInfo(self, p):
        pen = QPen(QColor(0, 255, 0))
        p.setPen(pen)
        p.drawText(2, 20, "量程:" + self.mRangeName)
        p.drawText(2, 40, "船艏:" + str(self.mHdt) + "度")

    # 绘制回波
    def __DrawAEchoLine(self, p, i):
        self.__DrawShadeLine(p, i)
        echoLinsCount = len(self.mEchoLines)
        if 0 == echoLinsCount:
            return
        assert i < echoLinsCount, "回波线索引越界"

        # TODO: 使用查表法 提速
        cosAngle = self.mCosAngleTable[i]
        sinAngle = self.mSinAngleTable[i]
        echoLine = self.mEchoLines[i]

        echoLine.Draw(p, self.mCenter, self.mRadius, cosAngle, sinAngle,
                      self.mRange, self.mPrecision)

    # 清除回波线上的上一帧数据
    def __DrawShadeLine(self, p, i):
        pen = QPen(QColor(0, 0, 0))

        angle = i / gEchoLineCountAFrame * 2 * gPI - 90 * g1Deg + g1Deg
        xStart = int(self.mCenter.x())
        yStart = int(self.mCenter.y())
        xEnd = int(self.mRadius * math.cos(angle) + xStart)
        yEnd = int(self.mRadius * math.sin(angle) + yStart)

        p.setPen(pen)
        p.drawLine(xStart, yStart, xEnd, yEnd)

    def __DrawCircle(self, p, center, r):
        x = center.x() - r
        y = center.y() - r

        width = 2 * r
        height = 2 * r

        p.drawEllipse(x, y, width, height)
예제 #40
0
class VispaWidgetOwner(object):
    """ Interface for classes containing VispaWidgets
    
    Only makes sense if implementing class also inherits QWidget or class inheriting QWidget.
    """
    
    def enableMultiSelect(self, multiSelect=True):
        self._multiSelectEnabledFlag = multiSelect
        
    def multiSelectEnabled(self):
        return hasattr(self, "_multiSelectEnabledFlag") and self._multiSelectEnabledFlag
    
    def selectedWidgets(self):
        """ Returns a list of all selected widgets.
        """
        if hasattr(self, "_selectedWidgets"):
            return self._selectedWidgets
        return [child for child in self.children() if hasattr(child, "isSelected") and child.isSelected()]
    
    def widgetSelected(self, widget, multiSelect=False):
        """ Forward selection information to super class if it is a VispaWidgetOwner.
        """
        logging.debug(self.__class__.__name__ +": widgetSelected()")

        if isinstance(self, QObject):
            if not hasattr(self, "_selectedWidgets"):
                self._selectedWidgets = []
                
            if  not multiSelect or not self.multiSelectEnabled():
                self.deselectAllWidgets(widget)
                self._selectedWidgets = []
                
            if widget.parent() == self and not widget in self._selectedWidgets:
                self._selectedWidgets.append(widget)
                
            for widget in [child for child in self._selectedWidgets if hasattr(child, "isSelected") and not child.isSelected()]:
                self._selectedWidgets.remove(widget)
                
            if isinstance(self.parent(), VispaWidgetOwner):
                self.parent().widgetSelected(widget)
            
    def widgetDoubleClicked(self, widget):
        """ Forward selection information to super class if it is a VispaWidgetOwner.
        """
        #logging.debug(self.__class__.__name__ +": widgetDoubleClicked()")
        if isinstance(self, QObject):
            if isinstance(self.parent(), VispaWidgetOwner):
                self.parent().widgetDoubleClicked(widget)
                
    def initWidgetMovement(self, widget):
        self._lastMovedWidgets = []
        if self.multiSelectEnabled():
            pos = widget.pos()
            for child in self.children():
                if child != widget and hasattr(child, "isSelected") and child.isSelected():
                    child.setDragReferencePoint(pos - child.pos())
            
    def widgetDragged(self, widget):
        """ Tell parent widget has moved.
        
        Only informs parent if it is a VispaWidgetOwner, too.
        """
        if isinstance(self.parent(), VispaWidgetOwner):
            self.parent().widgetDragged(widget)

        if hasattr(self, "_lastMovedWidgets"):
            self._lastMovedWidgets.append(widget)
            
        if self.multiSelectEnabled():
            for child in self.children():
                if hasattr(child, "dragReferencePoint") and child != widget and hasattr(child, "isSelected") and child.isSelected():
                    if hasattr(child, "setPreviousDragPosition"):
                        child.setPreviousDragPosition(child.pos())
                    child.move(widget.pos() - child.dragReferencePoint())
                    self._lastMovedWidgets.append(child)

# apparently unused feature (2010-07-02), remove if really unnecessary
# also see self._lastMovedWidget definition above
    def lastMovedWidgets(self):
        if hasattr(self, "_lastMovedWidgets"):
            return self._lastMovedWidgets
        return None

    def widgetAboutToDelete(self, widget):
        """ This function is called from the delete() function of VispaWidget.
        """
        pass
        
    def keyPressEvent(self, event):
        """ Calls delete() method of selected child widgets if multi-select is activated.
        """
        if self.multiSelectEnabled() and ( event.key() == Qt.Key_Backspace or event.key() == Qt.Key_Delete ):
            selection = self.selectedWidgets()[:]
            for widget in selection:
                widget.delete()
    
    def deselectAllWidgets(self, exception=None):
        """ Deselects all widgets except the widget given as exception.
        """
        #logging.debug(self.__class__.__name__ +": deselectAllWidgets()")
        self._selectedWidgets = []
        for child in self.children():
            if child != exception:
                if hasattr(child, 'select'):
                    child.select(False)
            else:
                self._selectedWidgets.append(child)
                
            if isinstance(child, VispaWidgetOwner):
                child.deselectAllWidgets(exception)
        self.update()
        
    def mousePressEvent(self, event):
        """ Calls deselectAllWidgets.
        """
        multiSelectEnabled = self.multiSelectEnabled()
        if event.modifiers() != Qt.ControlModifier:
            self.deselectAllWidgets()
        if multiSelectEnabled:
            self._selectionRectStartPos = QPoint(event.pos())
            self._selectionRect = None

    def mouseMoveEvent(self, event):
        if self.multiSelectEnabled() and self._selectionRectStartPos and (event.pos() - self._selectionRectStartPos).manhattanLength() >= QApplication.startDragDistance():
            eventX = event.pos().x()
            eventY = event.pos().y()
            startX = self._selectionRectStartPos.x()
            startY = self._selectionRectStartPos.y()
            oldRect = self._selectionRect
            self._selectionRect = QRect(min(startX, eventX), min(startY, eventY), abs(eventX - startX), abs(eventY - startY))
            if oldRect:
                self.update(self._selectionRect.united(oldRect).adjusted(-5, -5, 5, 5))
            else:
                self.update(self._selectionRect)
                
            # dynamically update selection statur
            # currently bad performance (2010-07-07)
            # TODO: improve selection mechanism
#            for child in self.children():
#                if hasattr(child, "select") and hasattr(child, "isSelected"):
#                    child.select(self._selectionRect.contains(child.geometry()), True)    # select, mulitSelect 
                
    def mouseReleaseEvent(self, event):
        if hasattr(self, "_selectionRect") and  self._selectionRect and self.multiSelectEnabled():
            for child in self.children():
                if hasattr(child, "select") and hasattr(child, "isSelected") and self._selectionRect.contains(child.geometry()) and not child.isSelected():
                    child.select(True, True)    # select, mulitSelect 
            self.update(self._selectionRect.adjusted(-5, -5, 5, 5))
        self._selectionRect = None
        self._selectionRectStartPos = None
        
예제 #41
0
파일: EchoSet.py 프로젝트: yougukepp/radar
class EchoSet(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.mCenter = QPoint(0, 0)
        self.mRadius = 0
        self.mEchoLines = []
        self.mEchoLinesIndex = 0

        self.SetCenter(QPoint(0,0))
        self.SetRadius(0)
        self.SetRange("50m")
        self.SetHdt(0)

        # 制作回波线角度表,用于提升性能
        step = 2.0 * gPI / gEchoLineCountAFrame
        self.mCosAngleTable = []
        self.mSinAngleTable = []
        for i in range(0, gEchoLineCountAFrame):
            self.mCosAngleTable.append(0)
            self.mSinAngleTable.append(0)
        for i in range(0, gEchoLineCountAFrame):
            angle = i * step - 90 * g1Deg
            self.mCosAngleTable[i] = math.cos(angle)
            self.mSinAngleTable[i] = math.sin(angle)

    def SetData(self, echoSetStrs):
        for echoStr in echoSetStrs:
            echoLine = EchoLine(echoStr)
            self.mEchoLines.append(echoLine)

    # 绘制时的圆心坐标
    def SetCenter(self, center):
        self.mCenter = center;

    # 绘制半径
    def SetRadius(self, radius):
        self.mRadius = radius * gRadarEchoScale

    # 设置量程
    def SetRange(self, radarRange):
        assert radarRange in gRangeTable, "量程表中没有量程:" + radarRange
        self.mRangeName = radarRange
        self.mRange = gRangeTable[radarRange][0]
        self.mPrecision = gRangeTable[radarRange][1]

    # 设置船艏向
    def SetHdt(self, hdt):
        self.mHdt = 0

    # 绘制
    def Draw(self, p): 
        self.__DrawAEchoLine(p, self.mEchoLinesIndex)
        self.__DrawShipHeadLine(p)
        self.__DrawDisCircle(p)
        self.__DrawRangeCicle(p)
        self.__DrawSysInfo(p)

        self.mEchoLinesIndex += 1
        indexMax = len(self.mEchoLines)
        if self.mEchoLinesIndex == indexMax:
            self.mEchoLinesIndex = 0 

    # 绘制量程范围
    def __DrawRangeCicle(self, p):
        pen = QPen(QColor(0, 255, 0))
        p.setPen(pen)

    # 绘制距标圈
    def __DrawDisCircle(self, p):
        pen = QPen(QColor(0, 150, 0))
        p.setPen(pen)
        p.setBrush(Qt.NoBrush)

        r = self.mRadius
        rHalf = 0.5 * r
        rHalfOne = 1.5 * r
        self.__DrawCircle(p, self.mCenter, r)
        self.__DrawCircle(p, self.mCenter, rHalf)
        self.__DrawCircle(p, self.mCenter, rHalfOne)

    # 绘制船艏线
    def __DrawShipHeadLine(self, p):
        pen = QPen(QColor(255, 255, 255))
        p.setPen(pen)

        angle = self.mHdt - 90 * g1Deg

        xStart = int(self.mCenter.x())
        yStart = int(self.mCenter.y())
        xEnd = int(self.mRadius * math.cos(angle) + xStart)
        yEnd = int(self.mRadius * math.sin(angle) + yStart)

        p.drawLine(xStart, yStart, xEnd, yEnd) 

        brush = QBrush(QColor(255, 255, 255), Qt.SolidPattern);
        p.setBrush(brush);

        angle = self.mHdt + 90 * g1Deg
        ang = angle - 30 * g1Deg;
        cos_a = math.cos(ang);
        sin_a = math.sin(ang);
        x1 = xEnd + gShipLegendLen * cos_a;
        y1 = yEnd - gShipLegendLen * sin_a;

        ang = angle + 30 * g1Deg;
        cos_a = math.cos(ang);
        sin_a = math.sin(ang);
        x2 = xEnd + gShipLegendLen * cos_a;
        y2 = yEnd - gShipLegendLen * sin_a;

        p1 = QPointF(xEnd, yEnd)
        p2 = QPointF(x1, y1)
        p3 = QPointF(x2, y2)
        p.drawPolygon(p1, p2, p3);
        
    # 绘制系统信息
    def __DrawSysInfo(self, p):
        pen = QPen(QColor(0, 255, 0))
        p.setPen(pen)
        p.drawText(2, 20, "量程:" + self.mRangeName)
        p.drawText(2, 40, "船艏:" + str(self.mHdt) + "度")

    # 绘制回波
    def __DrawAEchoLine(self, p, i):
        self.__DrawShadeLine(p, i)
        echoLinsCount = len(self.mEchoLines)
        if 0 == echoLinsCount:
            return
        assert i < echoLinsCount, "回波线索引越界"

        # TODO: 使用查表法 提速
        cosAngle = self.mCosAngleTable[i]
        sinAngle = self.mSinAngleTable[i]
        echoLine = self.mEchoLines[i]

        echoLine.Draw(p, self.mCenter, self.mRadius, cosAngle, sinAngle, self.mRange, self.mPrecision)

    # 清除回波线上的上一帧数据
    def __DrawShadeLine(self,p, i):
        pen = QPen(QColor(0, 0, 0))

        angle = i / gEchoLineCountAFrame * 2 * gPI - 90 * g1Deg + g1Deg
        xStart = int(self.mCenter.x())
        yStart = int(self.mCenter.y())
        xEnd = int(self.mRadius * math.cos(angle) + xStart)
        yEnd = int(self.mRadius * math.sin(angle) + yStart)

        p.setPen(pen)
        p.drawLine(xStart, yStart, xEnd, yEnd) 

    def __DrawCircle(self, p, center, r):
        x = center.x() - r
        y = center.y() - r

        width = 2 * r
        height = 2 * r

        p.drawEllipse(x, y, width, height)
예제 #42
0
    def click_by_gui_simulation(self, element):
        """Uses Qt GUI-level events to simulate a full user click.
        
        Takes a QWebElement as input.
        
        Implementation taken from Artemis:
        https://github.com/cs-au-dk/Artemis/blob/720f051c4afb4cd69e560f8658ebe29465c59362/artemis-code/src/runtime/input/clicksimulator.cpp#L73
        
        Method:
            * Find coordinates of the centre of the element.
            * Scroll viewport to show element.
            * Generate a GUI click at those coordinates.
        
        N.B. This will be different from click(..., full_simulation=True) in cases where the target element is
        obscured. In these cases the click will go at the centre coordinates of the taregt element, whether that means
        we click the target or the obscuring element.
        """

        verbose = False

        # We can avoid pulling the position from JavaScript (as Artemis needs to) because we allow the browser to process events all the time, so it should respond to position updates OK.
        targetCoordsInPage = element.geometry().center()
        targetCoords = QPoint(
            targetCoordsInPage.x() -
            self.page().mainFrame().scrollBarValue(Qt.Horizontal),
            targetCoordsInPage.y() -
            self.page().mainFrame().scrollBarValue(Qt.Vertical))
        viewportSize = self.page().viewportSize()

        if verbose:
            print "click_by_gui_simulation: Clicking viewport coordinates ({}, {})".format(
                targetCoords.x(), targetCoords.y())
            print "click_by_gui_simulation:", element.toOuterXml()
            print "click_by_gui_simulation: Dimensions of web view are X: {} Y: {}".format(
                viewportSize.width(), viewportSize.height())

        if ((viewportSize.width() + self.page().mainFrame().scrollBarValue(
                Qt.Horizontal)) < targetCoords.x()
                or self.page().mainFrame().scrollBarValue(
                    Qt.Horizontal) > targetCoords.x() or
            (viewportSize.height() + self.page().mainFrame().scrollBarValue(
                Qt.Vertical)) < targetCoords.y()
                or self.page().mainFrame().scrollBarValue(
                    Qt.Vertical) > targetCoords.y()):

            if verbose:
                print "click_by_gui_simulation: Target outside viewport, repositioning"

            xScroll = min(
                self.page().mainFrame().contentsSize().width() -
                viewportSize.width(),  # Scroll to the far right
                max(
                    0,  # Don't scroll / Scroll to the far left
                    targetCoords.x() -
                    (viewportSize.width() / 2)  # Put the target in the middle
                ))

            self.page().mainFrame().setScrollBarValue(Qt.Horizontal, xScroll)

            yScroll = min(
                self.page().mainFrame().contentsSize().height() -
                viewportSize.height(),  # Scroll to the bottom
                max(
                    0,  # Don't scroll / Scroll to the top
                    targetCoords.y() - (viewportSize.height() / 2)))

            self.page().mainFrame().setScrollBarValue(Qt.Vertical, yScroll)

            targetCoords = QPoint(targetCoords.x() - xScroll,
                                  targetCoords.y() - yScroll)

            if verbose:
                print "click_by_gui_simulation: Changed coordinates to ({}, {})".format(
                    targetCoords.x(), targetCoords.y())

        #element.setFocus(); # This is already implied by the browser handling the click.

        # Click the target element's coordinates.

        mouseButtonPress = QMouseEvent(QEvent.MouseButtonPress, targetCoords,
                                       Qt.LeftButton, Qt.LeftButton,
                                       Qt.NoModifier)
        QApplication.sendEvent(self.page(), mouseButtonPress)

        mouseButtonRelease = QMouseEvent(QEvent.MouseButtonRelease,
                                         targetCoords, Qt.LeftButton,
                                         Qt.LeftButton, Qt.NoModifier)
        QApplication.sendEvent(self.page(), mouseButtonRelease)
예제 #43
0
class MikiView(QWebView):
    def __init__(self, parent=None):
        super(MikiView, self).__init__(parent)
        self.parent = parent

        self.settings().clearMemoryCaches()
        self.notePath = parent.settings.notePath
        self.settings().setUserStyleSheetUrl(
            QUrl('file://' + self.parent.settings.cssfile))
        print(QUrl('file://' + self.parent.settings.cssfile))
        self.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks)

        self.page().linkClicked.connect(self.linkClicked)
        self.page().linkHovered.connect(self.linkHovered)
        self.page().mainFrame().contentsSizeChanged.connect(
            self.contentsSizeChanged)

        self.scrollPosition = QPoint(0, 0)

    def linkClicked(self, qurl):
        '''three kinds of link:
            external uri: http/https
            page ref link:
            toc anchor link: #
        '''
        name = qurl.toString()
        http = re.compile('https?://')
        if http.match(name):  # external uri
            QDesktopServices.openUrl(qurl)
            return

        self.load(qurl)
        name = name.replace('file://', '')
        name = name.replace(self.notePath, '').split('#')
        item = self.parent.notesTree.pageToItem(name[0])
        if not item or item == self.parent.notesTree.currentItem():
            return
        else:
            self.parent.notesTree.setCurrentItem(item)
            if len(name) > 1:
                link = "file://" + self.notePath + "/#" + name[1]
                self.load(QUrl(link))
            viewFrame = self.page().mainFrame()
            self.scrollPosition = viewFrame.scrollPosition()

    def linkHovered(self, link, title, textContent):
        '''show link in status bar
            ref link shown as: /parent/child/pageName
            toc link shown as: /parent/child/pageName#anchor (ToFix)
        '''
        # TODO: link to page by: /parent/child/pageName#anchor
        if link == '':  # not hovered
            self.parent.statusBar.showMessage(
                self.parent.notesTree.currentPage())
        else:  # beautify link
            link = link.replace('file://', '')
            link = link.replace(self.notePath, '')
            self.parent.statusBar.showMessage(link)

    def contentsSizeChanged(self, newSize):
        '''scroll notesView while editing (adding new lines)
           Whithout this, every `updateView` will result in scroll to top.
        '''
        if self.scrollPosition == QPoint(0, 0):
            return
        viewFrame = self.page().mainFrame()
        newY = self.scrollPosition.y() + newSize.height(
        ) - self.contentsSize.height()
        self.scrollPosition.setY(newY)
        viewFrame.setScrollPosition(self.scrollPosition)

    def updateView(self):
        # url_notebook = 'file://' + os.path.join(self.notePath, '/')
        viewFrame = self.page().mainFrame()
        # Store scrollPosition before update notesView
        self.scrollPosition = viewFrame.scrollPosition()
        self.contentsSize = viewFrame.contentsSize()
        url_notebook = 'file://' + self.notePath + '/'
        self.setHtml(self.parent.notesEdit.toHtml(), QUrl(url_notebook))
        # Restore previous scrollPosition
        viewFrame.setScrollPosition(self.scrollPosition)

    def updateLiveView(self):
        if self.parent.actions.get('split').isChecked():
            QTimer.singleShot(1000, self.updateView)
예제 #44
0
파일: afficheurImage.py 프로젝트: Ptaah/Ekd
class VisionneurImagePourEKD(QScrollArea):
	''' Classe pour l'affichage des images (avec des barres de
	défilement)'''
	def __init__(self, img=None):
		QScrollArea.__init__(self)

		# Déclaration du drapeau: a-t-on chargé un *.gif
		if img and os.path.splitext(img)[1]!=".gif":
			self.gif = 1
		else:
			self.gif = 0
		
		# Facteur de redimensionnement de l'image à afficher par rapport à la taille réelle de l'image
		self.factor = 1
		
		# Variables de paramètres
		self.modeTransformation=Qt.SmoothTransformation
		#self.modeTransformation=Qt.FastTransformation
		
		# widget qui contiendra l'image
		self.imageLabel = QLabel()
		self.imageLabel.setAlignment(Qt.AlignCenter)
		
		self.setBackgroundRole(QPalette.Dark)
		self.setWidget(self.imageLabel)
		# Indispensable pour ne pas avoir d'images tronquées, lors du chargement de nvll img
		self.setWidgetResizable(True)
		
		# Position du curseur dans le QScrollArea au moment du clic de la souris
		self.positionPresseeSourisIni = QPoint()
		# Position du point haut-gauche du QScrollArea par rapport au QPixMap entier au
		# moment du clic de la souris (par la suite appelée "position de la barre de défilement")
        	self.positionBarrePresseeSourisIni = QPoint()
		
		# Création du menu contextuel
		self.menuZoom=QMenu("Zoom")
		
		# Entrée zoom taille réelle
		self.menuTailleReelle=self.menuZoom.addAction(_(u'&Taille Réelle'))
		self.menuTailleReelle.setIcon(QIcon("Icones" + os.sep + "taillereelle.png"))
		self.connect(self.menuTailleReelle, SIGNAL("triggered()"), self.setTailleReelle)
		
		# Entrée zoom taille fenetre
		self.menuTailleFenetre=self.menuZoom.addAction(_(u'&Adapter à la fenêtre'))
		self.menuTailleFenetre.setIcon(QIcon("Icones" + os.sep + "fenetre.png"))
		self.connect(self.menuTailleFenetre, SIGNAL("triggered()"), self.setTailleFenetre)
	
		# Entrée zoom +
		self.menuZoomPlus=self.menuZoom.addAction(_(u'&Zoom Avant'))
		self.menuZoomPlus.setIcon(QIcon("Icones" + os.sep + "zoomplus.png"))
		self.connect(self.menuZoomPlus, SIGNAL("triggered()"), self.zoomAvant)
		
		# Entrée zoom - 
		self.menuZoomMoins=self.menuZoom.addAction(_(u'&Zoom Arrière'))
		self.menuZoomMoins.setIcon(QIcon("Icones" + os.sep + "zoommoins.png"))
		self.connect(self.menuZoomMoins, SIGNAL("triggered()"), self.zoomArriere)
		
		# Entrée mettre en pause/démarrer l'animation du gif
		self.menuStartPauseGif=self.menuZoom.addAction(_(u"Mettre en pause/démarrer l'animation"))
		self.menuStartPauseGif.setIcon(QIcon("Icones" + os.sep + "player_end.png"))
		self.connect(self.menuStartPauseGif, SIGNAL("triggered()"), self.startPauseGif)
			
		# Entrée mettre en pause/démarrer l'animation du gif
		self.menuStopGif=self.menuZoom.addAction(_(u"Arrêter l'animation"))
		self.menuStopGif.setIcon(QIcon("Icones" + os.sep + "player_stop.png"))
		self.connect(self.menuStopGif, SIGNAL("triggered()"), self.stopGif)
		
		# On cache les 2 menus de *.gif si on ne traite pas ce format
		if not self.gif:
			self.menuStartPauseGif.setVisible(False)
			self.menuStopGif.setVisible(False)
		
		# Si une image est en paramètre de classe, on l'affiche directement
		# sinon on pourra toujours l'afficher plus tard en appelant la
		# méthode setImage(), le moment venu
		if img:
			self.setImage(img)
			self.setToolTip(img)
		else:
			# image par défaut
			self.setImage("Icones" + os.sep + "avant-image.png")
			self.setToolTip(_(u"image d'accueil"))
			self.setTailleReelle()
	
	def mousePressEvent(self, event):
		"Menu contextuel et enregistrement de données préparant le déplacement de l'image par pincement"
		
		# Menu contextuel
		if event.button() == Qt.RightButton: 
			self.menuZoom.popup(event.globalPos())
		
		# On enregistre la position du curseur et de la barre de défilement au moment du clic
		elif event.button() == Qt.LeftButton:
			self.positionPresseeSourisIni = QPoint(event.pos())
			self.positionBarrePresseeSourisIni.setX(self.horizontalScrollBar().value())
			self.positionBarrePresseeSourisIni.setY(self.verticalScrollBar().value())
			if PYQT_VERSION_STR >= "4.1.0": 
				# curseur main fermée
				self.setCursor(Qt.ClosedHandCursor)
			else: self.setCursor(Qt.SizeAllCursor)
			event.accept()
	
	def mouseMoveEvent(self, event):
		"Déplacement de l'image dans le QScrollArea quand la souris est pressée"
		
		if self.positionPresseeSourisIni.isNull():
			event.ignore()
			return
		
		# Nouvelles positions de la barre de défilement (selon x et y)
		self.horizontalScrollBar().setValue(self.positionBarrePresseeSourisIni.x() + (self.positionPresseeSourisIni.x() - event.pos().x()))
		self.verticalScrollBar().setValue(self.positionBarrePresseeSourisIni.y() + (self.positionPresseeSourisIni.y() - event.pos().y()))
		self.horizontalScrollBar().update()
		self.verticalScrollBar().update()
		event.accept()
	
	def mouseReleaseEvent(self, event):
		"Réaffichage du curseur classique de la souris"
		self.setCursor(Qt.ArrowCursor)
		event.accept()
	
	def setScaleMode(self, mode):
		"Choix du mode de redimensionnement"
		# Mise à jour du paramètre
		self.modeTransformation=mode
	
	def setTailleFenetre(self):
		"Affichage taille fenetre"
		
		# Gestion de la taille
		#- Si l'image rentre
		##- Si l'image est trop grande
		# On retaille l'image en gardant le ratio entre 
		# le min (si l'image ne rentre pas dans le cadre), le max (sinon) de :
		#         * La largeur de la fenetre
		#         * La largeur de l'image
		#         * La hauteur de la fenetre
		#         * La hauteur de l'image
		if (self.preview.height() < self.height()) and (self.preview.width() < self.width()):
			width=max(self.preview.width(), self.width())
			height=max(self.preview.height(), self.height())
		else :
			width=min(self.preview.width(), self.width())
			height=min(self.preview.height(), self.height())

		if self.gif:
			self.redimGif(width - 5, height - 5)
		else:
			resultat = self.preview.get_preview().scaled(width - 5, height - 5, Qt.KeepAspectRatio, self.modeTransformation)
			debug(u"Preview : %s, taille : %d, %d" % (self.preview.get_imageName(), self.preview.width(), self.preview.height()))
			self.factor = min(float(self.height())/self.preview.height(), float(self.width())/self.preview.width())
		
		#-- On met l'image et on redimensionne le Label pour les images simples
		if not self.gif:
			self.imageLabel.setPixmap(resultat)


			
	
	def setTailleReelle(self):
		"Fonction d'affichage en taille réelle"
		self.preview.origin()

		width, height = self.preview.width(), self.preview.height()

		# On redimensionne le label à la taille de l'image
		if self.gif:
			self.redimGif(width, height)
		else:
			self.imageLabel.setPixmap(self.preview.get_preview())
		self.factor = 1
	
	def zoomAvant(self):
		"Fonction de zoom avant 25%"
		
		# On redimensionne l'image à 125% de la taille actuelle
		factor = 5/4. * self.factor

		width = int(self.preview.width() * factor)
		height = int(self.preview.height() * factor)

		if self.gif:
			self.redimGif(width, height)
		else:
			image = self.preview.get_preview().scaled(width, height, Qt.KeepAspectRatio)
			self.imageLabel.setPixmap(image)
		self.factor = factor
	
	def zoomArriere(self):
		"Fonction de zoom arrière 25%"
		
		# On redimensionne l'image à 75% de la taille actuelle
		factor = 3/4. * self.factor

		width = int(self.preview.width() * factor)
		height = int(self.preview.height() * factor)

		if self.gif:
			self.redimGif(width, height)
		else:
			image = self.preview.get_preview().scaled(width, height, Qt.KeepAspectRatio)
			self.imageLabel.setPixmap(image)
		self.factor = factor
	
	def startPauseGif(self):
		"Démarrer/mettre en pause l'animation de l'image gif"
		if self.movie.state() == QMovie.NotRunning:
			self.movie.start()
		else:
			self.movie.setPaused(self.movie.state() != QMovie.Paused)
	
	def stopGif(self):
		"Arrêter l'animation de l'image gif"
		if self.movie.state() != QMovie.NotRunning:
			self.movie.stop()
	
	def redimGif(self, width, height):
		"""Changer la taille d'affichage du gif en prenant soin d'arrêter et de
		reprendre l'animation si nécessaire.
		Il y a un petit bogue d'affichage sur la redimension (il disparait en changeant
		d'onglet ou de cadre et en revenant.
		"""
		etatInitial = self.movie.state()
		if etatInitial == QMovie.Running:
			self.movie.stop()
		self.movie.setScaledSize(QSize(width, height))
		if etatInitial == QMovie.Running:
			self.movie.start()
		else:
			# On redémarre le gif sinon l'image n'est pas actualisée et reste à la même taille
			self.movie.start()
			self.movie.stop()
	
	def isGif(self):
		"Indique si l'image affichée est un gif. Le test est effectué sur l'extension du fichier"
		return self.gif
	
	def setImage(self, img=None, fauxChemin=None, anim=False):
		"""Fonction de mise en place de l'image.
		Le faux chemin est utile pour dissocier le chemin que verra l'utilisateur
		du chemin de l'image affichée. Ils sont différents uniquement lorsqu'une image
		composite est affichée (cadres masque alpha 3D et image composite).
		L'argument "anim" dit si une image gif doit être animée.
		"""
		
		if not img:
			img = "Icones" + os.sep + "avant-image.png"
			self.setToolTip(_(u"image d'accueil"))
			self.setTailleReelle()
			return
		elif fauxChemin:
			self.setToolTip(fauxChemin)
		else:
			self.setToolTip(img)
		
		# Chargement du gif le cas échéant
		if isinstance(img, str) or isinstance(img, unicode):
			# En général
			extension = os.path.splitext(img)[1]
		elif isinstance(img, QString):
			# Pour selectWidget.py principalement
			extension = "." + QFileInfo(img).suffix()
		if extension == ".gif":
			self.menuStartPauseGif.setVisible(True)
			self.menuStopGif.setVisible(True)
			self.gif = 1
			self.movie = QMovie(img)
			# On démarre le gif de toute façon sinon l'image n'est pas visible
			self.movie.start()
			if not anim:
				self.movie.stop()
			self.imageLabel.setMovie(self.movie)
		else:
			# Pour des images non-gif, on cache les menus d'animation
			self.menuStartPauseGif.setVisible(False)
			self.menuStopGif.setVisible(False)
			self.gif = 0
		

		# Visiblement sous windows la taille du QScrollArea renvoie 0,
		# on passe par l'Objet à l'intérieur pour obtenir la taille de l'image à créer
		self.preview = EkdPreview(img, self.width(), 0, 10, False, True, True) #(chemin, largeur, qualité, cache?, keepRatio?, magnify? )

		# Par défault on charge en taille fenetre
		self.setTailleFenetre()
예제 #45
0
class ScribbleArea(QWidget):
    """
      this scales the image but it's not good, too many refreshes really mess it up!!!
    """
    def __init__(self, w, h, parent=None):
        super(ScribbleArea, self).__init__(parent)

        self.setAttribute(Qt.WA_StaticContents)
        self.scribbling = 0

        self.width = w
        self.height = h
        self.image_pen_width = 50
        self.pen_width = 1
        self.draw_color = Qt.red
        self.image = QImage(QSize(w, h), QImage.Format_RGB32)

        self.setMaximumSize(w * self.image_pen_width, w * self.image_pen_width)
        self.setMinimumSize(w * self.image_pen_width, h * self.image_pen_width)

        self.last_point = QPoint()
        self.clear_image()

    def set_draw_color(self, color):
        self.draw_color = color

    def array_draw(self, r, g, b, scale=1):
        for i in range(len(r)):
            self.image.setPixel(QPoint(i % 8, i // 8), (r[i] * scale << 16) |
                                (g[i] * scale << 8) | b[i] * scale)

        self.update()

    def fill_image(self, color):
        self.image.fill(color)
        self.update()

    def clear_image(self):
        self.image.fill(Qt.black)
        self.update()

    def mousePressEvent(self, event):
        self.parent().state = self.parent().STATE_COLOR_SCRIBBLE
        if event.button() == Qt.LeftButton:
            self.last_point = event.pos()
            self.scribbling = 1
        elif event.button() == Qt.RightButton:
            self.last_point = event.pos()
            self.scribbling = 2

    def mouseMoveEvent(self, event):
        if (event.buttons() & Qt.LeftButton) and self.scribbling == 1:
            self.draw_line_to(event.pos())
        elif (event.buttons() & Qt.RightButton) and self.scribbling == 2:
            self.draw_line_to(event.pos())

    def mouseReleaseEvent(self, event):
        if event.button() == Qt.LeftButton and self.scribbling == 1:
            self.draw_line_to(event.pos())
            self.scribbling = 0
        elif event.button() == Qt.RightButton and self.scribbling == 2:
            self.draw_line_to(event.pos())
            self.scribbling = 0

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.drawImage(
            event.rect(),
            self.image.scaledToWidth(self.width * self.image_pen_width))

    def draw_line_to(self, end_point):
        painter = QPainter(self.image)
        painter.setPen(
            QPen(self.draw_color if self.scribbling == 1 else Qt.black,
                 self.pen_width, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
        painter.drawLine(
            QPoint(self.last_point.x() // self.image_pen_width,
                   self.last_point.y() // self.image_pen_width),
            QPoint(end_point.x() // self.image_pen_width,
                   end_point.y() // self.image_pen_width))

        self.update()
        self.last_point = QPoint(end_point)
예제 #46
0
class View(KineticScrollArea):
    
    viewModeChanged = pyqtSignal(int)
    
    def __init__(self, parent=None):
        super(View, self).__init__(parent)
        
        self.setAlignment(Qt.AlignCenter)
        self.setBackgroundRole(QPalette.Dark)
        self.setMouseTracking(True)

        self._viewMode = FixedScale
        self._wheelZoomEnabled = True
        self._wheelZoomModifier = Qt.CTRL
        
        # delayed resize
        self._centerPos = False
        self._resizeTimer = QTimer(singleShot = True, timeout = self._resizeTimeout)
        
    def surface(self):
        """Returns our Surface, the widget drawing the page(s)."""
        sf = self.widget()
        if not sf:
            sf = surface.Surface(self)
            self.setSurface(sf)
        return sf
    
    def setSurface(self, sf):
        """Sets the given surface as our widget."""
        self.setWidget(sf)
        # For some reason mouse tracking *must* be enabled on the child as well...
        sf.setMouseTracking(True)
        self.kineticScrollingActive.connect(sf.updateKineticCursor)

    
    def viewMode(self):
        """Returns the current ViewMode."""
        return self._viewMode
        
    def setViewMode(self, mode):
        """Sets the current ViewMode."""
        if mode == self._viewMode:
            return
        self._viewMode = mode
        if mode:
            self.fit()
        self.viewModeChanged.emit(mode)
    
    def wheelZoomEnabled(self):
        """Returns whether wheel zoom is enabled."""
        return self._wheelZoomEnabled
        
    def setWheelZoomEnabled(self, enabled):
        """Sets whether wheel zoom is enabled.
        
        Wheel zoom is zooming using the mouse wheel and a keyboard modifier key
        (defaulting to Qt.CTRL).  Use setWheelZoomModifier() to set a key (or
        key combination).
        
        """
        self._wheelZoomEnabled = enabled
    
    def wheelZoomModifier(self):
        """Returns the modifier key to wheel-zoom with (defaults to Qt.CTRL)."""
        return self._wheelZoomModifier
        
    def setWheelZoomModifier(self, key):
        """Sets the modifier key to wheel-zoom with (defaults to Qt.CTRL).
        
        Can also be set to a ORed value, e.g. Qt.SHIFT|Qt.ALT.
        Only use Qt.ALT, Qt.CTRL, Qt.SHIFT and/or Qt.META.
        
        """
        self._wheelZoomModifier = key
        
    def load(self, document):
        """Convenience method to load all the pages from the given Poppler.Document."""
        self.surface().pageLayout().load(document)
        # dont do a fit() before the very first resize as the size is then bogus
        if self.viewMode():
            self.fit()
        self.surface().pageLayout().update()

    def clear(self):
        """Convenience method to clear the current layout."""
        self.surface().pageLayout().clear()
        self.surface().pageLayout().update()

    def scale(self):
        """Returns the scale of the pages in the View."""
        return self.surface().pageLayout().scale()
        
    def setScale(self, scale):
        """Sets the scale of all pages in the View."""
        self.surface().pageLayout().setScale(scale)
        self.surface().pageLayout().update()
        self.setViewMode(FixedScale)

    def visiblePages(self):
        """Yields the visible pages."""
        rect = self.viewport().rect()
        rect.translate(-self.surface().pos())
        rect.intersect(self.surface().rect())
        return self.surface().pageLayout().pagesAt(rect)

    def redraw(self):
        """Redraws, e.g. when you changed rendering hints or papercolor on the document."""
        pages = list(self.visiblePages())
        documents = set(page.document() for page in pages)
        for document in documents:
            cache.clear(document)
        for page in pages:
            page.repaint()

    def fit(self):
        """(Internal). Fits the layout according to the view mode.
        
        Prevents scrollbar/resize loops by precalculating which scrollbars will appear.
        
        """
        mode = self.viewMode()
        if mode == FixedScale:
            return
        
        maxsize = self.maximumViewportSize()
        
        # can vertical or horizontal scrollbars appear?
        vcan = self.verticalScrollBarPolicy() == Qt.ScrollBarAsNeeded
        hcan = self.horizontalScrollBarPolicy() == Qt.ScrollBarAsNeeded
        
        # width a scrollbar takes off the viewport size
        framewidth = 0
        if self.style().styleHint(QStyle.SH_ScrollView_FrameOnlyAroundContents, None, self):
            framewidth = self.style().pixelMetric(QStyle.PM_DefaultFrameWidth) * 2
        scrollbarextent = self.style().pixelMetric(QStyle.PM_ScrollBarExtent, None, self) + framewidth
        
        # first try to fit full size
        layout = self.surface().pageLayout()
        layout.fit(maxsize, mode)
        layout.reLayout()
        
        # minimal values
        minwidth = maxsize.width()
        minheight = maxsize.height()
        if vcan:
            minwidth -= scrollbarextent
        if hcan:
            minheight -= scrollbarextent
        
        # do width and/or height fit?
        fitw = layout.width() <= maxsize.width()
        fith = layout.height() <= maxsize.height()
        
        if not fitw and not fith:
            if vcan or hcan:
                layout.fit(QSize(minwidth, minheight), mode)
        elif mode & FitWidth and fitw and not fith and vcan:
            # a vertical scrollbar will appear
            w = minwidth
            layout.fit(QSize(w, maxsize.height()), mode)
            layout.reLayout()
            if layout.height() <= maxsize.height():
                # now the vert. scrollbar would disappear!
                # enlarge it as long as the vertical scrollbar would not be needed
                while True:
                    w += 1
                    layout.fit(QSize(w, maxsize.height()), mode)
                    layout.reLayout()
                    if layout.height() > maxsize.height():
                        layout.fit(QSize(w - 1, maxsize.height()), mode)
                        break
        elif mode & FitHeight and fith and not fitw and hcan:
            # a horizontal scrollbar will appear
            h = minheight
            layout.fit(QSize(maxsize.width(), h), mode)
            layout.reLayout()
            if layout.width() <= maxsize.width():
                # now the hor. scrollbar would disappear!
                # enlarge it as long as the horizontal scrollbar would not be needed
                while True:
                    h += 1
                    layout.fit(QSize(maxsize.width(), h), mode)
                    layout.reLayout()
                    if layout.width() > maxsize.width():
                        layout.fit(QSize(maxsize.width(), h - 1), mode)
                        break
        layout.update()
        
    def resizeEvent(self, ev):
        super(View, self).resizeEvent(ev)
        # Adjust the size of the document if desired
        if self.viewMode() and any(self.surface().pageLayout().pages()):
            if self._centerPos is False:
                self._centerPos = QPoint(0, 0)
            elif self._centerPos is None:
                # store the point currently in the center
                self._centerPos = self.viewport().rect().center() - self.surface().pos()
            if not self._resizeTimer.isActive():
                self._resizeTimeout()
            self._resizeTimer.start(150)
    
    def _resizeTimeout(self):
        if self._centerPos is None:
            return
        oldSize = self.surface().size()
        # resize the layout
        self.fit()
        # restore our position
        newSize = self.surface().size()
        newx = self._centerPos.x() * newSize.width() / oldSize.width()
        newy = self._centerPos.y() * newSize.height() / oldSize.height()
        # we explicitely want the non-kinetic centering function regardless of kinetic state.
        self.fastCenter(QPoint(newx, newy))
        self._centerPos = None

    def zoom(self, scale, pos=None):
        """Changes the display scale (1.0 is 100%).
        
        If pos is given, keeps that point at the same place if possible.
        Pos is a QPoint relative to ourselves.
        
        """
        scale = max(0.05, min(4.0, scale))
        if scale == self.scale():
            return
        
        if self.surface().pageLayout().count() == 0:
            self.setScale(scale)
            return
            
        if pos is None:
            pos = self.viewport().rect().center()
        
        surfacePos = pos - self.surface().pos()
        page = self.surface().pageLayout().pageAt(surfacePos)
        if page:
            pagePos = surfacePos - page.pos()
            x = pagePos.x() / float(page.width())
            y = pagePos.y() / float(page.height())
            self.setScale(scale)
            newPos = QPoint(round(x * page.width()), round(y * page.height())) + page.pos()
        else:
            x = surfacePos.x() / float(self.surface().width())
            y = surfacePos.y() / float(self.surface().height())
            self.setScale(scale)
            newPos = QPoint(round(x * self.surface().width()), round(y * self.surface().height()))
        surfacePos = pos - self.surface().pos()
        # use fastScrollBy as we do not want kinetic scrolling here regardless of its state.
        self.fastScrollBy(newPos - surfacePos)
            
    def zoomIn(self, pos=None, factor=1.1):
        self.zoom(self.scale() * factor, pos)
        
    def zoomOut(self, pos=None, factor=1.1):
        self.zoom(self.scale() / factor, pos)
        
    def wheelEvent(self, ev):
        if (self._wheelZoomEnabled and
            int(ev.modifiers()) & _SCAM == self._wheelZoomModifier):
            factor = 1.1 ** (ev.delta() / 120)
            if ev.delta():
                self.zoom(self.scale() * factor, ev.pos())
        else:
            super(View, self).wheelEvent(ev)
    
    def mousePressEvent(self, ev):
        """Mouse press event handler. Passes the event to the surface, and back to
        the base class if the surface did not do anything with it."""
        if not self.surface().handleMousePressEvent(ev):
            super(View, self).mousePressEvent(ev)

    def mouseReleaseEvent(self, ev):
        """Mouse release event handler. Passes the event to the surface, and back to
        the base class if the surface did not do anything with it."""
        if not self.surface().handleMouseReleaseEvent(ev):
            super(View, self).mouseReleaseEvent(ev)

    def mouseMoveEvent(self, ev):
        """Mouse move event handler. Passes the event to the surface, and back to
        the base class if the surface did not do anything with it."""
        if self.kineticIsIdle():
            if self.surface().handleMouseMoveEvent(ev):
                return
        super(View, self).mouseMoveEvent(ev)

    def moveEvent(self, ev):
        """Move event handler. Passes the event to the surface if we've not started any kinetic move,
        and back to the base class if the surface did not do anything with it."""
        if self.kineticIsIdle():
            if self.surface().handleMoveEvent(ev):
                return
        super(View, self).moveEvent(ev)

    def event(self, ev):
        if isinstance(ev, QHelpEvent):
            if self.surface().handleHelpEvent(ev):
                ev.accept()
                return True
        
        return super(View, self).event(ev)
    
    def currentPage(self):
        """Returns the Page currently mostly in the center, or None if there are no pages."""
        pos = self.viewport().rect().center() - self.surface().pos()
        layout = self.surface().pageLayout()
        if len(layout):
            d = layout.spacing() * 2
            for dx, dy in ((0, 0), (-d, 0), (0, -d), (d, 0), (0, d)):
                dist = QPoint(dx, dy)
                page = layout.pageAt(pos + dist)
                if page:
                    return page
    
    def currentPageNumber(self):
        """Returns the number (index in the layout) of the currentPage(), or -1 if there are no pages."""
        page = self.currentPage()
        if page:
            return self.surface().pageLayout().index(page)
        return -1

    def gotoPageNumber(self, num):
        """Aligns the page at the given index in the layout to the topleft of our View."""
        layout = self.surface().pageLayout()
        if num < len(layout) and num != self.currentPageNumber():
            margin = QPoint(layout.margin(), layout.margin())
            self.scrollBy(layout[num].pos() + self.surface().pos() - margin)
            
    def position(self):
        """Returns a three-tuple(num, x, y) describing the page currently in the center of the View.
        
        the number is the index of the Page in the Layout, and x and y are the coordinates in the
        range 0.0 -> 1.0 of the point that is at the center of the View.
        
        This way a position can be retained even if the scale or the orientation of the Layout changed.
        
        Returns None, None, None if the layout is empty.
        
        """
        page = self.currentPage()
        if page:
            layout = self.surface().pageLayout()
            pos = self.viewport().rect().center() - self.surface().pos()
            pagePos = pos - page.pos()
            x = pagePos.x() / float(page.width())
            y = pagePos.y() / float(page.height())
            return layout.index(page), x, y
        return None, None, None

    def setPosition(self, position, overrideKinetic=False):
        """Sets the position to a three-tuple as previously returned by position().
        
        Setting overrideKinetic to true allows for fast setup, instead of scrolling all the way to the visible point.
        """
        layout = self.surface().pageLayout()
        pageNum, x, y = position
        if pageNum is None or pageNum >= len(layout):
            return
        page = layout[pageNum]
        # center this point
        newPos = QPoint(round(x * page.width()), round(y * page.height())) + page.pos()
        if overrideKinetic:
            self.fastCenter(newPos)
        else:
            self.center(newPos)
예제 #47
0
파일: MainViewMaya.py 프로젝트: iras/JADE
class MainMayaWindow (QObject):
    '''
    Base QObject for the JADE Maya scripted plugin.
    Notice the difference with the MainMWindow. This class is subclassing QObject while the Standalone one subclasses QWidget.
    
    This class handles the Maya way to deal with the contextual pop-up menu. Additionally, this class shares some of the responsibilities with graph.py.
    '''
    def __init__ (self, graph, parent=None):
        '''constructor
        
        @param graph the model
        @param parent a parent QObject, or None for root window.
        '''
        super (MainMayaWindow, self).__init__(parent)
        QObject.__init__(self) # initiation indispensable for sending and receiving signals!
        
        # define scene and constrain its workspace
        self.scene = QGraphicsScene ()
        self.scene.setSceneRect (QRectF (-1000, -1000, 2000, 2000))
        
        self.graph_model = graph
        self.helper = utility.Helper (self, self.scene, self.graph_model)
        self.graph_view  = grv.GraphView (self.graph_model, self.helper)
        self.helper.setGraphView (self.graph_view)
        
        # wirings
        self.comm = self.graph_model.getComm ()
        self.connect (self.comm, SIGNAL ('deleteNode_MSignal(int)'), self.graph_view.removeTag)
        self.connect (self.comm, SIGNAL ('addLink_MSignal(int,int)'), self.graph_view.addWire)
        self.connect (self.comm, SIGNAL ('deleteLink_MSignal(int,int)'), self.graph_view.checkIfEmpty)
        self.connect (self.comm, SIGNAL ('addNode_MSignal(int, float, float)'), self.graph_view.addTag)
        
        self.scene.addItem (self.helper.getHarpoon ())
        
        self.hovered_tag_id = None
        
        # register a new command that takes care of deleting selected items and bind it to the key 'd'.
        cmds.nameCommand ('delSelection', ann='deleteSelectedItems', c='python (\"ClientMaya.ui.graph_view.removeSelectedItems ()\");')
        cmds.hotkey (k='d', name='delSelection')
    
    def setupUi (self, MainWindow):
        '''sets up the Maya UI.
        
        @param MainWindow
        '''
        MainWindow.setObjectName ('MainWindow')
        MainWindow.resize (800, 1396)
        sizePolicy = QSizePolicy (QSizePolicy.Preferred, QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch (0)
        sizePolicy.setVerticalStretch (0)
        sizePolicy.setHeightForWidth(MainWindow.sizePolicy().hasHeightForWidth())
        MainWindow.setSizePolicy(sizePolicy)
        font = QFont ()
        font.setPointSize (11)
        MainWindow.setFont (font)
        MainWindow.setWindowTitle (QApplication.translate("MainWindow", "Location Tool", None, QApplication.UnicodeUTF8))
        MainWindow.setTabShape (QTabWidget.Rounded)
        MainWindow.setDockOptions (QMainWindow.AllowTabbedDocks|QMainWindow.AnimatedDocks)
        
        self.scrollAreaWidgetContents_3 = QWidget (MainWindow)
        self.scrollAreaWidgetContents_3.setGeometry (QRect(10, 10, 900, 940))
        self.scrollAreaWidgetContents_3.setObjectName ('scrollAreaWidgetContents_3')
        self._view = View0.View ("JADEview", self.graph_view, self.scene, self.scrollAreaWidgetContents_3)
        self._view.setObjectName ('JADEview')  # real ui name
        self._view.graphicsView.setObjectName ('JADEInnerView')
        self.connect (self.scene, SIGNAL("selectionChanged()"), self._view.selectionChanged)
        
        self._view.wireViewItemsUp ()
        self._view.getGraphicsView().setScene (self.scene)
        self._view.setToolboxCSSColorScheme ('background-color: rgb(68,68,68);color: rgb(200,200,200)') # this needs to be done since the toolbox's background didn't have a uniform colour otherwise.
        #self._view.setGraphicsViewCSSBackground () # the CSS background doesn't seem to work in Maya as there seems to be a problem with cleaning QGraphicsLineItems when they move, that doesn't happen when there's no CSS applied to the background.

        self.graphicsView = self._view.getGraphicsView ()
        self.node_coords = QPoint (0,0)
        
        layout = QHBoxLayout (self.scrollAreaWidgetContents_3)
        layout.setContentsMargins (QMargins(0,0,0,0));
        layout.addWidget (self._view)
        
        QMetaObject.connectSlotsByName (MainWindow)
        
        """
        cmds.control('JADEInnerView', edit=True, ebg=True, bgc=[.5,.5,.9])
        print cmds.control('JADEInnerView', query=True, p=True)
        """
        
        # wiring the Maya Contextual pop-up Menus - yes, in Maya we've split the pop-up menu definition in three pop-up menus although only one will be present at any time.
        self.menu        = cmds.popupMenu ('JADEmenu',        parent='JADEInnerView', button=3, pmc = 'ClientMaya.ui.ctxMenu()',        aob=True)
        self.menuAddOuts = cmds.popupMenu ('JADEmenuAddOuts', parent='JADEInnerView', button=3, pmc = 'ClientMaya.ui.ctxMenuAddOuts()', aob=True, alt=True)
        self.menuAddIns  = cmds.popupMenu ('JADEmenuAddIns',  parent='JADEInnerView', button=3, pmc = 'ClientMaya.ui.ctxMenuAddIns()',  aob=True, ctl=True)
        
        # this class property is used to keep track of the mouse position.
        self._mouse = QCursor
        
        # self._view's zoom slider (we need this to correct the bias added to sort the mouse position when the zoom changes - ONLY in Maya)
        self._zoom_slider = self._view.getZoomSlider()
    
    # - - -    context menus methods   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    
    def ctxMenu (self):
        '''this method invokes the general Maya pop-up menu.
        '''
        self.hovered_tag_id = self.comm.getHoveredItemId()
        
        cmds.popupMenu ('JADEmenu', edit=True, dai=True) # clear all the menu items out.
        
        if self.hovered_tag_id==None:
            # ctx menu to establish what node is going to be retrieved
            tmp_ls = []
            [tmp_ls.append(key) for key in self.graph_model.getNodesDecription()]
            self.prepareGeneralCtxMenu (tmp_ls)
    
    def prepareGeneralCtxMenu (self, list0):
        '''populates the self.menu dynamically with available node infos.
        
        @param list0 list of menu items
        '''
        self.node_coords = self.graphicsView.mapToScene (self._mouse.pos())
        
        # populate the QMenu dynamically and pass the menu string name to the receiver
        for i in sorted (list0):
            cmds.menuItem (parent=self.menu, label=str(i), c='ClientMaya.ui.addTag ("'+str(i)+'")')
    
    def addTag (self, name0):
        '''adds a Tag0 instance by name. the constants added to the are needed to make the tag pop up near the mouse pointer.
        
        @param name0 string
        '''
        if self._view.getCurrentClusterIndex () != 0:
            
            # the piece-wise linear interpolation below is a workaround only present in the Maya JADE mapping tool since
            # the self.graphicsView.mapToScene() doesn't seem to work as the standalone's one.
            if self._zoom_slider.value() > 199 and self._zoom_slider.value() < 241:
                x_bias = -22.5*(self._zoom_slider.value()-200) + 2100
                y_bias = -3.75*(self._zoom_slider.value()-200) + 400
            elif self._zoom_slider.value() > 240 and self._zoom_slider.value() < 281:
                x_bias = -12.5*(self._zoom_slider.value()-240) + 1200
                y_bias = -2.5* (self._zoom_slider.value()-240) + 250
            
            new_node = self.graph_model.addNode (name0, self.node_coords.x() - x_bias, self.node_coords.y() - y_bias)
            self._view.updateCurrentClusterNodeList (new_node)
            
            self._view.setMessageBarText ('')
        else:
            self._view.setMessageBarText ('** Choose or create a cluster first. Node not created.')
    
    def ctxMenuAddOuts (self):
        '''this method invokes the Maya add-outs pop-up menu.
        '''
        self.hovered_tag_id = self.comm.getHoveredItemId()
        
        cmds.popupMenu ('JADEmenuAddOuts', edit=True, dai=True) # clear all the menu items out.
        
        if self.hovered_tag_id!=None:
            
            right_list = self.graph_model.getOutsTypesLeft (self.hovered_tag_id)
            if len(right_list)!=0:
                self.prepareNodeCtxMenuOnAddingOuts (right_list)
    
    def ctxMenuAddIns (self):
        '''this method invokes the Maya add-ins pop-up menu.
        '''
        self.hovered_tag_id = self.comm.getHoveredItemId()
        
        cmds.popupMenu ('JADEmenuAddIns', edit=True, dai=True) # clear all the menu items out.
        
        if self.hovered_tag_id!=None:
            
            left_list = self.graph_model.getInsTypesLeft (self.hovered_tag_id)
            if len(left_list)!=0:
                self.prepareNodeCtxMenuOnAddingIns (left_list)
    
    def prepareNodeCtxMenuOnAddingOuts (self, list0):
        '''populates the self.menuAddOuts dynamically with available node infos.
        
        @param list0 list of menu items
        '''
        for i in sorted(list0):
            cmds.menuItem (parent=self.menuAddOuts, label=str(i), c='ClientMaya.ui.addOutSocketAction ("'+str(i)+'")')
        
        self.helper.setMenu (self.menuAddOuts)
    
    def prepareNodeCtxMenuOnAddingIns (self, list0):
        '''populates the self.menuAddIns dynamically with available node infos.
        
        @param list0 list of menu items
        '''
        for i in sorted (list0):
            cmds.menuItem (parent=self.menuAddIns, label=str(i), c='ClientMaya.ui.addInSocketAction ("'+str(i)+'")')
        
        self.helper.setMenu (self.menuAddIns)
    
    def addOutSocketAction (self, value):
        '''adds an out-socket name based on the pressed key modifier.
        
        @param value
        '''
        self.graph_view.getTag (self.hovered_tag_id) # retrieve the tag the ctx menu was open above.
        
        # the event released by adding an InSocket signal will trigger the Tag0's method appendOutHook as a result.
        self.graph_model.addOutSocket (self.hovered_tag_id, value)
    
    def addInSocketAction (self, value):
        '''adds an in-socket name based on the pressed key modifier.
        
        @param value
        '''
        self.graph_view.getTag (self.hovered_tag_id) # retrieve the tag the ctx menu was open above.
        
        # the event released by adding an InSocket signal will trigger the Tag0's method appendInHook() as a result.
        self.graph_model.addInSocket (self.hovered_tag_id, value)
예제 #48
0
class ThresholdingInterpreter(QObject):
    # states
    FINAL = 0
    DEFAULT_MODE = 1  # normal navigation functionality
    THRESHOLDING_MODE = 2  # while pressing left mouse button allow thresholding
    NO_VALID_LAYER = 3  # not a grayscale layer

    @property
    def state(self):
        return self._current_state

    def __init__(self, navigationControler, layerStack, posModel):
        QObject.__init__(self)
        self._navCtrl = navigationControler
        self._navIntr = NavigationInterpreter(navigationControler)
        self._layerStack = layerStack
        self._active_layer = None
        self._active_channel_idx = -1
        self._current_state = self.FINAL
        self._current_position = QPoint(0, 0)
        # Setting default values, scaled on actual data later on
        self._steps_mean = 10
        self._steps_delta = self._steps_mean * 2
        self._steps_scaling = 0.07
        self._range_max = 4096.0  # hardcoded, in the case drange is not set in the data file or in the dataSelectionDialogue
        self._range_min = -4096.0
        self._range = np.abs(self._range_max - self._range_min)
        self._channel_range = dict()
        self._posModel = posModel

    def start(self):
        if self._current_state == self.FINAL:
            self._navIntr.start()
            self._current_state = self.DEFAULT_MODE
            self._init_layer()
        else:
            pass

    def stop(self):
        self._current_state = self.FINAL
        if self.valid_layer():
            self._active_layer.channelChanged.disconnect(self.channel_changed)
        self._navIntr.stop()

    def eventFilter(self, watched, event):
        etype = event.type()
        if self._current_state == self.DEFAULT_MODE:
            if etype == QEvent.MouseButtonPress \
                    and event.button() == Qt.LeftButton \
                    and event.modifiers() == Qt.NoModifier \
                    and self._navIntr.mousePositionValid(watched, event):
                # TODO maybe remove, if we can find out which view is active
                self.set_active_layer()
                if self.valid_layer():
                    self._current_state = self.THRESHOLDING_MODE
                    self._current_position = watched.mapToGlobal(event.pos())
                    return True
                else:
                    self._current_state = self.NO_VALID_LAYER
                return self._navIntr.eventFilter(watched, event)
            elif etype == QEvent.MouseButtonPress \
                    and event.button() == Qt.RightButton \
                    and event.modifiers() == Qt.NoModifier \
                    and self._navIntr.mousePositionValid(watched, event):
                self.set_active_layer()
                if self.valid_layer():
                    self.onRightClick_resetThreshold(watched, event)
                else:
                    pass  # do nothing
                return True
            else:
                return self._navIntr.eventFilter(watched, event)
        elif self._current_state == self.NO_VALID_LAYER:
            self.set_active_layer()
            if self.valid_layer():
                self._current_state = self.DEFAULT_MODE
            return self._navIntr.eventFilter(watched, event)
        elif self._current_state == self.THRESHOLDING_MODE:
            if self._active_layer == None:  # No active layer set, should not go here
                return self._navIntr.eventFilter(watched, event)
            if etype == QEvent.MouseButtonRelease and event.button(
            ) == Qt.LeftButton:
                self._current_state = self.DEFAULT_MODE
                self._active_layer = None
                self.onExit_threshold(watched, event)
                return True
            elif etype == QEvent.MouseMove and event.buttons(
            ) == Qt.LeftButton:
                self.onMouseMove_thresholding(watched, event)
                return True
            else:
                return self._navIntr.eventFilter(watched, event)
        else:
            # let the navigation interpreter handle common events
            return self._navIntr.eventFilter(watched, event)

    def onRightClick_resetThreshold(self, imageview, event):
        range = self.get_min_max_of_current_view(imageview)
        self._active_layer.set_normalize(0, (range[0], range[1]))
        self._channel_range[self._active_channel_idx] = (range[0], range[1])

    def set_active_layer(self):
        """
        determines the layer postion in the stack and the currently displayed
        channel. Needs to be called constantly, because the user can change the 
        position of the input layer within the stack
        """
        for idx, layer in enumerate(self._layerStack):
            if isinstance(layer, GrayscaleLayer):
                if layer.window_leveling:
                    self._active_layer = layer
                    self._active_channel_idx = layer._channel
                    return
        self._active_layer = None

    def _init_layer(self):
        self.set_active_layer()
        if self.valid_layer():
            self._active_layer.channelChanged.connect(self.channel_changed)
            if self.get_drange() != None:
                self._range_min, self._range_max = self.get_drange()

    def onExit_threshold(self, watched, event):
        pass

    def get_drange(self):
        """ 
        returns tuple of drange (min, max) as set in hdf5 file or None 
        if nothing is specified
        """
        return self._active_layer._datasources[
            0]._rawSource._op5.Output.meta.drange

    def valid_layer(self):
        if isinstance(self._active_layer, GrayscaleLayer):
            return self._active_layer.window_leveling
        else:
            return False

    def channel_changed(self):
        self.set_active_layer()
        if self._active_channel_idx in self._channel_range:
            self._active_layer.set_normalize(
                0, self._channel_range[self._active_channel_idx])
        else:
            self._active_layer.set_normalize(
                0, (self._range_min, self._range_max))

    def get_min_max_of_current_view(self, imageview):
        """
        Function returns min and max value of the current view 
        based on the raw data.
        Ugly hack, but all we got for now
        """
        shape2D = posView2D(list(self._posModel.shape5D[1:4]),
                            axis=self._posModel.activeView)
        data_x, data_y = 0, 0
        data_x2, data_y2 = shape2D[0], shape2D[1]

        if self._posModel.activeView == 0:
            x_pos = self._posModel.slicingPos5D[1]
            slicing = [
                slice(0, 1),
                slice(x_pos, x_pos + 1),
                slice(data_x, data_x2),
                slice(data_y, data_y2),
                slice(self._active_channel_idx, self._active_channel_idx + 1)
            ]
        if self._posModel.activeView == 1:
            y_pos = self._posModel.slicingPos5D[2]
            slicing = [
                slice(0, 1),
                slice(data_x, data_x2),
                slice(y_pos, y_pos + 1),
                slice(data_y, data_y2),
                slice(self._active_channel_idx, self._active_channel_idx + 1)
            ]
        if self._posModel.activeView == 2:
            z_pos = self._posModel.slicingPos5D[3]
            slicing = [
                slice(0, 1),
                slice(data_x, data_x2),
                slice(data_y, data_y2),
                slice(z_pos, z_pos + 1),
                slice(self._active_channel_idx, self._active_channel_idx + 1)
            ]
        request = self._active_layer._datasources[0].request(slicing)
        result = request.wait()
        return result.min(), result.max()

    def onMouseMove_thresholding(self, imageview, event):
        if self._active_channel_idx not in self._channel_range:
            range = self.get_min_max_of_current_view(imageview)
            range_lower = range[0]
            range_upper = range[1]
        else:
            range = self._channel_range[self._active_channel_idx]
            range_lower = range[0]
            range_upper = range[1]
        # don't know what version is more efficient
        # range_delta = np.sqrt((range_upper - range_lower)**2)
        range_delta = np.abs(range_upper - range_lower)
        range_mean = range_lower + range_delta / 2.0

        self._steps_mean = range_delta * self._steps_scaling
        self._steps_delta = self._steps_mean * 2
        pos = imageview.mapToGlobal(event.pos())
        dx = pos.x() - self._current_position.x()
        dy = self._current_position.y() - pos.y()

        if dx > 0.0:
            # move mean to right
            range_mean += self._steps_mean
        elif dx < 0.0:
            # move mean to left
            range_mean -= self._steps_mean

        if dy > 0.0:
            # increase delta
            range_delta += self._steps_delta
        elif dy < 0.0:
            # decrease delta
            range_delta -= self._steps_delta

        # check the bounds, ugly use min max values actually present
        if range_mean < self._range_min:
            range_mean = self._range_min
        elif range_mean > self._range_max:
            range_mean = self._range_max

        if range_delta < 1:
            range_delta = 1
        elif range_delta > self._range:
            range_delta = self._range

        a = range_mean - range_delta / 2.0
        b = range_mean + range_delta / 2.0

        if a < self._range_min:
            a = self._range_min
        elif a > self._range_max:
            a = self._range_max

        if b < self._range_min:
            b = self._range_min
        elif b > self._range_max:
            b = self._range_max

        assert a <= b

        # TODO test if in allowed range (i.e. max and min of data)
        self._active_layer.set_normalize(0, (a, b))
        self._channel_range[self._active_channel_idx] = (a, b)
        self._current_position = pos
예제 #49
0
class WebPage(QObject):
    initialized = pyqtSignal()
    javaScriptAlertSent = pyqtSignal(str)
    javaScriptConsoleMessageSent = pyqtSignal(str, int, str)
    loadStarted = pyqtSignal()
    loadFinished = pyqtSignal(str)
    resourceReceived = pyqtSignal('QVariantMap')
    resourceRequested = pyqtSignal('QVariantMap')

    blankHtml = '<html><head></head><body></body></html>'

    def __init__(self, parent, args):
        super(WebPage, self).__init__(parent)

        # variable declarations
        self.m_paperSize = {}
        self.m_clipRect = QRect()
        self.m_libraryPath = ''
        self.m_scrollPosition = QPoint()

        self.setObjectName('WebPage')
        self.m_webPage = CustomPage(self)
        self.m_mainFrame = self.m_webPage.mainFrame()

        self.m_mainFrame.javaScriptWindowObjectCleared.connect(self.initialized)
        self.m_webPage.loadStarted.connect(self.loadStarted)
        self.m_webPage.loadFinished.connect(self.finish)

        # Start with transparent background
        palette = self.m_webPage.palette()
        palette.setBrush(QPalette.Base, Qt.transparent)
        self.m_webPage.setPalette(palette)

        # Page size does not need to take scrollbars into account
        self.m_webPage.mainFrame().setScrollBarPolicy(Qt.Horizontal, Qt.ScrollBarAlwaysOff)
        self.m_webPage.mainFrame().setScrollBarPolicy(Qt.Vertical, Qt.ScrollBarAlwaysOff)

        self.m_webPage.settings().setAttribute(QWebSettings.OfflineStorageDatabaseEnabled, True)
        self.m_webPage.settings().setOfflineStoragePath(QDesktopServices.storageLocation(QDesktopServices.DataLocation))
        self.m_webPage.settings().setAttribute(QWebSettings.LocalStorageDatabaseEnabled, True)
        self.m_webPage.settings().setAttribute(QWebSettings.OfflineWebApplicationCacheEnabled, True)
        self.m_webPage.settings().setOfflineWebApplicationCachePath(QDesktopServices.storageLocation(QDesktopServices.DataLocation))
        self.m_webPage.settings().setAttribute(QWebSettings.FrameFlatteningEnabled, True)
        self.m_webPage.settings().setAttribute(QWebSettings.LocalStorageEnabled, True)
        self.m_webPage.settings().setLocalStoragePath(QDesktopServices.storageLocation(QDesktopServices.DataLocation))

        # Ensure we have a document.body.
        self.m_webPage.mainFrame().setHtml(self.blankHtml)

        # Custom network access manager to allow traffic monitoring
        self.m_networkAccessManager = NetworkAccessManager(self.parent(), args)
        self.m_webPage.setNetworkAccessManager(self.m_networkAccessManager)
        self.m_networkAccessManager.resourceRequested.connect(self.resourceRequested)
        self.m_networkAccessManager.resourceReceived.connect(self.resourceReceived)

        self.m_webPage.setViewportSize(QSize(400, 300))

        do_action('WebPageInit')

    def applySettings(self, defaults):
        opt = self.m_webPage.settings()

        opt.setAttribute(QWebSettings.AutoLoadImages, defaults['loadImages'])
        opt.setAttribute(QWebSettings.PluginsEnabled, defaults['loadPlugins'])
        opt.setAttribute(QWebSettings.JavascriptEnabled, defaults['javascriptEnabled'])
        opt.setAttribute(QWebSettings.XSSAuditingEnabled, defaults['XSSAuditingEnabled'])
        opt.setAttribute(QWebSettings.LocalContentCanAccessRemoteUrls, defaults['localToRemoteUrlAccessEnabled'])

        if 'userAgent' in defaults:
            self.m_webPage.m_userAgent = defaults['userAgent']

        if 'userName' in defaults:
            self.m_networkAccessManager.m_userName = defaults['userName']

        if 'password' in defaults:
            self.m_networkAccessManager.m_password = defaults['password']

    def finish(self, ok):
        status = 'success' if ok else 'fail'
        self.loadFinished.emit(status)

    def mainFrame(self):
        return self.m_mainFrame

    def renderImage(self):
        contentsSize = self.m_mainFrame.contentsSize()
        contentsSize -= QSize(self.m_scrollPosition.x(), self.m_scrollPosition.y())
        frameRect = QRect(QPoint(0, 0), contentsSize)
        if not self.m_clipRect.isEmpty():
            frameRect = self.m_clipRect

        viewportSize = self.m_webPage.viewportSize()
        self.m_webPage.setViewportSize(contentsSize)

        image = QImage(frameRect.size(), QImage.Format_ARGB32)
        image.fill(qRgba(255, 255, 255, 0))

        painter = QPainter()

        # We use tiling approach to work-around Qt software rasterizer bug
        # when dealing with very large paint device.
        # See http://code.google.com/p/phantomjs/issues/detail?id=54.
        tileSize = 4096
        htiles = (image.width() + tileSize - 1) / tileSize
        vtiles = (image.height() + tileSize - 1) / tileSize
        for x in range(htiles):
            for y in range(vtiles):
                tileBuffer = QImage(tileSize, tileSize, QImage.Format_ARGB32)
                tileBuffer.fill(qRgba(255, 255, 255, 0))

                # Render the web page onto the small tile first
                painter.begin(tileBuffer)
                painter.setRenderHint(QPainter.Antialiasing, True)
                painter.setRenderHint(QPainter.TextAntialiasing, True)
                painter.setRenderHint(QPainter.SmoothPixmapTransform, True)
                painter.translate(-frameRect.left(), -frameRect.top())
                painter.translate(-x * tileSize, -y * tileSize)
                self.m_mainFrame.render(painter, QRegion(frameRect))
                painter.end()

                # Copy the tile to the main buffer
                painter.begin(image)
                painter.setCompositionMode(QPainter.CompositionMode_Source)
                painter.drawImage(x * tileSize, y * tileSize, tileBuffer)
                painter.end()

        self.m_webPage.setViewportSize(viewportSize)
        return image

    # Different defaults.
    # OSX: 72, X11: 75(?), Windows: 96
    pdf_dpi = 72
    def renderPdf(self, fileName):
        p = QPrinter()
        p.setOutputFormat(QPrinter.PdfFormat)
        p.setOutputFileName(fileName)
        p.setResolution(self.pdf_dpi)
        paperSize = self.m_paperSize

        if not len(paperSize):
            pageSize = QSize(self.m_webPage.mainFrame().contentsSize())
            paperSize['width'] = str(pageSize.width()) + 'px'
            paperSize['height'] = str(pageSize.height()) + 'px'
            paperSize['border'] = '0px'

        if paperSize.get('width') and paperSize.get('height'):
            sizePt = QSizeF(ceil(self.stringToPointSize(paperSize['width'])),
                            ceil(self.stringToPointSize(paperSize['height'])))
            p.setPaperSize(sizePt, QPrinter.Point)
        elif 'format' in paperSize:
            orientation = QPrinter.Landscape if paperSize.get('orientation') and paperSize['orientation'].lower() == 'landscape' else QPrinter.Portrait
            orientation = QPrinter.Orientation(orientation)
            p.setOrientation(orientation)

            formats = {
                'A0': QPrinter.A0,
                'A1': QPrinter.A1,
                'A2': QPrinter.A2,
                'A3': QPrinter.A3,
                'A4': QPrinter.A4,
                'A5': QPrinter.A5,
                'A6': QPrinter.A6,
                'A7': QPrinter.A7,
                'A8': QPrinter.A8,
                'A9': QPrinter.A9,
                'B0': QPrinter.B0,
                'B1': QPrinter.B1,
                'B2': QPrinter.B2,
                'B3': QPrinter.B3,
                'B4': QPrinter.B4,
                'B5': QPrinter.B5,
                'B6': QPrinter.B6,
                'B7': QPrinter.B7,
                'B8': QPrinter.B8,
                'B9': QPrinter.B9,
                'B10': QPrinter.B10,
                'C5E': QPrinter.C5E,
                'Comm10E': QPrinter.Comm10E,
                'DLE': QPrinter.DLE,
                'Executive': QPrinter.Executive,
                'Folio': QPrinter.Folio,
                'Ledger': QPrinter.Ledger,
                'Legal': QPrinter.Legal,
                'Letter': QPrinter.Letter,
                'Tabloid': QPrinter.Tabloid
            }

            p.setPaperSize(QPrinter.A4) # fallback
            for format_, size in formats.items():
                if format_.lower() == paperSize['format'].lower():
                    p.setPaperSize(size)
                    break
        else:
            return False

        border = floor(self.stringToPointSize(paperSize['border'])) if paperSize.get('border') else 0
        p.setPageMargins(border, border, border, border, QPrinter.Point)

        self.m_webPage.mainFrame().print_(p)
        return True

    def stringToPointSize(self, string):
        units = (
            ('mm', 72 / 25.4),
            ('cm', 72 / 2.54),
            ('in', 72.0),
            ('px', 72.0 / self.pdf_dpi / 2.54),
            ('', 72.0 / self.pdf_dpi / 2.54)
        )

        for unit, format_ in units:
            if string.endswith(unit):
                value = string.rstrip(unit)
                return float(value) * format_
        return 0

    def userAgent(self):
        return self.m_webPage.m_userAgent

    ##
    # Properties and methods exposed to JavaScript
    ##

    @pyqtSlot(str)
    def _appendScriptElement(self, scriptUrl):
        self.m_mainFrame.evaluateJavaScript('''
            var el = document.createElement('script');
            el.onload = function() { alert('%(scriptUrl)s'); };
            el.src = '%(scriptUrl)s';
            document.body.appendChild(el);
        ''' % {'scriptUrl': scriptUrl})

    @pyqtProperty('QVariantMap')
    def clipRect(self):
        clipRect = self.m_clipRect
        result = {
            'width': clipRect.width(),
            'height': clipRect.height(),
            'top': clipRect.top(),
            'left': clipRect.left()
        }
        return result

    @clipRect.setter
    def clipRect(self, size):
        sizes = {'width': 0, 'height': 0, 'top': 0, 'left': 0}
        for item in sizes:
            try:
                sizes[item] = int(size[item])
                if sizes[item] < 0:
                    if item not in ('top', 'left'):
                        sizes[item] = 0
            except (KeyError, ValueError):
                sizes[item] = self.clipRect[item]

        self.m_clipRect = QRect(sizes['left'], sizes['top'], sizes['width'], sizes['height'])

    @pyqtProperty(str)
    def content(self):
        return self.m_mainFrame.toHtml()

    @content.setter
    def content(self, content):
        self.m_mainFrame.setHtml(content)

    @pyqtSlot(str, result='QVariant')
    def evaluate(self, code):
        function = '(%s)()' % code
        return self.m_mainFrame.evaluateJavaScript(function)

    @pyqtSlot(str, result=bool)
    def injectJs(self, filePath):
        return injectJsInFrame(filePath, self.parent().m_scriptEncoding.encoding, self.m_libraryPath, self.m_mainFrame)

    @pyqtSlot(str, str, 'QVariantMap')
    @pyqtSlot(str, 'QVariantMap', 'QVariantMap')
    def openUrl(self, address, op, settings):
        operation = op
        body = QByteArray()

        self.applySettings(settings)
        self.m_webPage.triggerAction(QWebPage.Stop)

        if type(op) is dict:
            operation = op.get('operation')
            body = QByteArray(op.get('data', ''))

        if operation == '':
            operation = 'get'

        networkOp = QNetworkAccessManager.CustomOperation
        operation = operation.lower()
        if operation == 'get':
            networkOp = QNetworkAccessManager.GetOperation
        elif operation == 'head':
            networkOp = QNetworkAccessManager.HeadOperation
        elif operation == 'put':
            networkOp = QNetworkAccessManager.PutOperation
        elif operation == 'post':
            networkOp = QNetworkAccessManager.PostOperation
        elif operation == 'delete':
            networkOp = QNetworkAccessManager.DeleteOperation

        if networkOp == QNetworkAccessManager.CustomOperation:
            self.m_mainFrame.evaluateJavaScript('console.error("Unknown network operation: %s");' % operation)
            return

        if address.lower() == 'about:blank':
            self.m_mainFrame.setHtml(self.blankHtml)
        else:
            self.m_mainFrame.load(QNetworkRequest(QUrl(address)), networkOp, body)

    @pyqtProperty('QVariantMap')
    def paperSize(self):
        return self.m_paperSize

    @paperSize.setter
    def paperSize(self, size):
        self.m_paperSize = size

    @pyqtSlot()
    def release(self):
        self.parent().m_pages.remove(self)
        sip.delete(self)

    @pyqtSlot(str, result=bool)
    def render(self, fileName):
        if self.m_mainFrame.contentsSize() == '':
            return False

        fileInfo = QFileInfo(fileName)
        path = QDir()
        path.mkpath(fileInfo.absolutePath())

        if fileName.lower().endswith('.pdf'):
            return self.renderPdf(fileName)

        image = self.renderImage()

        return image.save(fileName)

    @pyqtProperty(str)
    def libraryPath(self):
        return self.m_libraryPath

    @libraryPath.setter
    def libraryPath(self, dirPath):
        self.m_libraryPath = dirPath

    @pyqtSlot(str, 'QVariant', 'QVariant')
    def sendEvent(self, type_, arg1, arg2):
        type_ = type_.lower()

        if type_ in ('mousedown', 'mouseup', 'mousemove'):
            eventType = QMouseEvent.Type(QEvent.None)
            button = Qt.MouseButton(Qt.LeftButton)
            buttons = Qt.MouseButtons(Qt.LeftButton)

            if type_ == 'mousedown':
                eventType = QEvent.MouseButtonPress
            elif type_ == 'mouseup':
                eventType = QEvent.MouseButtonRelease
            elif type_ == 'mousemove':
                eventType = QEvent.MouseMove
                button = buttons = Qt.NoButton

            assert eventType != QEvent.None

            event = QMouseEvent(eventType, QPoint(arg1, arg2), button, buttons, Qt.NoModifier)
            QApplication.postEvent(self.m_webPage, event)
            QApplication.processEvents()

            return

        if type_ == 'click':
            self.sendEvent('mousedown', arg1, arg2)
            self.sendEvent('mouseup', arg1, arg2)

    @pyqtProperty('QVariantMap')
    def scrollPosition(self):
        scroll = self.m_scrollPosition
        result = {
            'left': scroll.x(),
            'top': scroll.y()
        }
        return result

    @scrollPosition.setter
    def scrollPosition(self, size):
        positions = {'left': 0, 'top': 0}
        for item in positions:
            try:
                positions[item] = int(size[item])
                if positions[item] < 0:
                    positions[item] = 0
            except (KeyError, ValueError):
                positions[item] = self.scrollPosition[item]
        self.m_scrollPosition = QPoint(positions['left'], positions['top'])
        self.m_mainFrame.setScrollPosition(self.m_scrollPosition)

    @pyqtSlot(str, str)
    def uploadFile(self, selector, fileName):
        el = self.m_mainFrame.findFirstElement(selector)
        if el.isNull():
            return

        self.m_webPage.m_uploadFile = fileName
        el.evaluateJavaScript('''
            (function (el) {
                var ev = document.createEvent('MouseEvents');
                ev.initEvent('click', true, true);
                el.dispatchEvent(ev);
            })(this)
        ''')

    @pyqtProperty('QVariantMap')
    def viewportSize(self):
        size = self.m_webPage.viewportSize()
        result = {
            'width': size.width(),
            'height': size.height()
        }
        return result

    @viewportSize.setter
    def viewportSize(self, size):
        sizes = {'width': 0, 'height': 0}
        for item in sizes:
            try:
                sizes[item] = int(size[item])
                if sizes[item] < 0:
                    sizes[item] = 0
            except (KeyError, ValueError):
                sizes[item] = self.viewportSize[item]

        self.m_webPage.setViewportSize(QSize(sizes['width'], sizes['height']))

    do_action('WebPage')
예제 #50
0
class View(KineticScrollArea):

    viewModeChanged = pyqtSignal(int)

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

        self.setAlignment(Qt.AlignCenter)
        self.setBackgroundRole(QPalette.Dark)
        self.setMouseTracking(True)

        self._viewMode = FixedScale
        self._wheelZoomEnabled = True
        self._wheelZoomModifier = Qt.CTRL

        # delayed resize
        self._centerPos = False
        self._resizeTimer = QTimer(singleShot=True,
                                   timeout=self._resizeTimeout)

    def surface(self):
        """Returns our Surface, the widget drawing the page(s)."""
        sf = self.widget()
        if not sf:
            sf = surface.Surface(self)
            self.setSurface(sf)
        return sf

    def setSurface(self, sf):
        """Sets the given surface as our widget."""
        self.setWidget(sf)
        # For some reason mouse tracking *must* be enabled on the child as well...
        sf.setMouseTracking(True)
        self.kineticScrollingActive.connect(sf.updateKineticCursor)

    def viewMode(self):
        """Returns the current ViewMode."""
        return self._viewMode

    def setViewMode(self, mode):
        """Sets the current ViewMode."""
        if mode == self._viewMode:
            return
        self._viewMode = mode
        if mode:
            self.fit()
        self.viewModeChanged.emit(mode)

    def wheelZoomEnabled(self):
        """Returns whether wheel zoom is enabled."""
        return self._wheelZoomEnabled

    def setWheelZoomEnabled(self, enabled):
        """Sets whether wheel zoom is enabled.
        
        Wheel zoom is zooming using the mouse wheel and a keyboard modifier key
        (defaulting to Qt.CTRL).  Use setWheelZoomModifier() to set a key (or
        key combination).
        
        """
        self._wheelZoomEnabled = enabled

    def wheelZoomModifier(self):
        """Returns the modifier key to wheel-zoom with (defaults to Qt.CTRL)."""
        return self._wheelZoomModifier

    def setWheelZoomModifier(self, key):
        """Sets the modifier key to wheel-zoom with (defaults to Qt.CTRL).
        
        Can also be set to a ORed value, e.g. Qt.SHIFT|Qt.ALT.
        Only use Qt.ALT, Qt.CTRL, Qt.SHIFT and/or Qt.META.
        
        """
        self._wheelZoomModifier = key

    def load(self, document):
        """Convenience method to load all the pages from the given Poppler.Document."""
        self.surface().pageLayout().load(document)
        # dont do a fit() before the very first resize as the size is then bogus
        if self.viewMode():
            self.fit()
        self.surface().pageLayout().update()

    def clear(self):
        """Convenience method to clear the current layout."""
        self.surface().pageLayout().clear()
        self.surface().pageLayout().update()

    def scale(self):
        """Returns the scale of the pages in the View."""
        return self.surface().pageLayout().scale()

    def setScale(self, scale):
        """Sets the scale of all pages in the View."""
        self.surface().pageLayout().setScale(scale)
        self.surface().pageLayout().update()
        self.setViewMode(FixedScale)

    def visiblePages(self):
        """Yields the visible pages."""
        rect = self.viewport().rect()
        rect.translate(-self.surface().pos())
        rect.intersect(self.surface().rect())
        return self.surface().pageLayout().pagesAt(rect)

    def redraw(self):
        """Redraws, e.g. when you changed rendering hints or papercolor on the document."""
        pages = list(self.visiblePages())
        documents = set(page.document() for page in pages)
        for document in documents:
            cache.clear(document)
        for page in pages:
            page.repaint()

    def fit(self):
        """(Internal). Fits the layout according to the view mode.
        
        Prevents scrollbar/resize loops by precalculating which scrollbars will appear.
        
        """
        mode = self.viewMode()
        if mode == FixedScale:
            return

        maxsize = self.maximumViewportSize()

        # can vertical or horizontal scrollbars appear?
        vcan = self.verticalScrollBarPolicy() == Qt.ScrollBarAsNeeded
        hcan = self.horizontalScrollBarPolicy() == Qt.ScrollBarAsNeeded

        # width a scrollbar takes off the viewport size
        framewidth = 0
        if self.style().styleHint(QStyle.SH_ScrollView_FrameOnlyAroundContents,
                                  None, self):
            framewidth = self.style().pixelMetric(
                QStyle.PM_DefaultFrameWidth) * 2
        scrollbarextent = self.style().pixelMetric(QStyle.PM_ScrollBarExtent,
                                                   None, self) + framewidth

        # first try to fit full size
        layout = self.surface().pageLayout()
        layout.fit(maxsize, mode)
        layout.reLayout()

        # minimal values
        minwidth = maxsize.width()
        minheight = maxsize.height()
        if vcan:
            minwidth -= scrollbarextent
        if hcan:
            minheight -= scrollbarextent

        # do width and/or height fit?
        fitw = layout.width() <= maxsize.width()
        fith = layout.height() <= maxsize.height()

        if not fitw and not fith:
            if vcan or hcan:
                layout.fit(QSize(minwidth, minheight), mode)
        elif mode & FitWidth and fitw and not fith and vcan:
            # a vertical scrollbar will appear
            w = minwidth
            layout.fit(QSize(w, maxsize.height()), mode)
            layout.reLayout()
            if layout.height() <= maxsize.height():
                # now the vert. scrollbar would disappear!
                # enlarge it as long as the vertical scrollbar would not be needed
                while True:
                    w += 1
                    layout.fit(QSize(w, maxsize.height()), mode)
                    layout.reLayout()
                    if layout.height() > maxsize.height():
                        layout.fit(QSize(w - 1, maxsize.height()), mode)
                        break
        elif mode & FitHeight and fith and not fitw and hcan:
            # a horizontal scrollbar will appear
            h = minheight
            layout.fit(QSize(maxsize.width(), h), mode)
            layout.reLayout()
            if layout.width() <= maxsize.width():
                # now the hor. scrollbar would disappear!
                # enlarge it as long as the horizontal scrollbar would not be needed
                while True:
                    h += 1
                    layout.fit(QSize(maxsize.width(), h), mode)
                    layout.reLayout()
                    if layout.width() > maxsize.width():
                        layout.fit(QSize(maxsize.width(), h - 1), mode)
                        break
        layout.update()

    def resizeEvent(self, ev):
        super(View, self).resizeEvent(ev)
        # Adjust the size of the document if desired
        if self.viewMode() and any(self.surface().pageLayout().pages()):
            if self._centerPos is False:
                self._centerPos = QPoint(0, 0)
            elif self._centerPos is None:
                # store the point currently in the center
                self._centerPos = self.viewport().rect().center(
                ) - self.surface().pos()
            if not self._resizeTimer.isActive():
                self._resizeTimeout()
            self._resizeTimer.start(150)

    def _resizeTimeout(self):
        if self._centerPos is None:
            return
        oldSize = self.surface().size()
        # resize the layout
        self.fit()
        # restore our position
        newSize = self.surface().size()
        newx = self._centerPos.x() * newSize.width() / oldSize.width()
        newy = self._centerPos.y() * newSize.height() / oldSize.height()
        # we explicitely want the non-kinetic centering function regardless of kinetic state.
        self.fastCenter(QPoint(newx, newy))
        self._centerPos = None

    def zoom(self, scale, pos=None):
        """Changes the display scale (1.0 is 100%).
        
        If pos is given, keeps that point at the same place if possible.
        Pos is a QPoint relative to ourselves.
        
        """
        scale = max(0.05, min(4.0, scale))
        if scale == self.scale():
            return

        if self.surface().pageLayout().count() == 0:
            self.setScale(scale)
            return

        if pos is None:
            pos = self.viewport().rect().center()

        surfacePos = pos - self.surface().pos()
        page = self.surface().pageLayout().pageAt(surfacePos)
        if page:
            pagePos = surfacePos - page.pos()
            x = pagePos.x() / float(page.width())
            y = pagePos.y() / float(page.height())
            self.setScale(scale)
            newPos = QPoint(round(x * page.width()), round(
                y * page.height())) + page.pos()
        else:
            x = surfacePos.x() / float(self.surface().width())
            y = surfacePos.y() / float(self.surface().height())
            self.setScale(scale)
            newPos = QPoint(round(x * self.surface().width()),
                            round(y * self.surface().height()))
        surfacePos = pos - self.surface().pos()
        # use fastScrollBy as we do not want kinetic scrolling here regardless of its state.
        self.fastScrollBy(newPos - surfacePos)

    def zoomIn(self, pos=None, factor=1.1):
        self.zoom(self.scale() * factor, pos)

    def zoomOut(self, pos=None, factor=1.1):
        self.zoom(self.scale() / factor, pos)

    def wheelEvent(self, ev):
        if (self._wheelZoomEnabled
                and int(ev.modifiers()) & _SCAM == self._wheelZoomModifier):
            factor = 1.1**(ev.delta() / 120)
            if ev.delta():
                self.zoom(self.scale() * factor, ev.pos())
        else:
            super(View, self).wheelEvent(ev)

    def mousePressEvent(self, ev):
        """Mouse press event handler. Passes the event to the surface, and back to
        the base class if the surface did not do anything with it."""
        if not self.surface().handleMousePressEvent(ev):
            super(View, self).mousePressEvent(ev)

    def mouseReleaseEvent(self, ev):
        """Mouse release event handler. Passes the event to the surface, and back to
        the base class if the surface did not do anything with it."""
        if not self.surface().handleMouseReleaseEvent(ev):
            super(View, self).mouseReleaseEvent(ev)

    def mouseMoveEvent(self, ev):
        """Mouse move event handler. Passes the event to the surface, and back to
        the base class if the surface did not do anything with it."""
        if self.kineticIsIdle():
            if self.surface().handleMouseMoveEvent(ev):
                return
        super(View, self).mouseMoveEvent(ev)

    def moveEvent(self, ev):
        """Move event handler. Passes the event to the surface if we've not started any kinetic move,
        and back to the base class if the surface did not do anything with it."""
        if self.kineticIsIdle():
            if self.surface().handleMoveEvent(ev):
                return
        super(View, self).moveEvent(ev)

    def event(self, ev):
        if isinstance(ev, QHelpEvent):
            if self.surface().handleHelpEvent(ev):
                ev.accept()
                return True

        return super(View, self).event(ev)

    def currentPage(self):
        """Returns the Page currently mostly in the center, or None if there are no pages."""
        pos = self.viewport().rect().center() - self.surface().pos()
        layout = self.surface().pageLayout()
        if len(layout):
            d = layout.spacing() * 2
            for dx, dy in ((0, 0), (-d, 0), (0, -d), (d, 0), (0, d)):
                dist = QPoint(dx, dy)
                page = layout.pageAt(pos + dist)
                if page:
                    return page

    def currentPageNumber(self):
        """Returns the number (index in the layout) of the currentPage(), or -1 if there are no pages."""
        page = self.currentPage()
        if page:
            return self.surface().pageLayout().index(page)
        return -1

    def gotoPageNumber(self, num):
        """Aligns the page at the given index in the layout to the topleft of our View."""
        layout = self.surface().pageLayout()
        if num < len(layout) and num != self.currentPageNumber():
            margin = QPoint(layout.margin(), layout.margin())
            self.scrollBy(layout[num].pos() + self.surface().pos() - margin)

    def position(self):
        """Returns a three-tuple(num, x, y) describing the page currently in the center of the View.
        
        the number is the index of the Page in the Layout, and x and y are the coordinates in the
        range 0.0 -> 1.0 of the point that is at the center of the View.
        
        This way a position can be retained even if the scale or the orientation of the Layout changed.
        
        Returns None, None, None if the layout is empty.
        
        """
        page = self.currentPage()
        if page:
            layout = self.surface().pageLayout()
            pos = self.viewport().rect().center() - self.surface().pos()
            pagePos = pos - page.pos()
            x = pagePos.x() / float(page.width())
            y = pagePos.y() / float(page.height())
            return layout.index(page), x, y
        return None, None, None

    def setPosition(self, position, overrideKinetic=False):
        """Sets the position to a three-tuple as previously returned by position().
        
        Setting overrideKinetic to true allows for fast setup, instead of scrolling all the way to the visible point.
        """
        layout = self.surface().pageLayout()
        pageNum, x, y = position
        if pageNum is None or pageNum >= len(layout):
            return
        page = layout[pageNum]
        # center this point
        newPos = QPoint(round(x * page.width()), round(
            y * page.height())) + page.pos()
        if overrideKinetic:
            self.fastCenter(newPos)
        else:
            self.center(newPos)
예제 #51
0
class MSGLCanvas2D(QGLWidget):
    """
    Canvas GL plotting in 2 dimensions
    """
    
    
    MAX = 100.
    
    
    corner_=100.0
    zoom_= 1.5
    xrot_=220
    yrot_ = 220
    trans_x_ =0.0
    trans_y_ = 0.0
    
    
    def __init__(self, data, parent=None, **kw):
        """
        Constructor, initialization
        """
        
        QGLWidget.__init__(self, parent)
        self.setFormat(QGLFormat(QGL.SampleBuffers))
        self.setMinimumSize(500,300)#300
        self.setMouseTracking(True) 
        self.setFocusPolicy(Qt.StrongFocus)
        
        self.data=data
        vertexes=[]
        colors=[]
        from utils.misc import IceAndFire
        maxY=max(map(max, [log10(el.y_data) for el in data]))
        maxX=max(map(max, [el.x_data for el in data]))
        rtmax=max([z.rtmin for z in data])
        for el in data:
            for i, x in enumerate(el.x_data):
                c=IceAndFire.getQColor(log10(el.y_data[i])/maxY)
                colors.append(c)
                vertexes.append([(x*2*self.corner_)/maxX, (el.rt*2*self.corner_)/rtmax])
        from OpenGL.arrays.vbo import VBO
        
        self.vertexes= VBO(array(vertexes,'f'))
        self.colors=VBO(array(colors,'f'))
        
        self.mode = "None" # "ZOOMING", "PANNING", "NONE"
        self.lastpos = QPoint()
        
        self.counter_trans_x = 0
        self.counter_trans_y = 0

        
        self.defaultColors = {'ticks':(0.,0.,0.,0.),
                              'axes':(0.,0.,0.,0.),
                              'curves':(0.,0.,1.,0.),
                              'backgroundColor':(1.,1.,1.,1.)
                              }
     
        #self.axes=self.drawAxes()
        self.transformationMatrix = self.setupTransformationMatrix(self.width(), 
                                                                   self.height())
    
    
 
                                 
        
    def setupTransformationMatrix(self,w, h):
        """
        use a matrix to translate in the gl landmark
        """
        
        m = QMatrix()
        m.translate(-w/2, h/2)
        m.scale(300./w, 300./h)
        print w, h, w/300., 1-((h/300)-1)
        #m.scale((self.width()*100)/300, -(self.height()*100)/300)
        #self.currentSize.x = w
        #self.currentSize.y = h        
        return m


    
    def inGLCoordinate(self, point):
        return self.transformationMatrix.map(point)        
        
    
    
    def resizeGL(self, w, h):
        """
        called when window is being resized
        """
    
        glViewport(0,0, w, h)    
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluOrtho2D(-self.corner_*self.zoom_, 
                   self.corner_*self.zoom_, 
                   -self.corner_*self.zoom_, 
                   self.corner_*self.zoom_)

        #self.transformationMatrix = self.setupTransformationMatrix(w, h)
        
        glMatrixMode(GL_MODELVIEW)
    
    
    def initializeGL(self):
        """needed, initialize GL parameters"""
        
        #glClearColor(1.,1.,1.,1.)
        glDisable(GL_DEPTH_TEST)
        glEnable(GL_LINE_SMOOTH)
        glEnable(GL_POINT_SMOOTH)
        glHint (GL_LINE_SMOOTH_HINT, GL_NICEST)
        glLoadIdentity() #model view by default
        
#        self.grid_lines = self.drawGridLines()
#        self.ticks =self.drawAxisTick()
#        self.axes = self.drawAxes()

    
    
    def paintGL(self):
        """Draw the scene, needed, called each time glDraw"""
        
        glClear(GL_COLOR_BUFFER_BIT)
        glTranslated(self.trans_x_, self.trans_y_, 0.)
        #addition
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluOrtho2D(-self.corner_*self.zoom_, 
                    self.corner_*self.zoom_,    
                    -self.corner_*self.zoom_, 
                    self.corner_*self.zoom_)
        glMatrixMode(GL_MODELVIEW)
        #end addition
        #glCallList(self.grid_lines)
        #glCallList(self.ticks)
        #glCallList(self.axes)
        glLineWidth(30.0)
        self.scatterPlot()
#        if self.flags == "chrom":
#            self.drawAxisLegend("retention time[s]", "intensity[%]")
#            glCallList(self.lines)
#        elif self.flags == "spectrum":
#            self.drawAxisLegend("m/z", "intensity")
        
    
    
    
    def drawAxes(self, width=2., colour=(0.,0.,0.)):
        """
        Draw Axes 
        """
        #width must be a float
        axes = glGenLists(1)
        glNewList(axes, GL_COMPILE)
        glLineWidth(width)
        glColor(colour[0],colour[1],colour[2])
        glBegin(GL_LINES)
        #x_achse
        glVertex2d(-self.corner_, -self.corner_)
        glVertex2d( self.corner_, -self.corner_)
        #y-achse
        glVertex2d(-self.corner_, -self.corner_)
        glVertex2d( -self.corner_, self.corner_)
        glEnd()
        glEndList()
        return axes
        
    
    def drawLegends(self, pos):
        """
        draw legend at the specified position
        """
        pass
    
    
    
   
        
    
    
    def drawAxisLegend(self, x_label, y_label):
        """
        Draw Axis Legend
        """
        font =QFont("Typewriter")                        
        #RT axis legend
        font.setPixelSize(12)
        self.renderText(self.corner_, -self.corner_-20.0, 0., x_label)# font
        self.renderText(-self.corner_-20.0, self.corner_, 0., y_label, font)
    
    
    
    
            
            
    def resetTranslations(self):            
        """
        reset the different translation to 0
        """
        self.trans_x_ =0.
        self.trans_y_ =0.
        self.counter_trans_x=0.
        self.counter_trans_y=0.
    
    
    
    def normalizeAngle(self,angle):
            while (angle < 0):
                    angle += 360 * 16
            while (angle > 360 * 16):
                    angle -= 360 * 16


########DRAWING METHODS##################################################

    def drawLine(self, point_, point):
        glBegin(GL_LINES)
        glVertex2d(point_.x(), point_.y())
        glVertex2d(point.x(), point.y())
        glEnd()
    
    def drawRect(self, p_1, p_2, p_3=None, p_4 = None):
        pass
    
    def drawOnePoint(self, point, colour= Qt.yellow):
        pass
    
    def scatterPlot(self):
        """ Draw Data (x, y)"""
        if self.vertexes is not None and self.colors is not None:
            self.vertexes.bind()
            glEnableClientState(GL_VERTEX_ARRAY)
            glVertexPointerf(self.vertexes)
            self.colors.bind()                  
            glEnableClientState(GL_COLOR_ARRAY)
            glColorPointerf(self.colors)
            glDrawArrays(GL_LINES, 0, len(self.vertexes))
            self.vertexes.unbind()
            self.colors.unbind()
            #self.textures.unbind()
            glDisableClientState(GL_VERTEX_ARRAY)
            glDisableClientState(GL_COLOR_ARRAY)
    
    def spectrumPlot(self, points):
        pass
    
    def histogramPlot(self, points, bin = 5.):
        pass
        
    def barPlot(points, width =2.):pass

    


########MOUSE AND KEYBOARDS EVENTS###########################################################################
    
    
    def wheelEvent(self, event):
        if event.delta() >0:
            self.zoom_ -= .05    
        else:
            self.zoom_ += .05
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluOrtho2D(-self.corner_*self.zoom_, 
                   self.corner_*self.zoom_, 
                   -self.corner_*self.zoom_, 
                   self.corner_*self.zoom_)
        self.updateGL()
        glMatrixMode(GL_MODELVIEW)
        event.accept()
            
    
    
    
    def keyPressEvent(self,  event):
        if event.key() == Qt.Key_Plus:
            self.zoom_ -= .1
            glMatrixMode(GL_PROJECTION)
            glLoadIdentity()
            gluOrtho2D(-self.corner_*self.zoom_, 
                       self.corner_*self.zoom_,    
                       -self.corner_*self.zoom_, 
                       self.corner_*self.zoom_)
            glMatrixMode(GL_MODELVIEW)

        if event.key() == Qt.Key_Minus:
                self.zoom_ += .1
                glMatrixMode(GL_PROJECTION) #// You had GL_MODELVIEW
                glLoadIdentity()
                gluOrtho2D(-self.corner_*self.zoom_, self.corner_*self.zoom_, -self.corner_*self.zoom_, self.corner_*self.zoom_)
                glMatrixMode(GL_MODELVIEW)
                
        if event.key() == Qt.Key_Up:
                self.trans_y_ += 2
                self.counter_trans_y +=2
                
        if event.key() == Qt.Key_Down:
                self.trans_y_ -=2
                self.counter_trans_y -=2
                
        if event.key() == Qt.Key_Left:
                self.trans_x_ -=2
                self.counter_trans_x -=2
                
        if event.key() == Qt.Key_Right:
                self.trans_x_ +=2
                self.counter_trans_x +=2
        
        
        if event.key() == Qt.Key_Z:
            self.mode= "ZOOMING"
            if self.counter_trans_x < 0 and self.counter_trans_y < 0:
                while self.counter_trans_x < 0 and self.counter_trans_y < 0:
                    self.trans_x_ = self.counter_trans_x
                    self.trans_y_ = self.counter_trans_y                    
                    self.updateGL()
                    self.counter_trans_x += 1
                    self.counter_trans_y += 1
                    
            if self.counter_trans_x > 0 and self.counter_trans_y < 0:
                while self.counter_trans_x < 0 and self.counter_trans_y < 0:
                    self.trans_x_ = self.counter_trans_x
                    self.trans_y_ = self.counter_trans_y                    
                    self.updateGL()
                    self.counter_trans_x -= 1
                    self.counter_trans_y += 1
            
            if self.counter_trans_x < 0 and self.counter_trans_y > 0:
                while self.counter_trans_x < 0 and self.counter_trans_y < 0:
                    self.trans_x_ = self.counter_trans_x
                    self.trans_y_ = self.counter_trans_y                    
                    self.updateGL()
                    self.counter_trans_x += 1
                    self.counter_trans_y -= 1
    
            if self.counter_trans_x < 0 and self.counter_trans_y > 0:
                while self.counter_trans_x < 0 and self.counter_trans_y < 0:
                    self.trans_x_ = self.counter_trans_x
                    self.trans_y_ = self.counter_trans_y                    
                    self.updateGL()
                    self.counter_trans_x -= 1
                    self.counter_trans_y -= 1
                    
            if self.zoom_ != 1.5:    
                self.zoom = 1.5
                #self.updateGL()
        self.updateGL()
        self.resetTranslations()    
        
    
    def mousePressEvent(self, event):
        if self.mode == "ZOOMING":
            self.mode = "None"
            self.computeSelection()
        else: 
            self.lastpos = QPoint(event.pos())
            self.setCursor(QCursor(Qt.ClosedHandCursor))
        
        
        #if event.buttons() ==  Qt.RightButton:
        #    self.mode = "PANNING"
            
    def computeSelection(self):
        print "selected"

    
    
    def mouseMoveEvent(self, event):
        dx = event.x() - self.lastpos.x()
        dy = event.y() - self.lastpos.y()
        
        if self.mode == "ZOOMING":
            font = QFont("Typewriter")
            self.renderText(-self.corner_ -30.0, self.corner_, 0., "ZOOMING MODE ACTIVATED", font)
            self.updateGL()
            glColor(0., 0., 1., .5)
            XMAX = 900.; XMIN = 180.
            pointer_x = (self.lastpos.x()*200.)/XMAX
            norm_dx = (dx*200.)/XMAX
            """
            if pointer_x > 100. or pointer_x < 100. \
                or norm_dx >100. or norm_dx<-100.:
                event.ignore()
            """

            
            glBegin(GL_QUADS)
            glVertex2d(pointer_x, -100.)
            glVertex2d(pointer_x+ norm_dx, -100.)
            glVertex2d(pointer_x+ norm_dx, 100.)
            glVertex2d(pointer_x, 100.)
            glEnd()
            
            self.updateGL()#update for seeing the rectangle
            
        mapping = self.mapFromGlobal
        cursorPos = self.inGLCoordinate(mapping(self.cursor().pos()))        
        QToolTip.showText(self.cursor().pos(),
                          "x:"+str(cursorPos.x())+ \
                          ", y:"+str(cursorPos.y())
                          )

        if self.mode == "None":      
            if event.buttons()== Qt.LeftButton:
                self.trans_y_ -= dy/5
                self.counter_trans_y -= dy/5
                self.trans_x_ += dx/5
                self.counter_trans_x += dx/5
            self.lastpos = QPoint(event.pos())
            self.glDraw()
            self.resetTranslations()        

    
    def mouseReleaseEvent(self, event):
        self.setCursor(QCursor(Qt.ArrowCursor))
예제 #52
0
class MSGLCanvas3D(QGLWidget):
    """Canvas GL plotting in 3 dimensions spectra"""
    
        
    corner=100.0
    near=0.0
    far=600.0
    zoom= 1.5
    xrot=220
    yrot = 220
    zrot=0
    trans_x =0.0
    trans_y = 0.0    

    
    def __init__(self, vertexes, colors, parent=None, **kw):#vertexes, colors, texturePath='graphics/Texture-Example.jpg', parent=None):#spl, peak=None, parent=None):
        """
        Constructor, initialization
        kw:
            -texturePath:pathway to the file to text
            -textures: coord textures to apply
            -parent:the parent widget
        """
        QGLWidget.__init__(self, parent)
        self.setFormat(QGLFormat(QGL.SampleBuffers))
        self.setMinimumSize(500,300)
        self.setMouseTracking(True)
        self.setFocusPolicy(Qt.StrongFocus)
        
#        if not 'texturePath'in kw.keys() and not 'textures' in kw.keys():
#            pass
#            #print ('Could not apply texture, no coordinates')
#        else:
#            try:
#                self._imageID = self.loadImage(kw.get('texturePath'))
#                self.textures = textures
#            except OSError:
#                print ('Could not apply texture, no coordinates')
            
        
        self.vertexes = vertexes
        self.colors = colors

        #self.axes=None
        self.zoom_mode = False
        self.pan_mode = True
        #self.axes = self.makeAxes()

        self.parameters={'axes_color':'b',
                        'axes_line_width':3.,
                        'draw_line_width':1.,
                        'colormap':True,
                        'fish_eye':False,
                        'cell_shading':False}
        self.lastpos = QPoint()

       
    
    def loadImage(self, imageName):		
        im = open(imageName)
        try:
            ix, iy, image = im.size[0], im.size[1], im.tostring("raw", "RGBA", 0, -1)
        except SystemError:
            ix, iy, image = im.size[0], im.size[1], im.tostring("raw", "RGBX", 0, -1)
        ID = glGenTextures(1)
        glBindTexture(GL_TEXTURE_2D, ID)
        glPixelStorei(GL_UNPACK_ALIGNMENT,1)
        glTexImage2D(GL_TEXTURE_2D, 0, 3, ix, iy, 0, GL_RGBA, GL_UNSIGNED_BYTE, image)
        return ID
    
    
    def setupTexture(self):
        glEnable(GL_TEXTURE_2D)
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL)
        glBindTexture(GL_TEXTURE_2D, self.imageID)
        
    
    
    def texturesCalc(self):
        from OpenGL.arrays.vbo import VBO
        basis = [[0.,0.], [0.,1.]]
        hola =[]        
        
        length = len(self.vertexes)
        for i in range(length/2):
            hola+=basis
        return VBO(array(hola))
    
    
    def recalcVertexesAndColors(self, colormap, **kwargs):
        pass
    
    def resizeGL(self, w, h):
        """called when window is being resized"""
        glViewport(0,0, w, h)     
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        glOrtho(-self.corner*self.zoom, 
                self.corner*self.zoom, 
                -self.corner*self.zoom, 
                self.corner*self.zoom , 
                self.near, 
                self.far)
        #gluPerspective(70,w/h, 1,1000)
        glMatrixMode(GL_MODELVIEW)
        
    
    def initializeGL(self):
        """opengl options"""
        #glClearColor(1., 1., 1., 1.)
        #glClearColor(0.,0.,0.)
        glEnable(GL_DEPTH_TEST)
        #glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
        glEnable(GL_LINE_SMOOTH)
        #glEnable(GL_POINT_SMOOTH)
        #glHint (GL_LINE_SMOOTH_HINT, GL_NICEST)#
        #glDepthFunc(GL_LEQUAL)
        glEnable(GL_CULL_FACE)

        #glCullFace(GL_BACK)
        #glEnable(GL_LIGHTING)
        #glLightfv(GL_LIGHT0, GL_DIFFUSE,(0.8, 0.8, 0.8, 1))
        #glEnable(GL_LIGHT0)
        #glEnable(GL_COLOR_MATERIAL)
        #glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE)
        #self.shader = compileProgram(vertex_shader, frag_shader)#vertex_shader)#shader
        #self.drawAxisLegend()

    
   
    
    
    
    
    def paintGL(self):
        """needed, called each time glDraw"""
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        glLoadIdentity()
        glTranslated(0.0, 0.0,-3.0*self.corner)
        glRotated(self.xrot / 16.0, 1.0, 0.0, 0.0)
        glRotated(self.yrot / 16.0, 0.0, 1.0, 0.0)
        glRotated(self.zrot/16.0, 0.0, 0.0, 1.0)
        glTranslated(self.trans_x, self.trans_y, 3.0*self.corner)
        #testing
        #glEnable(GL_DEPTH_TEST)
        #glEnable(GL_BLEND)
        #glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
      
        #self.setupTexture()
        #self.textures = self.texturesCalc()
        self.drawScene()
        #if self.zoom_mode:
        #    self.drawQuad()
        
    
    def renderTextModes(self):
        self.renderText(10, 10, 'mode:%s'%"zoom" if self.zoom_mode else 'mode:%s'%"pan", font=QFont())
        self.renderText(10, 20, 'selection mode:%s'%str(False), font=QFont())
        
    def drawScene(self):
        #
        self.renderTextModes()
        glLineWidth(1.)
        #glUseProgram(self.shader)
        if self.vertexes is not None and self.colors is not None:
            self.vertexes.bind()
            glEnableClientState(GL_VERTEX_ARRAY)
            glVertexPointerf(self.vertexes)
            self.colors.bind()                  
            glEnableClientState(GL_COLOR_ARRAY)
            glColorPointerf(self.colors)
            """        
            self.textures.bind()
            glEnableClientState(GL_TEXTURE_COORD_ARRAY)
            glTexCoordPointerf(self.textures)
            """
            glDrawArrays(GL_LINES, 0, len(self.vertexes))
            
            self.vertexes.unbind()
            self.colors.unbind()
            #self.textures.unbind()
            glDisableClientState(GL_VERTEX_ARRAY)
            glDisableClientState(GL_COLOR_ARRAY)
            #glDisableClientState(GL_TEXTURE_COORD_ARRAY)
            #glUseProgram(0)
        #glUseProgram(0)
        #if hasattr(self, 'axes'):
        #glCallList(self.axes)
        #glCallList(self.surface)
        #self.drawAxisLegend()

    
    
    def makeAxes(self):
        """Draw Axes """
        glLineWidth(2.0)
        glColor(0.,0.,1.)
        lspectr = glGenLists(1)
        glNewList(lspectr,GL_COMPILE)
        glBegin(GL_LINES)
        #glEnable(GL_LINE_STIPPLE)
        #glLineStipple(1, 1)
        glVertex3d(self.corner, -self.corner, -self.near-2*self.corner)
        glVertex3d(self.corner, self.corner, -self.near-2*self.corner)

        glVertex3d(self.corner, -self.corner, -self.far+2*self.corner)
        glVertex3d(self.corner, +self.corner, -self.far+2*self.corner)
        

        glVertex3d(-self.corner, -self.corner, -self.far+2*self.corner)
        glVertex3d(-self.corner, +self.corner, -self.far+2*self.corner)
        
        glVertex3d(-self.corner, +self.corner, -self.far+2*self.corner)
        glVertex3d(self.corner, +self.corner, -self.far+2*self.corner)
        
        
        glVertex3d(+self.corner, +self.corner, -self.far+2*self.corner)
        glVertex3d(+self.corner, +self.corner, -self.near-2*self.corner)
        #glDisable(GL_LINE_STIPPLE)
        
        glVertex3d(+self.corner, -self.corner, -self.far+2*self.corner)
        glVertex3d(+self.corner, -self.corner, -self.near-2*self.corner)
        
        glVertex3d(-self.corner, -self.corner, -self.far+2*self.corner)
        glVertex3d(self.corner, -self.corner, -self.far+2*self.corner)

        glEnd()
        glEndList()        
        return lspectr
    
    
    
    def drawAxisLegend(self):
        
        """Draw Axis Legend"""
        
        font = QFont("Typewriter")
        font.setPixelSize(10)
                
        #RT axis legend
        font.setPixelSize(12)
        self.qglColor(Qt.blue)
        mz_label = "retention time [s]";rt_label = "m/z"
        self.renderText(0.0,  -self.corner-20.0,  -self.near-2*self.corner+20.0, rt_label, font)
        self.renderText(-self.corner-20.0, -self.corner-20.0, -self.near-3*self.corner, mz_label, font)
        self.renderText(-self.corner-20.0, self.corner+10.0, -self.near-2*self.corner+20.0, "intensity %", font)
        font.setPixelSize(10)
        
#        #for rt number
#        for i in xrange (0,len(self.rtList), 100):
#            text = str(math.ceil(((self.rtList[i][0])*self.max_rt )/ self.max_rt))
#            self.renderText(-self.corner, 
#                            -self.corner -5.0, 
#                            -self.near-2*self.corner - self.rtList[i][0], 
#                            text, 
#                            font)
        
#        for i in xrange (0, len(self.massList[0]), 100):
#            text = str(math.ceil(((self.massList[0][i])*self.max_mass )/ 2*self.corner))
#            self.renderText( self.corner, 
#                             self.corner -5.0, 
#                            -self.near-2*self.corner - self.massList[0][i], 
#                            text, 
#                            font)
#        #for mz number

    def resetTranslations(self):
        
        """reset the different translation to 0"""
        
        self.trans_x =0.
        self.trans_y =0.
    
   
    def normalizeAngle(self,angle):
        """taken from qt documentation"""
        
        while (angle < 0):
            angle += 360 * 16
        while (angle > 360 * 16):
            angle -= 360 * 16
        return angle
    


    def computeSelection(self):pass
    


#===============================================================================
#              MOUSE AND KEYBOARDS EVENTS
#===============================================================================
    def wheelEvent(self, event):
        if event.delta() >0:
            self.zoom -= .05
            
        else:
            self.zoom += .05
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        glOrtho(-self.corner*self.zoom, 
                self.corner*self.zoom,    
                -self.corner*self.zoom, 
                self.corner*self.zoom , 
                self.near, 
                self.far)
        glMatrixMode(GL_MODELVIEW)
        self.updateGL()
        event.accept()
        
    
    
    def keyPressEvent(self,  event):
        if event.key() == Qt.Key_Minus:
            self.zoom -= .1
            glMatrixMode(GL_PROJECTION)
            glLoadIdentity()
            glOrtho(-self.corner*self.zoom, 
                    self.corner*self.zoom, 
                    -self.corner*self.zoom, 
                    self.corner*self.zoom , 
                    self.near, 
                    self.far)
            glMatrixMode(GL_MODELVIEW)

        if event.key() == Qt.Key_Plus:
            self.zoom += .1
            glMatrixMode(GL_PROJECTION) #// You had GL_MODELVIEW
            glLoadIdentity()
            glOrtho(-self.corner*self.zoom, 
                    self.corner*self.zoom,    
                    -self.corner*self.zoom, 
                    self.corner*self.zoom , 
                    self.near, 
                    self.far)
            glMatrixMode(GL_MODELVIEW)
        
        
        if event.key() ==Qt.Key_Z:
            #store all values
            self.zoom_mode = True
            
            glMatrixMode(GL_MODELVIEW)
            glLoadIdentity()
            font = QFont("Typewriter")
            self.renderText(0.,0.,0., "zooming mode", font)
            #little animation
            #a = -5
            #count = 0 
            if  self.yrot < 1444:
                while self.yrot < 1444:#and self.xrot < ref_rotx_:
                    #count += 1
                    self.xrot -=20
                    self.yrot +=20
                    #if self.zoom > a:
                    #    self.zoom-=1
                    self.updateGL()
                    
            elif self.yrot > 1444:
                while self.yrot <1444 :#and self.xrot < ref_rotx_:
                    #count += 1
                    self.xrot -=20
                    self.yrot -=20
                    #if self.zoom > a:
                    #    self.zoom-=1
                    self.updateGL()
            """
            count_ = 0
            tmp = self.xrot
            while  tmp < 1422:
                count_+=1
                tmp += 1
            b = count / count_
            count__ = 0
            """            
            while self.xrot < 1422:
                #count__+=1
                self.xrot+= 20
                #if self.zoom < 1: #and count__%b == 0:
                #    self.zoom+=1
                self.updateGL()


        if event.key() == Qt.Key_Up:
            self.trans_y +=10
        if event.key() == Qt.Key_Down:
            self.trans_y -=10
        if event.key() == Qt.Key_Left:
            self.trans_x -=10
        if event.key() == Qt.Key_Right:
            self.trans_x +=10
            
        self.updateGL()
        
    

    def mousePressEvent(self, event):
        self.lastpos = QPoint(event.pos())
#        modelview, projection =[], []
#        z =1
#        x, y =event.x(), event.y()
#        projection =glGetDoublev(GL_PROJECTION_MATRIX)
#        modelview= glGetDoublev(GL_MODELVIEW_MATRIX)
#        viewport=glGetIntegerv(GL_VIEWPORT)
#        glReadPixels( x, viewport[3]-y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, z )
#        objx, objy, objz =gluUnProject( x, viewport[3]-y, z, modelview, projection, viewport)
#        print objx, objy, objz
        
        
    def mouseMoveEvent(self, event):
        
        dx = event.x() - self.lastpos.x()
        dy = event.y() - self.lastpos.y()
        
        if not self.zoom_mode:  
            if event.buttons() == Qt.LeftButton:
                a = self.normalizeAngle(self.xrot + 8 * dy)
                b = self.normalizeAngle(self.yrot + 8 * dx)
                self.xrot= a#self.xrot + 8 * dy
                self.yrot= b#self.yrot + 8 * dx
                
            if event.buttons()== Qt.RightButton:
                self.setCursor(QCursor(Qt.ClosedHandCursor))
                self.trans_y -= dy/5
                self.trans_x += dx/5
                
            self.lastpos = QPoint(event.pos())
            self.updateGL()
        
            
            
    def drawQuad(self):
        '''change to accept arguments pass'''
        glColor( 0., 0., 1.)
        glLineWidth(4.0)
        pointer_x = self.lastpos.x()/200.#self.corner
        pointer_y = self.lastpos.y()/200.#/(self.corner)
        norm_dx = dx/200.#/(self.corner)
        norm_dy = dy/200.#/(self.corner)
        #print -self.corner, pointer_x, pointer_y, norm_dx, norm_dy
        glBegin(GL_QUADS)
        glVertex3f(-self.corner + pointer_x, 
                   -self.corner + pointer_y, 
                   -self.near+2*self.corner)
        
        glVertex3f(-self.corner + pointer_x+ norm_dx, 
                   -self.corner + pointer_y,
                   -self.near+2*self.corner)
                   
        glVertex3f(-self.corner + pointer_x+ norm_dx, 
                   -self.corner + pointer_y + norm_dy,
                   -self.near+2*self.corner)
        
        glVertex3f(-self.corner + pointer_x, 
                   -self.corner + pointer_y,
                   -self.near+2*self.corner)
        glEnd()
        self.lastpos = QPoint(event.pos())
        #redraw eachtime mouse 's moving
        self.updateGL()   
    
    
    
    
        
    def mouseReleaseEvent(self, event):
        self.setCursor(QCursor(Qt.ArrowCursor))
        if self.zoom_mode:
            self.computeSelection()
        self.zoom_mode = False
    
    
    def closeEvent(self, event):
        self.releaseKeyboard()
예제 #53
0
class GLWidget(QtOpenGL.QGLWidget):
    """
    This class renders something with OpenGL
    """
    def __init__(self, parent=None):
        """
        Constructor
        """
        self.__image_width = 250
        self.__image_height = 250

        self.__isMouseDown = False
        self.__zoomFactor = 1.0

        self.__scrollOffset = QPoint()

        if hasattr(QGLFormat, "setVersion"):
            # Modern OpenGL
            f = QGLFormat()
            f.setVersion(3, 3)
            f.setProfile(QGLFormat.CoreProfile)
            f.setSampleBuffers(True)
            c = QGLContext(f, None)

            QGLWidget.__init__(self, c, parent)
            print "Version is set to 3.3"
        else:
            QGLWidget.__init__(self, parent)

        #self.__svgItem = QtSvg.QGraphicsSvgItem("circle_star.svg")
        self.__mySvgTool = MySvgTool()

        self.__mySvgWriter = MySvgWriter()
        self.__mySvgWriter.DrawSomething()
        self.__myBufferPainter = MyBufferPainter()

    def initializeGL(self):

        glClearColor(0.5, 0.5, 0.5, 1.0)
        glEnable(GL_DEPTH_TEST)
        glEnable(GL_CULL_FACE)
        glEnable(GL_LINE_SMOOTH)
        glHint(GL_LINE_SMOOTH_HINT, GL_NICEST)

        self.__shaderProgram = QGLShaderProgram()
        if self.__shaderProgram.addShaderFromSourceFile(
                QGLShader.Vertex, "shader.vert"):
            print "Main - Vertex shader OK"
        if self.__shaderProgram.addShaderFromSourceFile(
                QGLShader.Fragment, "shader.frag"):
            print "Main - Fragment shader OK"
        self.__shaderProgram.link()

        self.__texCoordLocation = self.__shaderProgram.attributeLocation("uv")
        self.__vertexLocation = self.__shaderProgram.attributeLocation(
            "position")
        self.__colorLocation = self.__shaderProgram.attributeLocation("color")
        self.__use_color_location = self.__shaderProgram.uniformLocation(
            "use_color")
        self.__mvpMatrixLocation = self.__shaderProgram.uniformLocation(
            "mvpMatrix")

        # Returns -1 if name is not a valid attribute for this shader program.
        print "\n__texCoordLocation   :", self.__texCoordLocation, " ",   \
              "\n__vertexLocation     :", self.__vertexLocation, " ",     \
              "\n__colorLocation      :", self.__colorLocation, " ",      \
              "\n__use_color_location :", self.__use_color_location, " ", \
              "\n__mvpMatrixLocation  :", self.__mvpMatrixLocation

        self.__blurProgram = QGLShaderProgram()
        if self.__blurProgram.addShaderFromSourceFile(QGLShader.Vertex,
                                                      "shader.vert"):
            print "Gaussian blur - Vertex shader OK"

        # if I use shader.frag it's okay ???
        # if self.__blurProgram.addShaderFromSourceFile(QGLShader.Fragment, "gaussian_blur.frag") :
        if self.__blurProgram.addShaderFromSourceFile(QGLShader.Fragment,
                                                      "gaussian_blur.frag"):
            print "Gaussian blur - fragment shader OK"
        self.__blurProgram.link()

        self.__myBufferPainter.SetThings(self.__shaderProgram,
                                         self.__blurProgram)
        self.__myBufferPainter.initializeGL(
            self.bindTexture(QtGui.QPixmap("laughing_man.png")))
        self.__myBufferPainter.prepareFrameRect(self.__scrollOffset.x(),
                                                self.__scrollOffset.y(),
                                                self.width(), self.height(),
                                                self.__zoomFactor)
        """
        ### texture
        self.__ori_tex = self.bindTexture(QtGui.QPixmap("laughing_man.png"))

        vertexData = numpy.array([   0.0,   0.0, 0.0, 1.0,
                                     0.0, 250.0, 0.0, 1.0,
                                   250.0, 250.0, 0.0, 1.0,

                                     0.0,   0.0, 0.0, 1.0,
                                   250.0, 250.0, 0.0, 1.0,
                                   250.0,   0.0, 0.0, 1.0,

                                # uv
                                0, 1,
                                0, 0,
                                1, 0,

                                0, 1,
                                1, 0,
                                1, 1],
                                dtype = numpy.float32)

        colorData = numpy.array([1.0, 0.0, 0.0, 1.0,
                                 0.0, 0.0, 1.0, 1.0,
                                 0.0, 1.0, 0.0, 1.0,
                                 1.0, 0.0, 0.0, 1.0,
                                 0.0, 1.0, 0.0, 1.0,
                                 0.0, 0.0, 1.0, 1.0,],
                                 dtype = numpy.float32)

        ### create VAO
        self.__VAO = glGenVertexArrays(1)
        glBindVertexArray(self.__VAO)

        ### create a VBO for position and uv
        posVBO = glGenBuffers(1)
        glBindBuffer(GL_ARRAY_BUFFER, posVBO)
        glBufferData(GL_ARRAY_BUFFER, vertexData.nbytes, vertexData, GL_STATIC_DRAW)
        glEnableVertexAttribArray(self.__vertexLocation)
        glVertexAttribPointer(self.__vertexLocation, 4, GL_FLOAT, GL_FALSE, 0, None)

        glEnableVertexAttribArray(self.__texCoordLocation)
        glVertexAttribPointer(self.__texCoordLocation, 2, GL_FLOAT, GL_FALSE, 0, ctypes.c_void_p(96))

        ### create VBO for color
        colVBO = glGenBuffers(1)
        glBindBuffer(GL_ARRAY_BUFFER, colVBO)
        glBufferData(GL_ARRAY_BUFFER, colorData.nbytes, colorData, GL_STATIC_DRAW)
        glEnableVertexAttribArray(self.__colorLocation)
        glVertexAttribPointer(self.__colorLocation,    4, GL_FLOAT, GL_FALSE, 0, None)

        ### unbind vao and vbo
        glBindBuffer(GL_ARRAY_BUFFER, 0)
        glBindVertexArray(0)
        """

    def paintGL(self):
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        ### this doesn't work
        #frameBufferA.bind()
        #frameBufferA.release()

        glViewport(0, 0, self.width(), self.height())

        orthoMatrix = QMatrix4x4()
        orthoMatrix.ortho(0 + self.__scrollOffset.x(),
                          self.width() + self.__scrollOffset.x(),
                          self.height() + self.__scrollOffset.y(),
                          0 + self.__scrollOffset.y(), -100, 100)
        transformMatrix = QMatrix4x4()
        transformMatrix.setToIdentity()
        transformMatrix.scale(self.__zoomFactor)

        ### activate shader program
        #self.__shaderProgram.bind()
        ### set a shader attribute (0 means use texture, 1 means use color)
        #self.__shaderProgram.setUniformValue(self.__use_color_location, 0.0)

        ### feed the mpv matrix
        mpvMatrix = orthoMatrix * transformMatrix
        #self.__shaderProgram.setUniformValue(self.__mvpMatrixLocation, mpvMatrix)

        # Draw Something
        self.__myBufferPainter.paintGL(self.__scrollOffset.x(),
                                       self.__scrollOffset.y(), self.width(),
                                       self.height(), self.__zoomFactor,
                                       mpvMatrix)
        """
        ### DRAW SOMETHING
        ### bind texture
        glBindTexture(GL_TEXTURE_2D, self.__ori_tex)
        ### bind VAO
        glBindVertexArray(self.__VAO)
        ### draw triangle
        glDrawArrays(GL_TRIANGLES, 0, 18)
        """

        ### unbind
        #glBindVertexArray(0)
        #glUseProgram(0)
        #self.__shaderProgram.release()

    def SetSomething(self):
        pass

    def DrawSomething(self):
        pass

    def ZoomIn(self):
        self.__zoomFactor += 0.1

    def ZoomOut(self):
        self.__zoomFactor -= 0.1
        if (self.__zoomFactor < 0.1):
            self.__zoomFactor = 0.1

    """
    Get / Set
    """

    def GetImageSize(self):
        """
        Get the size of the canvas / image
        """
        return QSize(self.__image_width, self.__image_height)

    def SetZoomFactor(self, val):
        """
        Set the value of magnification
        """
        self.__zoomFactor = val

    def GetZoomFactor(self):
        """
        Obtain the value of the magnification
        """
        return self.__zoomFactor

    def SetMouseDown(self, val):
        """
        Set the value of mouse down
        """
        self.__isMouseDown = val

    def SetHorizontalScroll(self, val):
        """
        Set horizontal scroll value
        """
        self.__scrollOffset.setX(val)

    def SetVerticalScroll(self, val):
        """
        Set vertical scroll value
        """
        self.__scrollOffset.setY(val)
예제 #54
0
class MapSwipeTool(QgsMapTool):
    def __init__(self, iface):
        canvas = iface.mapCanvas()
        super(MapSwipeTool, self).__init__(canvas)
        self.view = iface.layerTreeView()
        self.msgBar = iface.messageBar()
        self.swipe = SwipeMap(canvas)
        self.checkDirection = self.hasSwipe = self.disabledSwipe = None
        self.firstPoint = QPoint()
        self.cursorV = QCursor(Qt.SplitVCursor)
        self.cursorH = QCursor(Qt.SplitHCursor)

    def tr(self, sourceText):
        context = 'MapSwipeTool'
        return QCoreApplication.translate(context, sourceText)

    def activate(self):
        self.canvas().setCursor(QCursor(Qt.CrossCursor))
        self._connect()
        self.hasSwipe = False
        self.disabledSwipe = False
        self.setLayersSwipe(None, None)
        self.checkLayer()

    def canvasPressEvent(self, e):
        if self.checkLayer():
            self.hasSwipe = True
            self.firstPoint.setX(e.x())
            self.firstPoint.setY(e.y())
            self.checkDirection = True

    def canvasReleaseEvent(self, e):
        self.hasSwipe = False
        self.canvas().setCursor(QCursor(Qt.CrossCursor))

    def canvasMoveEvent(self, e):
        if self.hasSwipe:
            if self.checkDirection:
                dX = abs(e.x() - self.firstPoint.x())
                dY = abs(e.y() - self.firstPoint.y())
                isVertical = dX > dY
                self.swipe.setIsVertical(isVertical)
                self.checkDirection = False
                self.canvas().setCursor(
                    self.cursorH if isVertical else self.cursorV)

            self.swipe.setLength(e.x(), e.y())

    def _connect(self, isConnect=True):
        signal_slot = ({
            'signal': self.canvas().mapCanvasRefreshed,
            'slot': self.swipe.setMap
        }, {
            'signal': self.view.selectionModel().selectionChanged,
            'slot': self.setLayersSwipe
        }, {
            'signal': QgsMapLayerRegistry.instance().removeAll,
            'slot': self.disable
        })
        if isConnect:
            for item in signal_slot:
                item['signal'].connect(item['slot'])
        else:
            for item in signal_slot:
                item['signal'].disconnect(item['slot'])

    def checkLayer(self):
        if len(self.swipe.layers) == 0:
            msg = self.tr(
                "Select active Layer or Group(with layers) in legend.")
            self.msgBar.clearWidgets()
            self.msgBar.pushMessage("MapSwipeTool", msg, QgsMessageBar.WARNING,
                                    4)
            return False
        else:
            return True

    @pyqtSlot("QModelIndex, QModelIndex")
    def setLayersSwipe(self, selected=None, deselected=None):
        if self.disabledSwipe:
            return

        ids = msg = None
        node = self.view.currentNode()
        if isinstance(node, QgsLayerTreeLayer):
            layer = node.layer()
            ids = [layer.id()]
            msg = self.tr("Active layer is '%s'.") % layer.name()
        else:
            group = self.view.currentGroupNode()
            if group.parent() is None:  # Root
                return
            ids = group.findLayerIds()
            msg = self.tr("Active group is '%s'.") % group.name()

        self.swipe.clear()
        self.swipe.setLayersId(ids)
        self.swipe.setMap()

        if self.checkLayer():
            self.msgBar.clearWidgets()
            self.msgBar.pushMessage("MapSwipeTool", msg, QgsMessageBar.INFO, 2)

    @pyqtSlot()
    def disable(self):
        self.swipe.clear()
        self.hasSwipe = False
        self.disabledSwipe = True

    def deactivate(self):
        super(MapSwipeTool, self).deactivate()
        self.deactivated.emit()
        self.swipe.clear()
        self._connect(False)
예제 #55
0
class ContainerWidget(QWidget):
    def __init__(self, container, parent: QWidget=None):
        QWidget.__init__(self, parent)
        self.setWindowTitle('Container')
        self.__b_widgets = []
        self.__container = container
        self.__translation = QPoint(0, 0)
        self.setMouseTracking(True)
        self.setFocusPolicy(Qt.ClickFocus)
        self.setFocus()
        for b in container.blocks:
            w = b.get_widget(self)
            self.__b_widgets.append(w)
        pal = QPalette(self.palette())
        pal.setColor(QPalette.Background, QColor(55, 50, 47))
        self.setAutoFillBackground(True)
        self.setPalette(pal)
        container.block_added.connect(self.add_block)
        container.block_removed.connect(self.remove_block)
        self.__moving = False
        self.__origin = QPoint()

    def paintEvent(self, e: QPaintEvent):
        if e.isAccepted() and e.accept():
            QWidget.paintEvent(self, e)
            p = QPainter(self)
            p.setRenderHint(QPainter.Antialiasing)
            for l in self.__container.lines:
                l.paint(p)

    def add_block(self, b):
        w = b.get_widget(self)
        self.__b_widgets.append(w)

    def __get_b_widget(self, b):
        for w in self.__b_widgets:
            if w.block() == b:
                return w
        return None

    def remove_block(self, b):
        w = self.__get_b_widget(b)
        if b is not None:
            self.__b_widgets.remove(b)
            w.deleteLater()

    def mousePressEvent(self, e: QMouseEvent):
        BlockManager.deselect_all()
        if e.button() == Qt.LeftButton:
            self.__moving = True
            self.__origin = e.pos()
            self.setCursor(Qt.DragMoveCursor)
        elif e.button() == Qt.RightButton:
            self.show_popup(e.pos())

    def mouseDoubleClickEvent(self, e: QMouseEvent):
        BlockManager.deselect_all()
        if e.button() == Qt.LeftButton:
            self.__moving = False
            self.__translation = QPoint()
            self.translate(0, 0)

    def show_popup(self, pos):
        print('here')

    def mouseMoveEvent(self, e: QMouseEvent):
        if self.__moving:
            dx = e.x() - self.__origin.x()
            dy = e.y() - self.__origin.y()
            self.__origin = e.pos()
            self.translate(dx, dy)

    def mouseReleaseEvent(self, e):
        self.__moving = False
        self.setCursor(Qt.ArrowCursor)

    def translate(self, dx, dy):
        p = QPoint(self.__translation.x() + dx, self.__translation.y() + dy)
        self.__translation = p
        for b in self.__b_widgets:
            b.translate(p)
        self.repaint()
예제 #56
0
class CImprovedButton(QToolButton):
    def __init__(self, parent=None):
        QToolButton.__init__(self, parent)

        #TESTO ALTERNATIVO
        #Spesso se il pulsante ha icona troppo grossa e quando per ragioni di spazio o altro non si può spostare
        #o ridimensionare il pulsante stesso, la label ha posizioni assurde e schifose. Aggiungerne una "+ controllabile"
        #è l'unico modo..
        self.__fixed_label = QLabel("alternative label", self)
        self.__fixed_label.move(0, self.geometry().height() - 35)
        self.__fixed_label.resize(self.geometry().width(),
                                  self.__fixed_label.geometry().height())
        self.__fixed_label.setAlignment(QtCore.Qt.AlignHCenter
                                        | QtCore.Qt.AlignVCenter)
        self.__font = QtGui.QFont("Arial", 10)
        self.__fixed_label.setFont(self.__font)
        self.__fixed_label.show()

        #INDICATORE STILE iOS
        self.__indicator = QLabel("0", self)
        self.__indicator.setStyleSheet(
            "border-image: url(':/images/backgrounds/indicator.png'); padding-right:1px; color: white;"
        )
        self.__indicator.geometry().setWidth(25)
        self.__indicator.geometry().setHeight(20)
        self.__indicator.setAlignment(QtCore.Qt.AlignHCenter
                                      | QtCore.Qt.AlignVCenter)
        self.__indicator.setVisible(False)
        self.setIndicatorPos(QPoint(self.width() - self.__indicator.width(),
                                    0))  #default top-right corner
        #Quando il pulsante viene ridimensionato (designer o meno) devo anche sistemare la label di conseguenza
        self.resizeEvent = self.__onResize
        self.__indicator.resizeEvent = self.__on_indicator_Resize

        self.setToolButtonStyle(QtCore.Qt.ToolButtonIconOnly)

        self.clicked.connect(self.stopAllAnimations)

        #BLINK
        self.__blink_timer = QTimer(parent)
        self.__blink_timer.timeout.connect(self.__on_blink_timer)
        self.__blink_timer_interval = 1000

        #FADING
        self.__opacity_effect = QGraphicsOpacityEffect()
        self.__fading_timer = QTimer(parent)
        self.__fading_timer.timeout.connect(self.__on_fading_timer)
        self.__FADE_TYPE = Enum("IN", "OUT")
        self.__fade_time = 20
        self.__opacity = 1.0
        self.__opacity_fading_coefficient = 0.02
        self.__selected_fade_type = self.__FADE_TYPE.IN

        # ANIMAZIONI GROW
        self.__animationGrow = QPropertyAnimation(self, "iconSize", self)
        self.__animationGrow.setDuration(1000)
        self.__animationGrow.setEasingCurve(QEasingCurve.Linear)
        self.__animationGrow.finished.connect(self.__on_growed)

        self.__animationShrink = QPropertyAnimation(self, "iconSize", self)
        self.__animationShrink.setDuration(1000)
        self.__animationShrink.setEasingCurve(QEasingCurve.Linear)
        self.__animationShrink.finished.connect(self.__on_shrinked)

        self.__defaultIconDimension = 60
        self.__iconGrowsBy = 40
        self.__growing = False

        # ANIMAZIONI BOUNCE
        self.__animationUp = QPropertyAnimation(self, "pos", self)
        self.__animationUp.setDuration(200)
        self.__animationUp.setEasingCurve(QEasingCurve.Linear)
        self.__animationUp.finished.connect(self.__on_top_reached)

        self.__animationBounce = QPropertyAnimation(self, "pos", self)
        self.__animationBounce.setDuration(1000)
        self.__animationBounce.setEasingCurve(QEasingCurve.OutBounce)
        self.__animationBounce.finished.connect(self.__on_bounce_finished)

        self.__bouncing = False
        self.__startPos = QPoint(self.pos().x(), self.pos().y())

        #PIXMAP & MASCHERA
        self.__pmap = QPixmap(self.size())
        self.__pmap_fname = ""
        self.__show_mask_preview = False

    def setDefaultIconSize(self, value):
        """ Sets default icon size when growing stops.
        @param value: size (both width and height)
        @type value: int
        """
        self.__defaultIconDimension = value

    def getDefaultIconSize(self):
        return self.__defaultIconDimension

    defaultIconSize = QtCore.pyqtProperty("int", getDefaultIconSize,
                                          setDefaultIconSize)

    def setFixetTextVisibility(self, bool):
        """ Sets if fixed text is visible or not.
        @param bool: visible or not
        @type bool: bool
        """
        self.__fixed_label.setVisible(bool)

    def getFixetTextVisibility(self):
        return self.__fixed_label.isVisible()

    fixetTextVisibility = QtCore.pyqtProperty("bool",
                                              fget=getFixetTextVisibility,
                                              fset=setFixetTextVisibility)

    def setFixedText(self, txt):
        """ Sets text on the button.
        @param txt: text
        @type txt: string
        """
        self.__fixed_label.setText(txt)

    def getFixedText(self):
        return self.__fixed_label.text()

    fixedText = QtCore.pyqtProperty("QString", getFixedText, setFixedText)

    def setFixedTextPos(self, qpoint):
        """ Sets text position in the button.
        @param qpoint: Position RELATIVE. 0,0 is top left corner of the button.
        @type qpoint: QPoint
        """
        self.__fixed_label.move(qpoint)

    def getFixedTextPos(self):
        return self.__fixed_label.pos()

    fixedTextPos = QtCore.pyqtProperty("QPoint", getFixedTextPos,
                                       setFixedTextPos)

    def setFixedTextFont(self, font):
        """ Sets text font.
        @param font: Font for fixed text.
        @type font: QFont
        """
        self.__font = font
        self.__fixed_label.setFont(self.__font)

    def getFixedTextFont(self):
        return self.__font

    fixedTextFont = QtCore.pyqtProperty("QFont", getFixedTextFont,
                                        setFixedTextFont)

    #FUNZIONI INDICATORE
    def setIndicatorVisibility(self, bool):
        """ Sets if indicator is visible or not.
        @param bool: visible or not
        @type bool: bool
        """
        self.__indicator.setVisible(bool)

    def getIndicatorVisibility(self):
        return self.__indicator.isVisible()

    indicatorVisibility = QtCore.pyqtProperty("bool",
                                              fget=getIndicatorVisibility,
                                              fset=setIndicatorVisibility)

    def setIndicatorPos(self, qpoint):
        """ Sets indicator position in the button.
        @param qpoint: Position RELATIVE. 0,0 is top left corner of the button.
        @type qpoint: QPoint
        """
        self.__indicator.move(qpoint)

    def getIndicatorPos(self):
        return self.__indicator.pos()

    indicatorPos = QtCore.pyqtProperty("QPoint", getIndicatorPos,
                                       setIndicatorPos)

    def setIndicatorSize(self, size):
        """ Sets indicator size.
        @param size: Size
        @type size: QSize
        """
        self.__indicator.resize(size)

    def getIndicatorSize(self):
        return self.__indicator.size()

    indicatorSize = QtCore.pyqtProperty("QSize", getIndicatorSize,
                                        setIndicatorSize)

    def setIndicatorFont(self, font):
        """ Sets indicator text font.
        @param font: Font for indicator text.
        @type font: QFont
        """
        self.__indicator.setFont(font)

    def getIndicatorFont(self):
        return self.__indicator.font()

    indicatorFont = QtCore.pyqtProperty("QFont", getIndicatorFont,
                                        setIndicatorFont)

    ## FUNZIONI PER BLINK
    def __on_blink_timer(self):
        self.setVisible(not (self.isVisible()))

    def setBlinking(self, blink):
        """ Sets if the button have to blink or not.
        @param blink: blinking or not
        @type blink: bool
        """
        if blink:
            self.__blink_timer.setInterval(self.__blink_timer_interval)
            self.__blink_timer.start()
        else:
            self.__blink_timer.stop()
            self.setVisible(True)

    def setBlinkInterval(self, value):
        """ Sets blink interval.
        @param blink: blink interval (msec)
        @type blink: int
        """
        self.__blink_timer_interval = value

    def getBlinkInterval(self):
        return self.__blink_timer_interval

    blinkInterval = QtCore.pyqtProperty("int", getBlinkInterval,
                                        setBlinkInterval)

    ##FUNZIONI PER FADING
    def fadeIn(self):
        """
         Button fades in from completely invisible to completely visible.
        """
        self.__opacity = 0.0
        self.__selected_fade_type = self.__FADE_TYPE.IN
        self.__fading_timer.start(self.__fade_time)

    def fadeOut(self):
        """
         Button fades out from completely visible to completely invisible.
        """
        self.__selected_fade_type = self.__FADE_TYPE.OUT
        self.__fading_timer.start(self.__fade_time)

    def setFadeTime(self, value):
        """ Sets fading time. Everytime interval is reached, alpha is increased (or decreased) by __opacity_fading_coefficient.
        @param value: fade time (msec)
        @type value: int
        """
        self.__fade_time = value

    def getFadeTime(self):
        return self.__fade_time

    fadeInterval = QtCore.pyqtProperty("int", getFadeTime, setFadeTime)

    def setFadeCoefficient(self, value):
        """ Sets fading coefficient. Alpha is increased (or decreased) by this value.
        @param value: coefficient (min 0.0 - max 1.0)
        @type value: float
        """
        self.__opacity_fading_coefficient = value

    def getFadeCoefficient(self):
        return self.__opacity_fading_coefficient

    fadeCoefficient = QtCore.pyqtProperty("double", getFadeCoefficient,
                                          setFadeCoefficient)

    def __on_fading_timer(self):
        if self.__selected_fade_type == self.__FADE_TYPE.OUT:
            if self.__opacity > 0:
                self.__opacity -= self.__opacity_fading_coefficient
                self.__opacity_effect.setOpacity(self.__opacity)
                self.setGraphicsEffect(self.__opacity_effect)
            else:
                self.__fading_timer.stop()

        if self.__selected_fade_type == self.__FADE_TYPE.IN:
            if self.__opacity <= 1.0:
                self.__opacity += self.__opacity_fading_coefficient
                self.__opacity_effect.setOpacity(self.__opacity)
                self.setGraphicsEffect(self.__opacity_effect)
            else:
                self.__fading_timer.stop()

    # FUNZIONI PER GROW\SHRINK
    def __on_growed(self):
        self.__animationShrink.setStartValue(
            QSize(self.iconSize().width(),
                  self.iconSize().height()))
        self.__animationShrink.setEndValue(
            QSize(self.iconSize().width() - self.__iconGrowsBy,
                  self.iconSize().height() - self.__iconGrowsBy))
        self.__animationShrink.start()

    def __on_shrinked(self):
        self.__animationGrow.setStartValue(
            QSize(self.iconSize().width(),
                  self.iconSize().height()))
        self.__animationGrow.setEndValue(
            QSize(self.iconSize().width() + self.__iconGrowsBy,
                  self.iconSize().height() + self.__iconGrowsBy))
        self.__animationGrow.start()

    def startGrow(self):
        """
         Button ICON starts to grow and shrink to standard value when maximum size (configured) is reached
        """
        if self.__growing:
            return
        self.__animationGrow.setStartValue(
            QSize(self.iconSize().width(),
                  self.iconSize().height()))
        self.__animationGrow.setEndValue(
            QSize(self.iconSize().width() + self.__iconGrowsBy,
                  self.iconSize().height() + self.__iconGrowsBy))
        self.__animationGrow.start()
        self.__growing = True

    def stopGrow(self):
        if self.__animationGrow.startValue().toSize() != QSize(
                0,
                0) and self.__animationShrink.startValue().toSize() != QPoint(
                    0, 0):
            self.__animationGrow.stop()
            self.__animationShrink.stop()
            self.setIconSize(
                QSize(self.__defaultIconDimension,
                      self.__defaultIconDimension))
            self.__growing = False

    #FUNZIONI PER BOUNCE
    def startBounce(self):
        """
         Button starts to bounce requiring attention.
        """
        if self.__bouncing:
            return
        self.__startPos = QPoint(self.pos().x(), self.pos().y())
        self.__animationUp.setStartValue(
            QPoint(self.__startPos.x(), self.__startPos.y()))
        self.__animationUp.setEndValue(
            QPoint(self.__startPos.x(),
                   self.__startPos.y() - self.geometry().height()))
        self.__animationUp.start()
        self.__bouncing = True

    def stopBounce(self):
        if self.__animationUp.startValue().toPoint() != QPoint(
                0,
                0) and self.__animationBounce.startValue().toPoint() != QPoint(
                    0, 0):
            self.__animationBounce.stop()
            self.__animationUp.stop()
            self.setGeometry(self.__startPos.x(), self.__startPos.y(),
                             self.geometry().width(),
                             self.geometry().height())
            self.__bouncing = False

    def __on_top_reached(self):
        self.__animationBounce.setStartValue(
            QPoint(self.pos().x(),
                   self.pos().y()))
        self.__animationBounce.setEndValue(
            QPoint(self.__startPos.x(), self.__startPos.y()))
        self.__animationBounce.start()

    def __on_bounce_finished(self):
        self.__animationUp.start()

    def stopAllAnimations(self):
        self.stopBounce()
        self.stopGrow()

    #FUNZIONI PER PIXMAP & MASCHERA
    def setPixmapFile(self, image_file):
        self.__pmap = image_file
        self.__pmap.scaled(self.size())
        #NB: Il pixmap deve essere BIANCO e NERO. Con heuristicMask il primo pixel in alto a sinistra (0,0) viene
        #usato per decidere il colore trasparente, tutto il resto è visibile.

    def getPixmapFile(self):
        return self.__pmap

    pixmapFile = QtCore.pyqtProperty("QPixmap", getPixmapFile, setPixmapFile)

    def applyMask(self, bool):
        self.__show_mask_preview = bool
        if bool:
            self.setMask(
                QBitmap(self.__pmap.createHeuristicMask().scaled(self.size())))
        else:
            self.setMask(QBitmap())

    def getMask(self):
        return self.__show_mask_preview

    appliedMask = QtCore.pyqtProperty("bool", fget=getMask, fset=applyMask)

    def __onResize(self, event):
        self.__fixed_label.move(0, self.geometry().height() - 35)
        self.__fixed_label.resize(self.geometry().width(),
                                  self.__fixed_label.geometry().height())
        self.setIndicatorPos(QPoint(self.width() - self.__indicator.width(),
                                    0))
        self.__pmap.scaled(self.size())
        if self.__show_mask_preview:
            self.setMask(
                QBitmap(self.__pmap.createHeuristicMask().scaled(self.size())))

    def __on_indicator_Resize(self, event):
        self.setIndicatorPos(QPoint(self.width() - self.__indicator.width(),
                                    0))
예제 #57
0
class OGLViewer(QGLWidget):
    '''
    OpenGL viewer class
    '''
    def __init__(self, parent=None):
        '''
        Viewer's Constructor
        '''
        frmt = QGLFormat()
        frmt.setSampleBuffers(True)

        super(OGLViewer, self).__init__(frmt, parent)

        #self.setMouseTracking (True)
        self.__mouse = QCursor()
        self.setCursor(Qt.OpenHandCursor)
        self.setFocusPolicy(Qt.ClickFocus)

        self.__Ctrl_or_Meta_key_pressed = False
        self.__Alt_key_pressed = False

        self.__w = 720
        self.__h = 450

        self._init_camera_vars()
        self._init_objec_vars()

        # matrix changed signal. The signal's payload is the matrix itself.
        self.__GLMatrixChanged = SIGNAL("MatrixChanged (PyQt_PyObject)")

        self.__compo_light_pos = QVector3D(.3, .2, .1)
        self.__AmbientMaterial = QVector3D(.2, .2, .2)

    def _init_camera_vars(self):
        '''
        static method. It initializes the math variables.
        '''
        self.__compo_mtools = MathTools.Tools()

        self.__curr_angles = QPoint(0, 0)
        self.__last_pos = QPoint(0, 0)
        self.__delta = QPoint(0, 0)
        self.__orig = QVector3D(0.0, 0.0, 0.0)
        self.__cam_dist = 0.0
        self.__z_near = 0.1
        self.__z_far = 2000.0
        self.__fovy = 45.0
        self.__angle = self.__compo_mtools.getAngle(self.__fovy)

        self.__norm_mtx = QMatrix4x4()  #(GLdouble * 16)()
        self.__norm_mtx.setToIdentity()

        self.__mtx = QMatrix4x4()  #(GLdouble * 16)()
        self.__mtx.setToIdentity()

        self.__aspect_ratio = float(self.__w) / float(self.__h)

        self.__camera_list = []

    def _init_objec_vars(self):

        self.__arrows_list = []
        self.__arrow_len = 2.0

        self.__lines_list = []
        self.__l_param = 200.0

        self.__intersections_list = []

        self.__poly_model = None
        self.__poly_list = []  # by polygon I mean triangle.

    def initializeGL(self):
        '''
        usual OpenGL method
        '''
        glClearColor(0.93, 0.93, 0.93, 1.0)
        glClearDepth(1.0)

        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluPerspective(self.__fovy,
                       float(self.__w) / float(self.__h), self.__z_near,
                       self.__z_far)

        self.refreshMatrices()

    def resizeGL(self, w, h):
        '''
        usual OpenGL method
        '''
        self.__w = w
        self.__h = h

        self.__aspect_ratio = float(self.__w) / float(self.__h)

        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()
        gluPerspective(self.__fovy, self.__aspect_ratio, self.__z_near,
                       self.__z_far)
        glViewport(0, 0, self.__w, self.__h)

        gluLookAt(
            0,
            0,
            -1,  # CameraPos
            0,
            0,
            0,  # CameraLookAt
            0,
            1,
            0)  # CameraUp

    def paintGL(self):
        '''
        usual OpenGL method
        '''
        self.__delta = QPoint(0, 0)

        q = self.__mouse.pos()
        if self.__Ctrl_or_Meta_key_pressed ^ self.__Alt_key_pressed:  #  xor (strictly one or the other)

            if self.__Ctrl_or_Meta_key_pressed:

                # rotation

                self.__delta = q - self.__last_pos

            else:

                # translation

                # transform mouse deltas and camera's local axes so that it'll look like as if the camera gets
                # translated based on the local axes x and y. What really happens is that the origin shifts along.
                # The resulting behaviour reminds of the Maya Camera Track Tool.
                d_x = q.x() - self.__last_pos.x()
                d_y = q.y() - self.__last_pos.y()

                zero = 0.0  #GLdouble (0.0)
                m_ref = self.__mtx.data(
                )  # retrieves the 16 items in this matrix and copies them to values in row-major order.
                vec_x = -m_ref[0] * d_x + m_ref[4] * d_y + zero * m_ref[8]
                vec_y = -m_ref[1] * d_x + m_ref[5] * d_y + zero * m_ref[9]
                vec_z = -m_ref[2] * d_x + m_ref[6] * d_y + zero * m_ref[10]

                mult = 0.03
                self.__orig.setX(self.__orig.x() + mult * vec_x)
                self.__orig.setY(self.__orig.y() + mult * vec_y)
                self.__orig.setZ(self.__orig.z() + mult * vec_z)

            # fire signal after done changing the model matrix.
            self.emit(self.__GLMatrixChanged, self.__mtx)

        self.__last_pos = q

        self.__curr_angles += self.__delta

        if glCheckFramebufferStatus(
                GL_FRAMEBUFFER) == 36053:  # 36053 = GL_FRAMEBUFFER_COMPLETE

            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
            glLoadIdentity()

            # Set the camera orientation :
            glMatrixMode(GL_MODELVIEW)
            glLoadIdentity()

            gluLookAt(
                self.__orig.x(),
                self.__orig.y(),
                self.__orig.z() - 40,  # CameraPos
                self.__orig.x(),
                self.__orig.y(),
                self.__orig.z(),  # CameraLookAt
                0.0,
                1.0,
                1.0)  # CameraUp

            # Rotate and move camera forward or backward.
            glTranslatef(0, 0, -self.__cam_dist)
            glTranslatef(self.__orig.x(), self.__orig.y(),
                         self.__orig.z())  # rotation around current origin.
            glRotatef(-30 - self.__curr_angles.y() * 0.15, 1, 0,
                      0)  # rotate around axis x.
            glRotatef(-30 + self.__curr_angles.x() * 0.1, 0, 1,
                      0)  # rotate around axis y.
            glTranslatef(-self.__orig.x(), -self.__orig.y(),
                         -self.__orig.z())  # rotation around current origin.

            self.refreshMatrices()

            self.displayObjects()
            self.displayArrows()
            self.displayLines()
            self.displayIntersections()

            self.drawGrid()
            self.drawFixedOriginAxes()
            self.drawCurrentOriginAxes()

            self.displayCamera()

    def refreshMatrices(self):

        tmp = glGetDoublev(
            GL_MODELVIEW_MATRIX
        )  # this returns a list of lists BUT QMatrix4x4 accepts a list of floats.
        tmp_qmtx = QMatrix4x4([
            item for sublist in tmp for item in sublist
        ])  # flattens the list of lists out in a single list.

        self.__mtx = tmp_qmtx

        tmp_tuple = tmp_qmtx.inverted()
        self.__norm_mtx = (tmp_tuple[0]).transposed(
        )  # assumption : matrix always invertible so I'm not going to check the boolean tmp_tuple[1].

    def run(self):
        '''
        method refreshed cyclically by a timer when it is in focus.
        When out of focus, the timer stops calling it and so freezing
        the image to what it looked like when last used.
        '''
        self.paintGL()  # render actual frame
        self.swapBuffers()

    def addCamera(self):

        self.__compo_mtools.setNormalMatrix(self.__norm_mtx)

        angle_by_aspect_ratio = self.__angle * self.__aspect_ratio
        inv_w = 1.0 / self.__w
        inv_h = 1.0 / self.__h
        m = -1.0

        w_param = (inv_w - 1) * angle_by_aspect_ratio
        h_param = (1 - inv_h) * self.__angle

        # compute center + corners
        cam_centre = self.__compo_mtools.cameraToWorldTransform(0, 0, 0)
        top_left = self.__compo_mtools.cameraToWorldTransform(
            w_param, h_param, m)
        top_right = self.__compo_mtools.cameraToWorldTransform(
            w_param, -h_param, m)
        bottom_left = self.__compo_mtools.cameraToWorldTransform(
            -w_param, h_param, m)
        bottom_right = self.__compo_mtools.cameraToWorldTransform(
            -w_param, -h_param, m)

        self.__camera_list.append(
            [cam_centre, top_left, top_right, bottom_left, bottom_right])

    # - - -  viewer graphics  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    def displayCamera(self):

        glLineWidth(1.0)
        for cam in self.__camera_list:

            cc = cam[0]
            tl = cam[1]
            tr = cam[2]
            bl = cam[3]
            br = cam[4]

            glBegin(GL_LINES)
            glColor3f(0.6, 0.6, 0.6)
            glVertex3f(cc[0], cc[1], cc[2])
            glVertex3f(tl[0], tl[1], tl[2])
            glVertex3f(cc[0], cc[1], cc[2])
            glVertex3f(tr[0], tr[1], tr[2])
            glVertex3f(cc[0], cc[1], cc[2])
            glVertex3f(br[0], br[1], br[2])
            glVertex3f(cc[0], cc[1], cc[2])
            glVertex3f(bl[0], bl[1], bl[2])
            glVertex3f(tl[0], tl[1], tl[2])
            glVertex3f(tr[0], tr[1], tr[2])
            glVertex3f(tr[0], tr[1], tr[2])
            glVertex3f(br[0], br[1], br[2])
            glVertex3f(br[0], br[1], br[2])
            glVertex3f(bl[0], bl[1], bl[2])
            glVertex3f(bl[0], bl[1], bl[2])
            glVertex3f(tl[0], tl[1], tl[2])
            glEnd()

    def displayObjects(self):

        glClear(GL_COLOR_BUFFER_BIT)

        glEnable(GL_DEPTH_TEST)
        glDepthMask(GL_TRUE)
        #glEnable (GL_CULL_FACE)

        for poly in self.__poly_list:

            p0 = poly[0]
            p1 = poly[1]
            p2 = poly[2]

            glBegin(GL_TRIANGLES)
            col = .4 + 0.5 * QVector3D.dotProduct(poly[3],
                                                  self.__compo_light_pos)
            glColor3f(col, col, col)
            glVertex3f(p0.x(), p0.y(), p0.z())
            glVertex3f(p1.x(), p1.y(), p1.z())
            glVertex3f(p2.x(), p2.y(), p2.z())
            glEnd()

    def displayIntersections(self):

        for intsect in self.__intersections_list:

            p = intsect[0]
            c = intsect[1]
            # Draw a translated solid sphere
            glPushMatrix()
            glTranslatef(p[0], p[1], p[2])
            glColor3f(c[0], c[1], c[2])
            glutSolidSphere(GLdouble(0.03), 9, 9)
            glPopMatrix()

    def displayLines(self):

        glLineWidth(1.0)
        for line in self.__lines_list:

            p = line[0]  # line initial position  (3-list)
            d = line[1]  # line direction (3-list)
            t = str(line[2])  # line type (o:open line, p:point-to-point line)

            glBegin(GL_LINES)
            glColor3ub(255, 255, 255)
            glVertex3f(p[0], p[1], p[2])

            # open line
            if t == 'o':
                glVertex3f(self.__l_param * d[0] + p[0],
                           self.__l_param * d[1] + p[1],
                           self.__l_param * d[2] + p[2])
            # point-to-point line
            elif t == 'p':
                glVertex3f(d[0], d[1], d[2])

            else:
                raise sys.exit('*** Unrecognised line type : "' + t + '"')

            glEnd()

    def displayArrows(self):

        for arrow in self.__arrows_list:

            p = arrow[0]  # arrow position  (3-list)
            d = arrow[1]  # arrow direction (3-list)
            t = str(arrow[2])  # arrow type (i:inwards, o:outwards)

            # scale parameters
            scale_x = 0.01
            scale_y = scale_x
            scale_z = 0.5
            t_z = scale_z * self.__arrow_len

            # arrow type
            if t == 'o': add_t = 0
            elif t == 'i': add_t = -t_z * 2.5
            else: raise sys.exit('*** Unrecognised arrow type : "' + t + '"')

            glPushMatrix()

            # arrow shaft
            glColor3f(0.5, 0.5, 0)
            glTranslatef(p[0], p[1], p[2])
            angles_from_orient = self.__compo_mtools.alignZAxisToVector(
                d[0], d[1], d[2])
            glRotatef(180, 0, 0, 1)
            glRotatef(angles_from_orient[1], 0, 1, 0)
            glRotatef(angles_from_orient[0], 1, 0, 0)
            glScale(scale_x, scale_y, scale_z)
            glTranslatef(0, 0, t_z + add_t)
            glutSolidCube(GLdouble(self.__arrow_len))

            # arrow head
            # REMEMBER ! The head's transformations are built on top of the arrow shaft's and are NOT independent !
            # The reason for doing that is that the user can change the scale of the arrow from UI's slider.
            glColor3f(0.6, 0.6, 0)
            glTranslatef(0, 0, t_z)
            glutSolidCone(GLdouble(t_z * 5), GLdouble(t_z * 0.5), GLint(6),
                          GLint(2))

            glPopMatrix()

    def drawGrid(self):

        glLineWidth(1.0)
        for i in range(-10, 11):
            glBegin(GL_LINES)
            glColor3ub(185, 185, 185)
            glVertex3f(-10, 0, i)
            glVertex3f(10, 0, i)
            glVertex3f(i, 0, -10)
            glVertex3f(i, 0, 10)
            glEnd()

    def drawFixedOriginAxes(self):

        glLineWidth(2.0)
        glBegin(GL_LINES)
        glColor3ub(250, 0, 0)
        glVertex3f(0, 0, 0)
        glVertex3f(0, 0, 5)
        glColor3ub(255, 150, 150)
        glVertex3f(0, 0, 5)
        glVertex3f(0, 0, 10)
        glEnd()
        glBegin(GL_LINES)
        glColor3ub(0, 250, 0)
        glVertex3f(0, 0, 0)
        glVertex3f(0, 5, 0)
        glColor3ub(150, 255, 150)
        glVertex3f(0, 5, 0)
        glVertex3f(0, 10, 0)
        glEnd()
        glBegin(GL_LINES)
        glColor3ub(0, 0, 250)
        glVertex3f(0, 0, 0)
        glVertex3f(5, 0, 0)
        glColor3ub(150, 150, 255)
        glVertex3f(5, 0, 0)
        glVertex3f(10, 0, 0)
        glEnd()

    def drawCurrentOriginAxes(self):

        glPointSize(6.0)
        glBegin(GL_POINTS)
        glColor3f(0.0, 1.0, 1.0)
        glVertex3f(self.__orig.x(), self.__orig.y(), self.__orig.z())
        glEnd()

        glBegin(GL_LINES)
        glColor3ub(250, 0, 0)
        glVertex3f(self.__orig.x(), self.__orig.y(), self.__orig.z())
        glVertex3f(self.__orig.x(), self.__orig.y(),
                   self.__orig.z() + 5)
        glEnd()
        glBegin(GL_LINES)
        glColor3ub(0, 250, 0)
        glVertex3f(self.__orig.x(), self.__orig.y(), self.__orig.z())
        glVertex3f(self.__orig.x(),
                   self.__orig.y() + 5, self.__orig.z())
        glEnd()
        glBegin(GL_LINES)
        glColor3ub(0, 0, 250)
        glVertex3f(self.__orig.x(), self.__orig.y(), self.__orig.z())
        glVertex3f(self.__orig.x() + 5, self.__orig.y(), self.__orig.z())
        glEnd()

    # - - -  listeners  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    def changeArrowsSize(self, new_size):
        if len(self.__arrows_list) > 0:
            self.__arrow_len = new_size

    def addArrow(self, pos, orient, arrow_type):
        self.__arrows_list.append([pos, orient, arrow_type])

    def addLine(self, pos, orient_or_second_point, line_type):
        self.__lines_list.append([pos, orient_or_second_point, line_type])

    def addIntersection(self, pos, icolor):
        self.__intersections_list.append([pos, icolor])

    def keyPressEvent(self, e):
        if e.key() == Qt.Key_Control or e.key() == Qt.Key_Meta:
            self.__Ctrl_or_Meta_key_pressed = True
        if e.key() == Qt.Key_Alt: self.__Alt_key_pressed = True

    def keyReleaseEvent(self, e):
        if e.key() == Qt.Key_Control or e.key() == Qt.Key_Meta:
            self.__Ctrl_or_Meta_key_pressed = False
        if e.key() == Qt.Key_Alt: self.__Alt_key_pressed = False

    def wheelEvent(self, e):
        if self.__Ctrl_or_Meta_key_pressed:
            self.__cam_dist += e.delta() * 0.01

    # the three methods below are for regulate the OpenGL widget's FPS based on the focus received by the user.
    def setUi_Form(self, uif):
        self.uiform = uif

    def focusInEvent(self, e):
        self.uiform.speedUpGLFrameRate()

    def focusOutEvent(self, e):
        self.uiform.freezeGLFrameRate()

    def getFovy(self):
        return self.__fovy

    def getMatrix(self):
        return self.__mtx

    def getNormalMatrix(self):
        return self.__norm_mtx

    def setModel(self, model):
        self.__poly_model = model
        self.__poly_list = model.getPolyListCopy()