Example #1
0
    def decoration(self, index):
        """Defines the decoration of the node.

        Tries to load a banner from the URL, defined by :py:meth:`banner_url`,
        sets a default image while loading and in case the attempt to
        obtain a banner was unsuccesful. If a banner has been cached for the
        given URL, the cached image will be used instead.

        :param index: The index referring to the node to get decoration for.
        :type index: :class:`~.PySide.QtCore.QModelIndex`

        :returns: The :class:`PySide.QtGui.Pixmap` to use as the node's decoration.

        """
        pixmap = QPixmap()
        banner_url = self.banner_url()
        if banner_url:
            placeholder = ":/icons/image-loading.png"
            fetch = True
        else:
            banner_url = placeholder = ":/icons/image-missing.png"
            fetch = False

        if not pixmap_cache.find(banner_url, pixmap):
            if fetch:
                banner_loader.fetch_banner(banner_url, index, self._cache)
            pixmap.load(placeholder)
            if self._scale:
                pixmap = pixmap.scaled(self._scale, Qt.AspectRatioMode.KeepAspectRatio)
            pixmap_cache.insert(banner_url, pixmap)
        return pixmap
    def paintStartAndFinishLine(self, painter):
        start = QPixmap()
        start.load('.\\pictures\\start-finish\\start.bmp')
        finish = QPixmap()
        finish.load('.\\pictures\\start-finish\\finish.bmp')

        for y in range(0, self.field.height, start.height()):
            painter.drawPixmap(QPoint(self.field.start_line_x, y) + self.field.focus_point, start)
            painter.drawPixmap(QPoint(self.field.finish_line_x, y) + self.field.focus_point, finish)
Example #3
0
def pixmap_cache ( name ):
    """ Return the QPixmap corresponding to a filename.  If the filename does
        not contain a path component then the local 'images' directory is used.
    """
    if name[:1] == '@':
        image = image_for( name )
        if image is not None:
            return image.bitmap

    path, _ = os.path.split( name )
    if not path:
        name = os.path.join( os.path.dirname( __file__ ), 'images', name )

    pm = QPixmap()

    if not QPixmapCache.find( name, pm ):
        pm.load( name )
        QPixmapCache.insert( name, pm )

    return pm
Example #4
0
    def finished_request(self, reply):
        """Processes replies and dispatches results to requesters.

        This method will be invoked on each finished request, submitted by
        :py:meth:`.fetch_banner`. It then converts the loaded data into a
        banner and passes the result on to the model of the request's origin.

        :param reply: The network reply from a banner load request.
        :type reply: :class:`.QNetworkReply`

        """
        pixmap = QPixmap()
        if reply.error() == QNetworkReply.NoError:
            image_bytes = reply.readAll()
            pixmap.loadFromData(image_bytes)
        else:
            pixmap.load(":/icons/image-missing.png")

        index = self._ready_signal.pop(reply.request().url().toString())

        index.model().setData(index, pixmap, Qt.DecorationRole)
Example #5
0
    def __init__(self, app_tag, app_image_path, app_description_path):
        QWidget.__init__(self)
        #App tag
        self.app_tag_ = QLabel(app_tag)
        #App image
        app_image = QPixmap()
        app_image.load(app_image_path)
        self.app_image_ = QLabel()
        self.app_image_.setPixmap(app_image)
        #App description
        try:
            f = open(app_description_path, 'r')
            self.app_description_ = f.read()
            f.close()
        except:
            print "Error opening description. Quitting."

        self.setToolTip(self.app_description_)
        #Layout the child widgets
        self.child_layout_ = QVBoxLayout()
        self.child_layout_.addWidget(self.app_image_)
        self.child_layout_.addWidget(self.app_tag_)

        self.setLayout(self.child_layout_)
    def __init__(self, app_tag, app_image_path, app_description_path):
        QWidget.__init__(self)
        # App tag
        self.app_tag_ = QLabel(app_tag)
        # App image
        app_image = QPixmap()
        app_image.load(app_image_path)
        self.app_image_ = QLabel()
        self.app_image_.setPixmap(app_image)
        # App description
        try:
            f = open(app_description_path, "r")
            self.app_description_ = f.read()
            f.close()
        except:
            print "Error opening description. Quitting."

        self.setToolTip(self.app_description_)
        # Layout the child widgets
        self.child_layout_ = QVBoxLayout()
        self.child_layout_.addWidget(self.app_image_)
        self.child_layout_.addWidget(self.app_tag_)

        self.setLayout(self.child_layout_)
Example #7
0
class MdiArea(QMdiArea):  # MdiArea::MdiArea(MainWindow* mw, QWidget *parent) : QMdiArea(parent), mainWin(mw)
    """
    Subclass of `QMdiArea`_

    TOWRITE
    """

    def __init__(self, mw, parent=None):
        """
        Default class constructor.

        :param `mw`: Pointer to a application main window instance.
        :type `mw`: `MainWindow`_
        :param `parent`: Pointer to a parent widget instance.
        :type `parent`: `QWidget`_
        """
        super(MdiArea, self).__init__(parent)

        self.mainWin = mw
        self.gSpiralsImgPath = mw.gImgDir + os.sep + 'texture-spirals.png'
        self.gLogoSpiralsImgPath = mw.gImgDir + os.sep + 'logo-spirals.png'

        try:  #if QT_VERSION >= 0x040800
            self.setTabsClosable(True)
        except AttributeError:
            pass

        self.useLogo = False
        self.useTexture = False
        self.useColor = False

        self.bgLogo = QPixmap()
        self.bgTexture = QPixmap(self.gSpiralsImgPath)
        self.bgColor = QColor()

        self.bgLogo = QPixmap(self.gLogoSpiralsImgPath)

        # Brushes
        self.colorBrush = QBrush(QColor(EMBROIDERBLUE1))
        self.backgroundBrush = QBrush(QPixmap(self.gSpiralsImgPath))
        linearGrad = QLinearGradient(QPointF(0, 0), QPointF(400, 400))
        linearGrad.setColorAt(0, QColor(EMBROIDERBLUE1))
        linearGrad.setColorAt(1, QColor(EMBROIDERBLUE2))
        self.gradientBrush = QBrush(linearGrad)

        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.setActivationOrder(QMdiArea.ActivationHistoryOrder)

        self.setFocusPolicy(Qt.WheelFocus)
        self.setFocus()

        self.setAcceptDrops(True)
        self.doSetDocumentMode(True)

    def __del__(self):
        """Class destructor."""
        qDebug("MdiArea Destructor")

    def useBackgroundLogo(self, use):
        """
        TOWRITE

        :param `use`: TOWRITE
        :type `use`: bool
        """
        self.useLogo = use
        self.forceRepaint()

    def useBackgroundTexture(self, use):
        """
        TOWRITE

        :param `use`: TOWRITE
        :type `use`: bool
        """
        self.useTexture = use
        self.forceRepaint()

    def useBackgroundColor(self, use):
        """
        TOWRITE

        :param `use`: TOWRITE
        :type `use`: bool
        """
        self.useColor = use
        self.forceRepaint()

    def setBackgroundLogo(self, fileName):
        """
        TOWRITE

        :param `fileName`: TOWRITE
        :type `fileName`: QString
        """
        self.bgLogo.load(fileName)
        self.forceRepaint()

    def setBackgroundTexture(self, fileName):
        """
        TOWRITE

        :param `fileName`: TOWRITE
        :type `fileName`: QString
        """
        self.bgTexture.load(fileName)
        self.forceRepaint()

    def setBackgroundColor(self, color):
        """
        TOWRITE

        :param `color`: TOWRITE
        :type `color`: `QColor`_
        """
        if not color:  # .isValid()
            self.bgColor = self.background().color()
        else:
            self.bgColor = color

        self.forceRepaint()

    def mouseDoubleClickEvent(self, event):
        """
        Handles the ``mouseDoubleClickEvent`` event for :class:`MdiArea`.

        :param `event`: A `QMouseEvent`_ to be processed.
        """
        qDebug('%s' % event.button())
        evtBtn = event.button()
        if evtBtn == Qt.LeftButton: # return 1
            self.mainWin.openFile()
        elif evtBtn == Qt.RightButton: # return 2
            qDebug('DoubleRightClick')
        elif evtBtn == Qt.MiddleButton: # return 4
            qDebug('DoubleMiddleClick')
        elif evtBtn == Qt.XButton1: # Aux1 return 8
            qDebug('DoubleAux1Click')
        elif evtBtn == Qt.XButton2: # Aux2 return 16
            qDebug('DoubleAux2Click')

    ## def paintEvent(self, event):
    ##     """
    ##     Handles the ``paintEvent`` event for :class:`MdiArea`.
    ##
    ##     :param `event`: A `QPaintEvent`_ to be processed.
    ##     """
    ##     vport = self.viewport()  # QWidget*
    ##     rect = vport.rect()  # QRect
    ##
    ##     painter = QPainter(vport)
    ##     painter.setRenderHint(QPainter.SmoothPixmapTransform)
    ##
    ##     # Always fill with a solid color first.
    ##     if self.useColor:
    ##         painter.fillRect(rect, self.bgColor)
    ##     else:
    ##         painter.fillRect(rect, self.background())
    ##
    ##     # Then overlay the texture.
    ##     if self.useTexture:
    ##         bgBrush = QBrush(self.bgTexture)
    ##         painter.fillRect(rect, bgBrush)
    ##
    ##     # Overlay the logo last.
    ##     if self.useLogo:
    ##         bgLogo = self.bgLogo
    ##         # Center the pixmap.
    ##         dx = (rect.width() - bgLogo.width()) / 2     # int
    ##         dy = (rect.height() - bgLogo.height()) / 2   # int
    ##         painter.drawPixmap(dx, dy, bgLogo.width(), bgLogo.height(), bgLogo)

    def paintEvent(self, event):
        """
        Handles the ``paintEvent`` event for :class:`MdiArea`.

        :param `event`: A `QPaintEvent`_ to be processed.
        """
        vport = self.viewport()
        rect = vport.rect()

        painter = QPainter(vport)
        painter.setRenderHint(painter.SmoothPixmapTransform)

        # Always fill with a solid color first
        if self.useColor:
            # painter.fillRect(rect, self.colorBrush)
            painter.fillRect(rect, self.bgColor)
        else:
            painter.fillRect(rect, self.background())

        # Then overlay the texture
        if self.useTexture:
            # painter.fillRect(rect, self.backgroundBrush)
            bgBrush = QBrush(self.bgTexture)
            painter.fillRect(rect, bgBrush)
            

        # Overlay the logo last
        if self.useLogo:
            if not len(self.subWindowList()):  # Nothing is open.
                cSizeW, cSizeH = rect.width(), rect.height()
                bgLogoW, bgLogoH = self.bgLogo.width(), self.bgLogo.height()
                if bgLogoW > cSizeW:
                    # Proportional Scaling an Image.
                    newHeight = bgLogoH * cSizeW // bgLogoW
                    scaledLogo = self.bgLogo.scaled(cSizeW, newHeight)
                    painter.drawPixmap(0,
                                       cSizeH // 2 - scaledLogo.height() // 2,
                                       scaledLogo)
                else:
                    painter.drawPixmap((cSizeW - bgLogoW) // 2,
                                       (cSizeH - bgLogoH) // 2,
                                       self.bgLogo)
            else:
                # Center the pixmap
                dx = (rect.width() - self.bgLogo.width()) / 2
                dy = (rect.height() - self.bgLogo.height()) / 2
                painter.drawPixmap(dx, dy,
                                   self.bgLogo.width(), self.bgLogo.height(),
                                   self.bgLogo)

    def zoomExtentsAllSubWindows(self):
        """
        TOWRITE
        """
        for window in self.subWindowList():  # foreach(QMdiSubWindow* window, subWindowList())
            mdiWin = window  # MdiWindow* mdiWin = qobject_cast<MdiWindow*>(window);
            if mdiWin:
                v = mdiWin.getView()  # View*
                if v:
                    v.recalculateLimits()
                    v.zoomExtents()

    def forceRepaint(self):
        """
        TOWRITE
        """
        # HACK: Take that QMdiArea!
        hack = self.size()  # QSize
        self.resize(hack + QSize(1, 1))
        self.resize(hack)

    def moveEvent(self, event):
        """
        Handles the ``moveEvent`` event for :class:`MDIArea`.

        :param `event`: A `QMoveEvent`_ to be processed.
        """
        # Dragging while MouseButton is down.
        qDebug("QMdiArea moveEvent")

    def contextMenuEvent(self, event):
        """
        Handles the ``contextMenuEvent`` event for :class:`MDIArea`.

        :param `event`: A `QContextMenuEvent`_ to be processed.
        """
        mainWin = self.mainWin
        if not len(self.subWindowList()): # Nothing is open.
            # Build a menu suitable for the startup screen.
            menu = QMenu(self)
            menu.addAction(mainWin.actionHash["ACTION_new"])
            menu.addAction(mainWin.actionHash["ACTION_open"])
            menu.addAction(mainWin.actionHash["ACTION_settingsdialog"])
            menu.addAction(mainWin.actionHash["ACTION_help"])
            menu.addAction(mainWin.actionHash["ACTION_about"])
            menu.addAction(mainWin.actionHash["ACTION_exit"])
            menu.popup(self.mapToGlobal(event.pos()))
            # menu.exec_(self.mapToGlobal(event.pos()))
        else:
            # Build a menu suitable for when the mdi workspace is open.
            mainWin.fileMenu.popup(self.mapToGlobal(event.pos()))

        event.accept()
        qDebug("QMdiArea contextMenuEvent")

    def doSetDocumentMode(self, enabled=False):
        """
        Set the document mode for :class:`MDIArea`.

        :param `enabled`: Whether the tab bar is set to document mode in tabbed view mode.
         Document mode is disabled by default.
        :type `enabled`: bool
        """
        self.setDocumentMode(enabled)

    # Slots ------------------------------------------------------------------

    @Slot()
    def cascade(self):
        """
        TOWRITE
        """
        self.cascadeSubWindows()
        self.zoomExtentsAllSubWindows()

    @Slot()
    def tile(self):
        """
        TOWRITE
        """
        self.tileSubWindows()
        self.zoomExtentsAllSubWindows()
Example #8
0
class MdiArea(
        QMdiArea
):  # MdiArea::MdiArea(MainWindow* mw, QWidget *parent) : QMdiArea(parent), mainWin(mw)
    """
    Subclass of `QMdiArea`_

    TOWRITE
    """
    def __init__(self, mw, parent=None):
        """
        Default class constructor.

        :param `mw`: Pointer to a application main window instance.
        :type `mw`: `MainWindow`_
        :param `parent`: Pointer to a parent widget instance.
        :type `parent`: `QWidget`_
        """
        super(MdiArea, self).__init__(parent)

        self.mainWin = mw
        self.gSpiralsImgPath = mw.gImgDir + os.sep + 'texture-spirals.png'
        self.gLogoSpiralsImgPath = mw.gImgDir + os.sep + 'logo-spirals.png'

        try:  #if QT_VERSION >= 0x040800
            self.setTabsClosable(True)
        except AttributeError:
            pass

        self.useLogo = False
        self.useTexture = False
        self.useColor = False

        self.bgLogo = QPixmap()
        self.bgTexture = QPixmap(self.gSpiralsImgPath)
        self.bgColor = QColor()

        self.bgLogo = QPixmap(self.gLogoSpiralsImgPath)

        # Brushes
        self.colorBrush = QBrush(QColor(EMBROIDERBLUE1))
        self.backgroundBrush = QBrush(QPixmap(self.gSpiralsImgPath))
        linearGrad = QLinearGradient(QPointF(0, 0), QPointF(400, 400))
        linearGrad.setColorAt(0, QColor(EMBROIDERBLUE1))
        linearGrad.setColorAt(1, QColor(EMBROIDERBLUE2))
        self.gradientBrush = QBrush(linearGrad)

        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.setActivationOrder(QMdiArea.ActivationHistoryOrder)

        self.setFocusPolicy(Qt.WheelFocus)
        self.setFocus()

        self.setAcceptDrops(True)
        self.doSetDocumentMode(True)

    def __del__(self):
        """Class destructor."""
        qDebug("MdiArea Destructor")

    def useBackgroundLogo(self, use):
        """
        TOWRITE

        :param `use`: TOWRITE
        :type `use`: bool
        """
        self.useLogo = use
        self.forceRepaint()

    def useBackgroundTexture(self, use):
        """
        TOWRITE

        :param `use`: TOWRITE
        :type `use`: bool
        """
        self.useTexture = use
        self.forceRepaint()

    def useBackgroundColor(self, use):
        """
        TOWRITE

        :param `use`: TOWRITE
        :type `use`: bool
        """
        self.useColor = use
        self.forceRepaint()

    def setBackgroundLogo(self, fileName):
        """
        TOWRITE

        :param `fileName`: TOWRITE
        :type `fileName`: QString
        """
        self.bgLogo.load(fileName)
        self.forceRepaint()

    def setBackgroundTexture(self, fileName):
        """
        TOWRITE

        :param `fileName`: TOWRITE
        :type `fileName`: QString
        """
        self.bgTexture.load(fileName)
        self.forceRepaint()

    def setBackgroundColor(self, color):
        """
        TOWRITE

        :param `color`: TOWRITE
        :type `color`: `QColor`_
        """
        if not color:  # .isValid()
            self.bgColor = self.background().color()
        else:
            self.bgColor = color

        self.forceRepaint()

    def mouseDoubleClickEvent(self, event):
        """
        Handles the ``mouseDoubleClickEvent`` event for :class:`MdiArea`.

        :param `event`: A `QMouseEvent`_ to be processed.
        """
        qDebug('%s' % event.button())
        evtBtn = event.button()
        if evtBtn == Qt.LeftButton:  # return 1
            self.mainWin.openFile()
        elif evtBtn == Qt.RightButton:  # return 2
            qDebug('DoubleRightClick')
        elif evtBtn == Qt.MiddleButton:  # return 4
            qDebug('DoubleMiddleClick')
        elif evtBtn == Qt.XButton1:  # Aux1 return 8
            qDebug('DoubleAux1Click')
        elif evtBtn == Qt.XButton2:  # Aux2 return 16
            qDebug('DoubleAux2Click')

    ## def paintEvent(self, event):
    ##     """
    ##     Handles the ``paintEvent`` event for :class:`MdiArea`.
    ##
    ##     :param `event`: A `QPaintEvent`_ to be processed.
    ##     """
    ##     vport = self.viewport()  # QWidget*
    ##     rect = vport.rect()  # QRect
    ##
    ##     painter = QPainter(vport)
    ##     painter.setRenderHint(QPainter.SmoothPixmapTransform)
    ##
    ##     # Always fill with a solid color first.
    ##     if self.useColor:
    ##         painter.fillRect(rect, self.bgColor)
    ##     else:
    ##         painter.fillRect(rect, self.background())
    ##
    ##     # Then overlay the texture.
    ##     if self.useTexture:
    ##         bgBrush = QBrush(self.bgTexture)
    ##         painter.fillRect(rect, bgBrush)
    ##
    ##     # Overlay the logo last.
    ##     if self.useLogo:
    ##         bgLogo = self.bgLogo
    ##         # Center the pixmap.
    ##         dx = (rect.width() - bgLogo.width()) / 2     # int
    ##         dy = (rect.height() - bgLogo.height()) / 2   # int
    ##         painter.drawPixmap(dx, dy, bgLogo.width(), bgLogo.height(), bgLogo)

    def paintEvent(self, event):
        """
        Handles the ``paintEvent`` event for :class:`MdiArea`.

        :param `event`: A `QPaintEvent`_ to be processed.
        """
        vport = self.viewport()
        rect = vport.rect()

        painter = QPainter(vport)
        painter.setRenderHint(painter.SmoothPixmapTransform)

        # Always fill with a solid color first
        if self.useColor:
            # painter.fillRect(rect, self.colorBrush)
            painter.fillRect(rect, self.bgColor)
        else:
            painter.fillRect(rect, self.background())

        # Then overlay the texture
        if self.useTexture:
            # painter.fillRect(rect, self.backgroundBrush)
            bgBrush = QBrush(self.bgTexture)
            painter.fillRect(rect, bgBrush)

        # Overlay the logo last
        if self.useLogo:
            if not len(self.subWindowList()):  # Nothing is open.
                cSizeW, cSizeH = rect.width(), rect.height()
                bgLogoW, bgLogoH = self.bgLogo.width(), self.bgLogo.height()
                if bgLogoW > cSizeW:
                    # Proportional Scaling an Image.
                    newHeight = bgLogoH * cSizeW // bgLogoW
                    scaledLogo = self.bgLogo.scaled(cSizeW, newHeight)
                    painter.drawPixmap(0,
                                       cSizeH // 2 - scaledLogo.height() // 2,
                                       scaledLogo)
                else:
                    painter.drawPixmap((cSizeW - bgLogoW) // 2,
                                       (cSizeH - bgLogoH) // 2, self.bgLogo)
            else:
                # Center the pixmap
                dx = (rect.width() - self.bgLogo.width()) / 2
                dy = (rect.height() - self.bgLogo.height()) / 2
                painter.drawPixmap(dx, dy, self.bgLogo.width(),
                                   self.bgLogo.height(), self.bgLogo)

    def zoomExtentsAllSubWindows(self):
        """
        TOWRITE
        """
        for window in self.subWindowList(
        ):  # foreach(QMdiSubWindow* window, subWindowList())
            mdiWin = window  # MdiWindow* mdiWin = qobject_cast<MdiWindow*>(window);
            if mdiWin:
                v = mdiWin.getView()  # View*
                if v:
                    v.recalculateLimits()
                    v.zoomExtents()

    def forceRepaint(self):
        """
        TOWRITE
        """
        # HACK: Take that QMdiArea!
        hack = self.size()  # QSize
        self.resize(hack + QSize(1, 1))
        self.resize(hack)

    def moveEvent(self, event):
        """
        Handles the ``moveEvent`` event for :class:`MDIArea`.

        :param `event`: A `QMoveEvent`_ to be processed.
        """
        # Dragging while MouseButton is down.
        qDebug("QMdiArea moveEvent")

    def contextMenuEvent(self, event):
        """
        Handles the ``contextMenuEvent`` event for :class:`MDIArea`.

        :param `event`: A `QContextMenuEvent`_ to be processed.
        """
        mainWin = self.mainWin
        if not len(self.subWindowList()):  # Nothing is open.
            # Build a menu suitable for the startup screen.
            menu = QMenu(self)
            menu.addAction(mainWin.actionHash["ACTION_new"])
            menu.addAction(mainWin.actionHash["ACTION_open"])
            menu.addAction(mainWin.actionHash["ACTION_settingsdialog"])
            menu.addAction(mainWin.actionHash["ACTION_help"])
            menu.addAction(mainWin.actionHash["ACTION_about"])
            menu.addAction(mainWin.actionHash["ACTION_exit"])
            menu.popup(self.mapToGlobal(event.pos()))
            # menu.exec_(self.mapToGlobal(event.pos()))
        else:
            # Build a menu suitable for when the mdi workspace is open.
            mainWin.fileMenu.popup(self.mapToGlobal(event.pos()))

        event.accept()
        qDebug("QMdiArea contextMenuEvent")

    def doSetDocumentMode(self, enabled=False):
        """
        Set the document mode for :class:`MDIArea`.

        :param `enabled`: Whether the tab bar is set to document mode in tabbed view mode.
         Document mode is disabled by default.
        :type `enabled`: bool
        """
        self.setDocumentMode(enabled)

    # Slots ------------------------------------------------------------------

    @Slot()
    def cascade(self):
        """
        TOWRITE
        """
        self.cascadeSubWindows()
        self.zoomExtentsAllSubWindows()

    @Slot()
    def tile(self):
        """
        TOWRITE
        """
        self.tileSubWindows()
        self.zoomExtentsAllSubWindows()
Example #9
0
class ImageSource(Source):
    '''
    A celestial object represented by an image, such as a planet or a galaxy.
    
    // These two vectors, along with Source.xyz, determine the position of the
    // image object.  The corners are as follows
    //
    //  xyz-u+v   xyz+u+v
    //     +---------+     ^
    //     |   xyz   |     | v
    //     |    .    |     .
    //     |         |
    //     +---------+
    //  xyz-u-v    xyz+u-v
    //
    //          .--->
    //            u
    '''
    image_scale = 1

    def get_horizontal_corner(self):
        return [self.ux, self.uy, self.uz]
    
    def get_verical_corner(self):
        return [self.vx, self.vy, self.vz]
    
    def set_up_vector(self, up_v):
        p = self.geocentric_coords
        u = negate(normalized(cross_product(p, up_v)))
        v = cross_product(u, p)
        v.scale(self.image_scale)
        u.scale(self.image_scale)
        
        self.ux = u.x
        self.uy = u.y
        self.uz = u.z
        
        self.vx = v.x
        self.vy = v.y
        self.vz = v.z
    
    def set_image_id(self, input_id):
        # hack bool to prevent blank meteors from rendering
        self.is_blank = True if input_id == 'blank' else False
        
        url = "assets/drawable/" + input_id + ".png"
        self.pixmap_image = QPixmap()
        
        if not self.pixmap_image.load(url):
            raise RuntimeError("Could not load image resource")
    
    def __init__(self, geo_coord, new_id, up_v=Vector3(0.0, 1.0, 0.0), im_scale=1):
        '''
        Constructor
        '''
        Source.__init__(self, colors.WHITE, geo_coord)
        self.is_blank = False
        self.requires_blending = False
        self.pixmap_image = None
        self.image_scale = im_scale
        self.set_up_vector(up_v)
        self.set_image_id(new_id)