Пример #1
0
    def OnKeyDown(self, evt):
        """Capture the keypress when the notebook tab is focused.
            Currently this is used to workaround a bug in Windows since the
            notebook tab instead of the panel receives focus."""

        if guiutil.IsMSWindows():
            pub.sendMessage('main.key_down', msg=evt)
Пример #2
0
    def OnMouseWheel(self, evt):
        """Capture the mousewheel event when the notebook tab is focused.
            Currently this is used to workaround a bug in Windows since the
            notebook tab instead of the panel receives focus."""

        if guiutil.IsMSWindows():
            pub.sendMessage('main.mousewheel', msg=evt)
Пример #3
0
    def OnKeyDown(self, evt):
        """Change the image when the user presses the appropriate keys."""

        # Needed to work around a bug in Windows. See main.py for more details.
        if guiutil.IsMSWindows():
            try:
                evt = evt.data
            except AttributeError:
                keyname = evt.GetKeyCode()

        if len(self.images):
            keyname = evt.GetKeyCode()
            prevkey = [wx.WXK_UP, wx.WXK_PAGEUP]
            nextkey = [wx.WXK_DOWN, wx.WXK_PAGEDOWN]
            zoominkey = [43, 61, 388] # Keys: +, =, Numpad add
            zoomoutkey = [45, 95, 390] # Keys: -, _, Numpad subtract
            if (keyname in prevkey):
                if (self.imagenum > 1):
                    self.imagenum -= 1
                    self.Refresh()
            if (keyname in nextkey):
                if (self.imagenum < len(self.images)):
                    self.imagenum += 1
                    self.Refresh()
            if (keyname == wx.WXK_HOME):
                self.imagenum = 1
                self.Refresh()
            if (keyname == wx.WXK_END):
                self.imagenum = len(self.images)
                self.Refresh()
            if (keyname in zoominkey):
                self.OnZoomIn(None)
            if (keyname in zoomoutkey):
                self.OnZoomOut(None)
Пример #4
0
    def Init(self, plugins, pluginsDisabled):
        """Method called after the panel has been initialized."""

        # Set window icon
        if not guiutil.IsMac():
            self.SetIcon(guiutil.get_icon())

        # Initialize controls
        self.tcPlugins = XRCCTRL(self, 'tcPlugins')
        self.panelTreeView = XRCCTRL(self, 'panelTreeView')
        self.panelProperties = XRCCTRL(self, 'panelProperties')
        self.lblName = XRCCTRL(self, 'lblName')
        self.lblAuthor = XRCCTRL(self, 'lblAuthor')
        self.lblPluginType = XRCCTRL(self, 'lblPluginType')
        self.lblVersion = XRCCTRL(self, 'lblVersion')
        self.lblVersionNumber = XRCCTRL(self, 'lblVersionNumber')
        self.lblDescription = XRCCTRL(self, 'lblDescription')
        self.checkEnabled = XRCCTRL(self, 'checkEnabled')
        self.lblMessage = XRCCTRL(self, 'lblMessage')
        self.btnGetMorePlugins = XRCCTRL(self, 'btnGetMorePlugins')
        self.btnDeletePlugin = XRCCTRL(self, 'btnDeletePlugin')

        self.plugins = plugins
        self.pluginsDisabled = set(pluginsDisabled)

        # Bind interface events to the proper methods
        #        wx.EVT_BUTTON(self, XRCID('btnDeletePlugin'), self.DeletePlugin)
        wx.EVT_CHECKBOX(self, XRCID('checkEnabled'), self.OnEnablePlugin)
        wx.EVT_TREE_ITEM_ACTIVATED(self, XRCID('tcPlugins'),
                                   self.OnEnablePlugin)
        wx.EVT_TREE_SEL_CHANGED(self, XRCID('tcPlugins'),
                                self.OnSelectTreeItem)
        wx.EVT_TREE_SEL_CHANGING(self, XRCID('tcPlugins'),
                                 self.OnSelectRootItem)

        # Modify the control and font size as needed
        font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
        if guiutil.IsMac():
            children = list(self.Children) + \
                        list(self.panelTreeView.Children) + \
                        list(self.panelProperties.Children)
            for control in children:
                control.SetFont(font)
                control.SetWindowVariant(wx.WINDOW_VARIANT_SMALL)
            XRCCTRL(self, 'wxID_OK').SetWindowVariant(wx.WINDOW_VARIANT_NORMAL)
        font.SetWeight(wx.FONTWEIGHT_BOLD)
        if guiutil.IsMSWindows():
            self.tcPlugins.SetPosition((0, 3))
            self.panelTreeView.SetWindowStyle(wx.STATIC_BORDER)
        if (guiutil.IsMac() or guiutil.IsGtk()):
            self.tcPlugins.SetPosition((-30, 0))
            self.panelTreeView.SetWindowStyle(wx.SUNKEN_BORDER)
        self.lblName.SetFont(font)
        self.lblMessage.SetFont(font)

        self.Layout()
        self.InitPluginList()
        self.LoadPlugins()
Пример #5
0
    def OnMouseMotion(self, evt):
        """Process mouse motion events and pass to the appropriate handler."""

        if evt.LeftIsDown():
            self.OnLeftIsDown(evt)
            self.SetCursor(wx.Cursor(wx.CURSOR_SIZING))
        elif evt.RightIsDown():
            self.OnRightIsDown(evt)
            # Custom cursors with > 2 colors only works on Windows currently
            if guiutil.IsMSWindows():
                image = wx.Image(util.GetResourcePath('contrast_high.png'))
                self.SetCursor(wx.CursorFromImage(image))
        # Update the positon and values of the mouse cursor
        self.mousepos = evt.GetPosition()
        self.OnUpdatePositionValues(evt)
Пример #6
0
    def OnUnfocus(self):
        """Unbind to certain events when the plugin is unfocused."""

        # Unbind keyboard and mouse events
        self.Unbind(wx.EVT_KEY_DOWN)
        self.Unbind(wx.EVT_MOUSEWHEEL)
        self.Unbind(wx.EVT_LEFT_DOWN)
        self.Unbind(wx.EVT_LEFT_UP)
        self.Unbind(wx.EVT_RIGHT_DOWN)
        self.Unbind(wx.EVT_RIGHT_UP)
        self.Unbind(wx.EVT_MOTION)
        if guiutil.IsMSWindows():
            pub.unsubscribe(self.OnKeyDown, 'main.key_down')
            pub.unsubscribe(self.OnMouseWheel, 'main.mousewheel')
        pub.unsubscribe(self.OnRefresh, '2dview.refresh')
Пример #7
0
    def OnFocus(self):
        """Bind to certain events when the plugin is focused."""

        # Bind keyboard and mouse events
        self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
        self.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel)
        self.Bind(wx.EVT_LEFT_DOWN, self.OnMouseDown)
        self.Bind(wx.EVT_LEFT_UP, self.OnMouseUp)
        self.Bind(wx.EVT_RIGHT_DOWN, self.OnMouseDown)
        self.Bind(wx.EVT_RIGHT_UP, self.OnMouseUp)
        self.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnter)
        self.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseLeave)
        if guiutil.IsMSWindows():
            pub.subscribe(self.OnKeyDown, 'main.key_down')
            pub.subscribe(self.OnMouseWheel, 'main.mousewheel')
Пример #8
0
    def OnLicense(self, evt):
        """Show the license document in a new dialog."""

        f = open(util.get_text_resources("license.txt"), "rU")
        msg = f.read()
        f.close()

        if guiutil.IsMSWindows():
            dlg = wx.lib.dialogs.ScrolledMessageDialog(self, msg,
                                                       "dicompyler License")
        else:
            dlg = wx.lib.dialogs.ScrolledMessageDialog(self,
                                                       msg,
                                                       "dicompyler License",
                                                       size=(650, 550))

        dlg.ShowModal()
        dlg.Destroy()
Пример #9
0
    def OnMouseWheel(self, evt):
        """Change the image when the user scrolls the mouse wheel."""

        # Needed to work around a bug in Windows. See main.py for more details.
        if guiutil.IsMSWindows():
            try:
                evt = evt.data
            except AttributeError:
                delta = evt.GetWheelDelta()
                rot = evt.GetWheelRotation()

        if len(self.images):
            delta = evt.GetWheelDelta()
            rot = evt.GetWheelRotation()
            rot = rot/delta
            if (rot >= 1):
                if (self.imagenum > 1):
                    self.imagenum -= 1
                    self.Refresh()
            if (rot <= -1):
                if (self.imagenum < len(self.images)):
                    self.imagenum += 1
                    self.Refresh()
Пример #10
0
    def OnPaint(self, evt):
        """Update the panel when it needs to be refreshed."""

        # Bind motion event when the panel has been painted to avoid a blank
        # image on Windows if a file is loaded too quickly before the plugin
        # is initialized
        self.Bind(wx.EVT_MOTION, self.OnMouseMotion)

        # Special case for Windows to account for flickering
        # if and only if images are loaded
        if (guiutil.IsMSWindows() and len(self.images)):
            dc = wx.BufferedPaintDC(self)
            self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
        else:
            dc = wx.PaintDC(self)

        width, height = self.GetClientSize()
        try:
            gc = wx.GraphicsContext.Create(dc)
        except NotImplementedError:
            dc.DrawText(
                "This build of wxPython does not support the "
                "wx.GraphicsContext family of classes.", 25, 25)
            return

        # If we have images loaded, process and show the image
        if len(self.images):
            # Save the original drawing state
            gc.PushState()
            # Scale the image by the zoom factor
            gc.Scale(self.zoom, self.zoom)

            # Redraw the background on Windows
            if guiutil.IsMSWindows():
                gc.SetBrush(wx.Brush(wx.Colour(0, 0, 0)))
                gc.SetPen(wx.Pen(wx.Colour(0, 0, 0)))
                gc.DrawRectangle(0, 0, width, height)

            image = guiutil.convert_pil_to_wx(
                self.images[self.imagenum - 1].GetImage(
                    self.window, self.level))
            bmp = wx.Bitmap(image)
            self.bwidth, self.bheight = image.GetSize()

            # Center the image
            transx = self.pan[0] + (width -
                                    self.bwidth * self.zoom) / (2 * self.zoom)
            transy = self.pan[1] + (height -
                                    self.bheight * self.zoom) / (2 * self.zoom)
            gc.Translate(transx, transy)
            gc.DrawBitmap(bmp, 0, 0, self.bwidth, self.bheight)
            gc.SetBrush(wx.Brush(wx.Colour(0, 0, 255, 30)))
            gc.SetPen(wx.Pen(wx.Colour(0, 0, 255, 30)))

            # Draw the structures if present
            imdata = self.images[self.imagenum - 1].GetImageData()
            self.z = '%.2f' % imdata['position'][2]

            # Determine whether the patient is prone or supine
            if 'p' in imdata['patientposition'].lower():
                prone = True
            else:
                prone = False
            # Determine whether the patient is feet first or head first
            if 'ff' in imdata['patientposition'].lower():
                feetfirst = True
            else:
                feetfirst = False
            for id, structure in self.structures.items():
                self.DrawStructure(structure, gc, self.z, prone, feetfirst)

            # Draw the isodoses if present
            if len(self.isodoses):
                grid = self.dose.GetDoseGrid(float(self.z))
                if not (grid == []):
                    x, y = np.meshgrid(np.arange(grid.shape[1]),
                                       np.arange(grid.shape[0]))
                    # Instantiate the isodose generator for this slice
                    isodosegen = cntr.Cntr(x, y, grid)
                    for id, isodose in iter(sorted(self.isodoses.items())):
                        self.DrawIsodose(isodose, gc, isodosegen)

            # Restore the translation and scaling
            gc.PopState()

            # Prepare the font for drawing the information text
            font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
            if guiutil.IsMac():
                font.SetPointSize(10)
            gc.SetFont(font, wx.WHITE)

            # Draw the information text
            imtext = "Image: " + str(self.imagenum) + "/" + str(
                len(self.images))
            te = gc.GetFullTextExtent(imtext)
            gc.DrawText(imtext, 10, 7)
            impos = "Position: " + str(self.z) + " mm"
            gc.DrawText(impos, 10, 7 + te[1] * 1.1)
            if ("%.3f" % self.zoom == "1.000"):
                zoom = "1"
            else:
                zoom = "%.3f" % self.zoom
            imzoom = "Zoom: " + zoom + ":1"
            gc.DrawText(imzoom, 10, height - 17)
            imsize = "Image Size: " + str(self.bheight) + "x" + str(
                self.bwidth) + " px"
            gc.DrawText(imsize, 10, height - 17 - te[1] * 1.1)
            imwinlevel = "W/L: " + str(self.window) + ' / ' + str(self.level)
            te = gc.GetFullTextExtent(imwinlevel)
            gc.DrawText(imwinlevel, width - te[0] - 7, 7)
            impatpos = "Patient Position: " + imdata['patientposition']
            te = gc.GetFullTextExtent(impatpos)
            gc.DrawText(impatpos, width - te[0] - 7, height - 17)

            # Send message with the current image number and various properties
            pub.sendMessage(
                '2dview.updated.image',
                msg={
                    'number': self.imagenum,  # slice number
                    'z': self.z,  # slice location
                    'window': self.window,  # current window value
                    'level': self.level,  # curent level value
                    'gc': gc,  # wx.GraphicsContext
                    'scale': self.zoom,  # current zoom level
                    'transx': transx,  # current x translation
                    'transy': transy,  # current y translation
                    'imdata': imdata,  # image data dictionary
                    'patientpixlut': self.structurepixlut
                })