Commit 1743ebf81204c3c6bd326f02bea3c0c902e38468

Authored by Paulo Henrique Junqueira Amorim
1 parent f879b8b8

ADD: Added beginning of the PACS client

.gitattributes
... ... @@ -839,7 +839,10 @@ invesalius/.svnignore -text
839 839 invesalius/data/bases.py -text
840 840 invesalius/data/co_registration.py -text
841 841 invesalius/data/converters.py -text
  842 +invesalius/gui/import_network_panel.py -text
842 843 invesalius/gui/preferences.py -text
  844 +invesalius/net/__init__.py -text
  845 +invesalius/net/dicom.py -text
843 846 locale/de/LC_MESSAGES/invesalius.mo -text
844 847 locale/el/LC_MESSAGES/invesalius.mo -text
845 848 locale/en/LC_MESSAGES/invesalius.mo -text
... ...
invesalius/gui/frame.py
... ... @@ -32,6 +32,7 @@ import default_tasks as tasks
32 32 import default_viewers as viewers
33 33 import gui.dialogs as dlg
34 34 import import_panel as imp
  35 +import import_network_panel as imp_net
35 36 import project as prj
36 37 import session as ses
37 38 import utils
... ... @@ -58,7 +59,7 @@ class Frame(wx.Frame):
58 59 icon_path = os.path.join(const.ICON_DIR, "invesalius.ico")
59 60 self.SetIcon(wx.Icon(icon_path, wx.BITMAP_TYPE_ICO))
60 61 if sys.platform != 'darwin':
61   - self.Maximize()
  62 + ####self.Maximize() ##DESCOMENTAR PAULO
62 63 #Necessary update AUI (statusBar in special)
63 64 #when maximized in the Win 7 and XP
64 65 #self.SetSize(self.GetSize())
... ... @@ -94,6 +95,7 @@ class Frame(wx.Frame):
94 95 sub(self._SetProjectName, 'Set project name')
95 96 sub(self._ShowContentPanel, 'Show content panel')
96 97 sub(self._ShowImportPanel, 'Show import panel in frame')
  98 + sub(self._ShowImportNetwork, 'Show retrieve dicom panel')
97 99 sub(self._ShowTask, 'Show task panel')
98 100 sub(self._UpdateAUI, 'Update AUI')
99 101 sub(self._Exit, 'Exit')
... ... @@ -140,6 +142,12 @@ class Frame(wx.Frame):
140 142 MaximizeButton(True).Floatable(True).
141 143 Caption(caption).CaptionVisible(True))
142 144  
  145 + ncaption = _("Retrieve DICOM from PACS")
  146 + aui_manager.AddPane(imp_net.Panel(self), wx.aui.AuiPaneInfo().
  147 + Name("Retrieve").Centre().Hide().
  148 + MaximizeButton(True).Floatable(True).
  149 + Caption(ncaption).CaptionVisible(True))
  150 +
143 151 # Add toolbars to manager
144 152 # This is pretty tricky -- order on win32 is inverted when
145 153 # compared to linux2 & darwin
... ... @@ -253,6 +261,18 @@ class Frame(wx.Frame):
253 261 aui_manager.GetPane("Tasks").Show(1)
254 262 aui_manager.Update()
255 263  
  264 + def _ShowImportNetwork(self, evt_pubsub):
  265 + """
  266 + Show viewers and task, hide import panel.
  267 + """
  268 + ps.Publisher().sendMessage("Set layout button full")
  269 + aui_manager = self.aui_manager
  270 + aui_manager.GetPane("Retrieve").Show(1)
  271 + aui_manager.GetPane("Data").Show(0)
  272 + aui_manager.GetPane("Tasks").Show(0)
  273 + aui_manager.GetPane("Import").Show(0)
  274 + aui_manager.Update()
  275 +
256 276 def _ShowImportPanel(self, evt_pubsub):
257 277 """
258 278 Show only DICOM import panel.
... ... @@ -316,7 +336,9 @@ class Frame(wx.Frame):
316 336 elif id == const.ID_START:
317 337 self.ShowGettingStarted()
318 338 elif id == const.ID_PREFERENCES:
319   - self.ShowPreferences()
  339 + self.ShowPreferences()
  340 + elif id == const.ID_DICOM_NETWORK:
  341 + self.ShowRetrieveDicomPanel()
320 342  
321 343 def OnSize(self, evt):
322 344 """
... ... @@ -365,6 +387,10 @@ class Frame(wx.Frame):
365 387 """
366 388 ps.Publisher().sendMessage('Show import directory dialog')
367 389  
  390 + def ShowRetrieveDicomPanel(self):
  391 + print "teste.............."
  392 + ps.Publisher().sendMessage('Show retrieve dicom panel')
  393 +
368 394 def ShowOpenProject(self):
369 395 """
370 396 Show open project dialog.
... ... @@ -432,6 +458,7 @@ class MenuBar(wx.MenuBar):
432 458 file_menu = wx.Menu()
433 459 app = file_menu.Append
434 460 app(const.ID_DICOM_IMPORT, _("Import DICOM...\tCtrl+I"))
  461 + app(const.ID_DICOM_NETWORK, _("Retrieve DICOM from PACS"))
435 462 file_menu.AppendMenu(const.ID_IMPORT_OTHERS_FILES, _("Import Others Files"), others_file_menu)
436 463 app(const.ID_PROJECT_OPEN, _("Open Project...\tCtrl+O"))
437 464 app(const.ID_PROJECT_SAVE, _("Save Project\tCtrl+S"))
... ...
invesalius/gui/import_network_panel.py 0 → 100644
... ... @@ -0,0 +1,660 @@
  1 +#--------------------------------------------------------------------------
  2 +# Software: InVesalius - Software de Reconstrucao 3D de Imagens Medicas
  3 +# Copyright: (C) 2001 Centro de Pesquisas Renato Archer
  4 +# Homepage: http://www.softwarepublico.gov.br
  5 +# Contact: invesalius@cti.gov.br
  6 +# License: GNU - GPL 2 (LICENSE.txt/LICENCA.txt)
  7 +#--------------------------------------------------------------------------
  8 +# Este programa e software livre; voce pode redistribui-lo e/ou
  9 +# modifica-lo sob os termos da Licenca Publica Geral GNU, conforme
  10 +# publicada pela Free Software Foundation; de acordo com a versao 2
  11 +# da Licenca.
  12 +#
  13 +# Este programa eh distribuido na expectativa de ser util, mas SEM
  14 +# QUALQUER GARANTIA; sem mesmo a garantia implicita de
  15 +# COMERCIALIZACAO ou de ADEQUACAO A QUALQUER PROPOSITO EM
  16 +# PARTICULAR. Consulte a Licenca Publica Geral GNU para obter mais
  17 +# detalhes.
  18 +#--------------------------------------------------------------------------
  19 +import wx
  20 +import sys
  21 +import wx.gizmos as gizmos
  22 +import wx.lib.pubsub as ps
  23 +import wx.lib.splitter as spl
  24 +
  25 +import constants as const
  26 +import gui.dialogs as dlg
  27 +#import dicom_preview_panel as dpp
  28 +import reader.dicom_grouper as dcm
  29 +import net.dicom as dcm_net
  30 +
  31 +from wx.lib.mixins.listctrl import CheckListCtrlMixin
  32 +#from dicionario import musicdata
  33 +import wx.lib.mixins.listctrl as listmix
  34 +
  35 +
  36 +myEVT_SELECT_SERIE = wx.NewEventType()
  37 +EVT_SELECT_SERIE = wx.PyEventBinder(myEVT_SELECT_SERIE, 1)
  38 +
  39 +myEVT_SELECT_SLICE = wx.NewEventType()
  40 +EVT_SELECT_SLICE = wx.PyEventBinder(myEVT_SELECT_SLICE, 1)
  41 +
  42 +myEVT_SELECT_PATIENT = wx.NewEventType()
  43 +EVT_SELECT_PATIENT = wx.PyEventBinder(myEVT_SELECT_PATIENT, 1)
  44 +
  45 +myEVT_SELECT_SERIE_TEXT = wx.NewEventType()
  46 +EVT_SELECT_SERIE_TEXT = wx.PyEventBinder(myEVT_SELECT_SERIE_TEXT, 1)
  47 +
  48 +class SelectEvent(wx.PyCommandEvent):
  49 + def __init__(self , evtType, id):
  50 + super(SelectEvent, self).__init__(evtType, id)
  51 +
  52 + def GetSelectID(self):
  53 + return self.SelectedID
  54 +
  55 + def SetSelectedID(self, id):
  56 + self.SelectedID = id
  57 +
  58 + def GetItemData(self):
  59 + return self.data
  60 +
  61 + def SetItemData(self, data):
  62 + self.data = data
  63 +
  64 +
  65 +class Panel(wx.Panel):
  66 + def __init__(self, parent):
  67 + wx.Panel.__init__(self, parent, pos=wx.Point(5, 5))#,
  68 + #size=wx.Size(280, 656))
  69 +
  70 + sizer = wx.BoxSizer(wx.VERTICAL)
  71 + sizer.Add(InnerPanel(self), 1, wx.EXPAND|wx.GROW|wx.ALL, 5)
  72 +
  73 + self.SetSizer(sizer)
  74 + sizer.Fit(self)
  75 +
  76 + self.Layout()
  77 + self.Update()
  78 + self.SetAutoLayout(1)
  79 +
  80 +
  81 +# Inner fold panel
  82 +class InnerPanel(wx.Panel):
  83 + def __init__(self, parent):
  84 + wx.Panel.__init__(self, parent, pos=wx.Point(5, 5))#,
  85 + #size=wx.Size(680, 656))
  86 +
  87 + self.patients = []
  88 + self.first_image_selection = None
  89 + self.last_image_selection = None
  90 + self._init_ui()
  91 + self._bind_events()
  92 + self._bind_pubsubevt()
  93 +
  94 + def _init_ui(self):
  95 + splitter = spl.MultiSplitterWindow(self, style=wx.SP_LIVE_UPDATE)
  96 + splitter.SetOrientation(wx.VERTICAL)
  97 + self.splitter = splitter
  98 +
  99 + panel = wx.Panel(self)
  100 + self.btn_cancel = wx.Button(panel, wx.ID_CANCEL)
  101 + self.btn_ok = wx.Button(panel, wx.ID_OK, _("Import"))
  102 +
  103 + btnsizer = wx.StdDialogButtonSizer()
  104 + btnsizer.AddButton(self.btn_ok)
  105 + btnsizer.AddButton(self.btn_cancel)
  106 + btnsizer.Realize()
  107 +
  108 + self.combo_interval = wx.ComboBox(panel, -1, "", choices=const.IMPORT_INTERVAL,
  109 + style=wx.CB_DROPDOWN|wx.CB_READONLY)
  110 + self.combo_interval.SetSelection(0)
  111 +
  112 + inner_sizer = wx.BoxSizer(wx.HORIZONTAL)
  113 + inner_sizer.AddSizer(btnsizer, 0, wx.LEFT|wx.TOP, 5)
  114 + inner_sizer.Add(self.combo_interval, 0, wx.LEFT|wx.RIGHT|wx.TOP, 5)
  115 + panel.SetSizer(inner_sizer)
  116 + inner_sizer.Fit(panel)
  117 +
  118 + sizer = wx.BoxSizer(wx.VERTICAL)
  119 + sizer.Add(splitter, 20, wx.EXPAND)
  120 + sizer.Add(panel, 1, wx.EXPAND|wx.LEFT, 90)
  121 +
  122 + self.SetSizer(sizer)
  123 + sizer.Fit(self)
  124 +
  125 + self.image_panel = HostFindPanel(splitter)
  126 + splitter.AppendWindow(self.image_panel, 250)
  127 +
  128 + self.text_panel = TextPanel(splitter)
  129 + splitter.AppendWindow(self.text_panel, 250)
  130 +
  131 +
  132 + self.Layout()
  133 + self.Update()
  134 + self.SetAutoLayout(1)
  135 +
  136 + def _bind_pubsubevt(self):
  137 + #ps.Publisher().subscribe(self.ShowDicomPreview, "Load import panel")
  138 + #ps.Publisher().subscribe(self.GetSelectedImages ,"Selected Import Images")
  139 + pass
  140 +
  141 + def GetSelectedImages(self, pubsub_evt):
  142 + self.first_image_selection = pubsub_evt.data[0]
  143 + self.last_image_selection = pubsub_evt.data[1]
  144 +
  145 + def _bind_events(self):
  146 + self.Bind(EVT_SELECT_SERIE, self.OnSelectSerie)
  147 + self.Bind(EVT_SELECT_SLICE, self.OnSelectSlice)
  148 + self.Bind(EVT_SELECT_PATIENT, self.OnSelectPatient)
  149 + self.btn_ok.Bind(wx.EVT_BUTTON, self.OnClickOk)
  150 + self.btn_cancel.Bind(wx.EVT_BUTTON, self.OnClickCancel)
  151 + self.text_panel.Bind(EVT_SELECT_SERIE_TEXT, self.OnDblClickTextPanel)
  152 +
  153 + def ShowDicomPreview(self, pubsub_evt):
  154 + dicom_groups = pubsub_evt.data
  155 + self.patients.extend(dicom_groups)
  156 + self.text_panel.Populate(dicom_groups)
  157 +
  158 + def OnSelectSerie(self, evt):
  159 + patient_id, serie_number = evt.GetSelectID()
  160 + self.text_panel.SelectSerie(evt.GetSelectID())
  161 + for patient in self.patients:
  162 + if patient_id == patient.GetDicomSample().patient.id:
  163 + for group in patient.GetGroups():
  164 + if serie_number == group.GetDicomSample().acquisition.serie_number:
  165 + self.image_panel.SetSerie(group)
  166 +
  167 + def OnSelectSlice(self, evt):
  168 + pass
  169 +
  170 + def OnSelectPatient(self, evt):
  171 + pass
  172 +
  173 + def OnDblClickTextPanel(self, evt):
  174 + group = evt.GetItemData()
  175 + self.LoadDicom(group)
  176 +
  177 + def OnClickOk(self, evt):
  178 + group = self.text_panel.GetSelection()
  179 +
  180 + if group:
  181 + self.LoadDicom(group)
  182 +
  183 + def OnClickCancel(self, evt):
  184 + #ps.Publisher().sendMessage("Cancel DICOM load")
  185 + pass
  186 +
  187 + def LoadDicom(self, group):
  188 + interval = self.combo_interval.GetSelection()
  189 +
  190 + if not isinstance(group, dcm.DicomGroup):
  191 + group = max(group.GetGroups(), key=lambda g: g.nslices)
  192 +
  193 + slice_amont = group.nslices
  194 + if (self.first_image_selection != None) and (self.first_image_selection != self.last_image_selection):
  195 + slice_amont = (self.last_image_selection) - self.first_image_selection
  196 + slice_amont += 1
  197 + if slice_amont == 0:
  198 + slice_amont = group.nslices
  199 +
  200 + nslices_result = slice_amont / (interval + 1)
  201 + if (nslices_result > 1):
  202 + #ps.Publisher().sendMessage('Open DICOM group', (group, interval,
  203 + # [self.first_image_selection, self.last_image_selection]))
  204 + pass
  205 + else:
  206 + dlg.MissingFilesForReconstruction()
  207 +
  208 +class TextPanel(wx.Panel):
  209 + def __init__(self, parent):
  210 + wx.Panel.__init__(self, parent, -1)
  211 +
  212 + self._selected_by_user = True
  213 + self.idserie_treeitem = {}
  214 + self.treeitem_idpatient = {}
  215 +
  216 + self.__init_gui()
  217 + self.__bind_events_wx()
  218 + self.__bind_pubsub_evt()
  219 +
  220 + def __bind_pubsub_evt(self):
  221 + #ps.Publisher().subscribe(self.SelectSeries, 'Select series in import panel')
  222 + pass
  223 +
  224 + def __bind_events_wx(self):
  225 + self.Bind(wx.EVT_SIZE, self.OnSize)
  226 +
  227 + def __init_gui(self):
  228 + tree = gizmos.TreeListCtrl(self, -1, style =
  229 + wx.TR_DEFAULT_STYLE
  230 + | wx.TR_HIDE_ROOT
  231 + | wx.TR_ROW_LINES
  232 + | wx.TR_COLUMN_LINES
  233 + | wx.TR_FULL_ROW_HIGHLIGHT
  234 + | wx.TR_SINGLE
  235 + )
  236 +
  237 +
  238 + tree.AddColumn(_("Patient name"))
  239 + tree.AddColumn(_("Patient ID"))
  240 + tree.AddColumn(_("Age"))
  241 + tree.AddColumn(_("Gender"))
  242 + tree.AddColumn(_("Study description"))
  243 + tree.AddColumn(_("Modality"))
  244 + tree.AddColumn(_("Date acquired"))
  245 + tree.AddColumn(_("# Images"))
  246 + tree.AddColumn(_("Institution"))
  247 + tree.AddColumn(_("Date of birth"))
  248 + tree.AddColumn(_("Accession Number"))
  249 + tree.AddColumn(_("Referring physician"))
  250 +
  251 + tree.SetMainColumn(0) # the one with the tree in it...
  252 + tree.SetColumnWidth(0, 280) # Patient name
  253 + tree.SetColumnWidth(1, 110) # Patient ID
  254 + tree.SetColumnWidth(2, 40) # Age
  255 + tree.SetColumnWidth(3, 60) # Gender
  256 + tree.SetColumnWidth(4, 160) # Study description
  257 + tree.SetColumnWidth(5, 70) # Modality
  258 + tree.SetColumnWidth(6, 200) # Date acquired
  259 + tree.SetColumnWidth(7, 70) # Number Images
  260 + tree.SetColumnWidth(8, 130) # Institution
  261 + tree.SetColumnWidth(9, 100) # Date of birth
  262 + tree.SetColumnWidth(10, 140) # Accession Number
  263 + tree.SetColumnWidth(11, 160) # Referring physician
  264 +
  265 + self.root = tree.AddRoot(_("InVesalius Database"))
  266 + self.tree = tree
  267 +
  268 + def SelectSeries(self, pubsub_evt):
  269 + group_index = pubsub_evt.data
  270 +
  271 + def Populate(self, patient_list):
  272 + tree = self.tree
  273 +
  274 + first = 0
  275 + for patient in patient_list:
  276 + if not isinstance(patient, dcm.PatientGroup):
  277 + return None
  278 + ngroups = patient.ngroups
  279 + dicom = patient.GetDicomSample()
  280 + title = dicom.patient.name + " (%d series)"%(ngroups)
  281 + date_time = "%s %s"%(dicom.acquisition.date,
  282 + dicom.acquisition.time)
  283 +
  284 + parent = tree.AppendItem(self.root, title)
  285 +
  286 + if not first:
  287 + parent_select = parent
  288 + first += 1
  289 +
  290 + tree.SetItemPyData(parent, patient)
  291 + tree.SetItemText(parent, "%s" % dicom.patient.id, 1)
  292 + tree.SetItemText(parent, "%s" % dicom.patient.age, 2)
  293 + tree.SetItemText(parent, "%s" % dicom.patient.gender, 3)
  294 + tree.SetItemText(parent, "%s" % dicom.acquisition.study_description, 4)
  295 + tree.SetItemText(parent, "%s" % dicom.acquisition.modality, 5)
  296 + tree.SetItemText(parent, "%s" % date_time, 6)
  297 + tree.SetItemText(parent, "%s" % patient.nslices, 7)
  298 + tree.SetItemText(parent, "%s" % dicom.acquisition.institution, 8)
  299 + tree.SetItemText(parent, "%s" % dicom.patient.birthdate, 9)
  300 + tree.SetItemText(parent, "%s" % dicom.acquisition.accession_number, 10)
  301 + tree.SetItemText(parent, "%s" % dicom.patient.physician, 11)
  302 +
  303 + group_list = patient.GetGroups()
  304 + for n, group in enumerate(group_list):
  305 + dicom = group.GetDicomSample()
  306 +
  307 + child = tree.AppendItem(parent, group.title)
  308 + tree.SetItemPyData(child, group)
  309 +
  310 + tree.SetItemText(child, "%s" % group.title, 0)
  311 + tree.SetItemText(child, "%s" % dicom.acquisition.protocol_name, 4)
  312 + tree.SetItemText(child, "%s" % dicom.acquisition.modality, 5)
  313 + tree.SetItemText(child, "%s" % date_time, 6)
  314 + tree.SetItemText(child, "%s" % group.nslices, 7)
  315 +
  316 + self.idserie_treeitem[(dicom.patient.id,
  317 + dicom.acquisition.serie_number)] = child
  318 +
  319 + tree.Expand(self.root)
  320 + tree.SelectItem(parent_select)
  321 + tree.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnActivate)
  322 + tree.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelChanged)
  323 +
  324 + def OnSelChanged(self, evt):
  325 + item = self.tree.GetSelection()
  326 + if self._selected_by_user:
  327 + group = self.tree.GetItemPyData(item)
  328 + if isinstance(group, dcm.DicomGroup):
  329 + #ps.Publisher().sendMessage('Load group into import panel',
  330 + # group)
  331 + pass
  332 +
  333 + elif isinstance(group, dcm.PatientGroup):
  334 + id = group.GetDicomSample().patient.id
  335 + my_evt = SelectEvent(myEVT_SELECT_PATIENT, self.GetId())
  336 + my_evt.SetSelectedID(id)
  337 + self.GetEventHandler().ProcessEvent(my_evt)
  338 +
  339 + #ps.Publisher().sendMessage('Load patient into import panel',
  340 + # group)
  341 + else:
  342 + parent_id = self.tree.GetItemParent(item)
  343 + self.tree.Expand(parent_id)
  344 + evt.Skip()
  345 +
  346 + def OnActivate(self, evt):
  347 + item = evt.GetItem()
  348 + group = self.tree.GetItemPyData(item)
  349 + my_evt = SelectEvent(myEVT_SELECT_SERIE_TEXT, self.GetId())
  350 + my_evt.SetItemData(group)
  351 + self.GetEventHandler().ProcessEvent(my_evt)
  352 +
  353 + def OnSize(self, evt):
  354 + self.tree.SetSize(self.GetSize())
  355 +
  356 + def SelectSerie(self, serie):
  357 + self._selected_by_user = False
  358 + item = self.idserie_treeitem[serie]
  359 + self.tree.SelectItem(item)
  360 + self._selected_by_user = True
  361 +
  362 + def GetSelection(self):
  363 + """Get selected item"""
  364 + item = self.tree.GetSelection()
  365 + group = self.tree.GetItemPyData(item)
  366 + return group
  367 +
  368 +
  369 +
  370 +
  371 +
  372 +
  373 +
  374 +
  375 +
  376 +
  377 +
  378 +
  379 +class FindPanel(wx.Panel):
  380 + def __init__(self, parent):
  381 + wx.Panel.__init__(self, parent, -1)
  382 +
  383 + self.sizer = wx.BoxSizer(wx.VERTICAL)
  384 +
  385 + sizer_word_label = wx.BoxSizer(wx.HORIZONTAL)
  386 + sizer_word_label.Add((5, 0), 0, wx.EXPAND|wx.HORIZONTAL)
  387 + find_label = wx.StaticText(self, -1, _("Word"))
  388 + sizer_word_label.Add(find_label)
  389 +
  390 + sizer_txt_find = wx.BoxSizer(wx.HORIZONTAL)
  391 + sizer_txt_find.Add((5, 0), 0, wx.EXPAND|wx.HORIZONTAL)
  392 + find_txt = wx.TextCtrl(self, -1,size=(225, -1))
  393 +
  394 + self.btn_find = wx.Button(self, -1, _("Search"))
  395 +
  396 +
  397 + sizer_txt_find.Add(find_txt)
  398 + sizer_txt_find.Add(self.btn_find)
  399 +
  400 + self.sizer.Add((0, 5), 0, wx.EXPAND|wx.HORIZONTAL)
  401 + self.sizer.AddSizer(sizer_word_label)
  402 + self.sizer.AddSizer(sizer_txt_find)
  403 +
  404 + #self.sizer.Add(self.serie_preview, 1, wx.EXPAND | wx.ALL, 5)
  405 + #self.sizer.Add(self.dicom_preview, 1, wx.EXPAND | wx.ALL, 5)
  406 + self.sizer.Fit(self)
  407 +
  408 + self.SetSizer(self.sizer)
  409 +
  410 + self.Layout()
  411 + self.Update()
  412 + self.SetAutoLayout(1)
  413 +
  414 + self.__bind_evt()
  415 + self._bind_gui_evt()
  416 +
  417 + def __bind_evt(self):
  418 + #ps.Publisher().subscribe(self.ShowDicomSeries, 'Load dicom preview')
  419 + #ps.Publisher().subscribe(self.SetDicomSeries, 'Load group into import panel')
  420 + #ps.Publisher().subscribe(self.SetPatientSeries, 'Load patient into import panel')
  421 + pass
  422 +
  423 + def _bind_gui_evt(self):
  424 + #self.serie_preview.Bind(dpp.EVT_CLICK_SERIE, self.OnSelectSerie)
  425 + #self.dicom_preview.Bind(dpp.EVT_CLICK_SLICE, self.OnSelectSlice)
  426 + self.Bind(wx.EVT_BUTTON, self.OnButtonFind, self.btn_find)
  427 +
  428 + def OnButtonFind(self, evt):
  429 + print "clicked...."
  430 +
  431 +
  432 +class HostFindPanel(wx.Panel):
  433 + def __init__(self, parent):
  434 + wx.Panel.__init__(self, parent, -1)
  435 + self._init_ui()
  436 + self._bind_events()
  437 +
  438 + def _init_ui(self):
  439 + splitter = spl.MultiSplitterWindow(self, style=wx.SP_LIVE_UPDATE)
  440 + splitter.SetOrientation(wx.HORIZONTAL)
  441 + self.splitter = splitter
  442 +
  443 + splitter.ContainingSizer = wx.BoxSizer(wx.HORIZONTAL)
  444 +
  445 + sizer = wx.BoxSizer(wx.HORIZONTAL)
  446 + sizer.Add(splitter, 1, wx.EXPAND)
  447 + self.SetSizer(sizer)
  448 +
  449 + self.image_panel = NodesPanel(splitter)
  450 + splitter.AppendWindow(self.image_panel, 500)
  451 +
  452 + self.text_panel = FindPanel(splitter)
  453 + splitter.AppendWindow(self.text_panel, 750)
  454 +
  455 + self.SetSizer(sizer)
  456 + sizer.Fit(self)
  457 +
  458 + self.Layout()
  459 + self.Update()
  460 + self.SetAutoLayout(1)
  461 +
  462 + def _bind_events(self):
  463 + self.text_panel.Bind(EVT_SELECT_SERIE, self.OnSelectSerie)
  464 + self.text_panel.Bind(EVT_SELECT_SLICE, self.OnSelectSlice)
  465 +
  466 + def OnSelectSerie(self, evt):
  467 + evt.Skip()
  468 +
  469 + def OnSelectSlice(self, evt):
  470 + self.image_panel.dicom_preview.ShowSlice(evt.GetSelectID())
  471 + evt.Skip()
  472 +
  473 + def SetSerie(self, serie):
  474 + self.image_panel.dicom_preview.SetDicomGroup(serie)
  475 +
  476 +
  477 +class NodesTree(wx.ListCtrl, CheckListCtrlMixin,listmix.ListCtrlAutoWidthMixin,
  478 + listmix.TextEditMixin):
  479 +
  480 + def __init__(self, parent):
  481 + self.item = 0
  482 + self.col_locs = [0]
  483 + self.editorBgColour = wx.Colour(255, 255, 255, 255)
  484 + wx.ListCtrl.__init__(self, parent, -1, style=wx.LC_REPORT |wx.LC_HRULES)
  485 + listmix.CheckListCtrlMixin.__init__(self)
  486 + listmix.TextEditMixin.__init__(self)
  487 +
  488 + def OnCheckItem(self, index, flag):
  489 + ps.Publisher().sendMessage("Check item dict", [index, flag])
  490 +
  491 + def OpenEditor(self, col, row):
  492 +
  493 + if col >= 1 and col < 4:
  494 + listmix.TextEditMixin.OpenEditor(self, col, row)
  495 + else:
  496 + listmix.CheckListCtrlMixin.ToggleItem(self, self.item)
  497 +
  498 + def SetSelected(self, item):
  499 + self.item = item
  500 +
  501 + def SetDeselected(self, item):
  502 + self.item = item
  503 +
  504 +
  505 +class NodesPanel(wx.Panel):
  506 + def __init__(self, parent):
  507 +
  508 + self.selected_item = None
  509 + self.hosts = {}
  510 +
  511 + wx.Panel.__init__(self, parent, -1)
  512 + self.__init_gui()
  513 + self.__bind_evt()
  514 +
  515 +
  516 + def __bind_evt(self):
  517 +
  518 + self.Bind(wx.EVT_COMMAND_RIGHT_CLICK, self.RightButton, self.tree_node)
  519 + self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected, self.tree_node)
  520 + self.Bind(wx.EVT_LIST_ITEM_DESELECTED, self.OnItemDeselected, self.tree_node)
  521 + self.Bind(wx.EVT_BUTTON, self.OnButtonAdd, self.btn_add)
  522 + self.Bind(wx.EVT_BUTTON, self.OnButtonRemove, self.btn_remove)
  523 + self.Bind(wx.EVT_BUTTON, self.OnButtonCheck, self.btn_check)
  524 +
  525 + self.Bind(wx.EVT_LIST_END_LABEL_EDIT, self.EndEdition, self.tree_node)
  526 +
  527 + ps.Publisher().subscribe(self.CheckItemDict, "Check item dict")
  528 + #ps.Publisher().subscribe(self.UnCheckItemDict, "Uncheck item dict")
  529 +
  530 +
  531 + def __init_gui(self):
  532 + self.tree_node = NodesTree(self)
  533 +
  534 + self.tree_node.InsertColumn(0, _("Active"))
  535 + self.tree_node.InsertColumn(1, _("Host"))
  536 + self.tree_node.InsertColumn(2, _("Port"))
  537 + self.tree_node.InsertColumn(3, _("AETitle"))
  538 + self.tree_node.InsertColumn(4, _("Status"))
  539 +
  540 + self.tree_node.SetColumnWidth(0,50)
  541 + self.tree_node.SetColumnWidth(1, 150)
  542 + self.tree_node.SetColumnWidth(2, 50)
  543 + self.tree_node.SetColumnWidth(3, 150)
  544 + self.tree_node.SetColumnWidth(4, 80)
  545 +
  546 + self.hosts[0] = [True, "localhost", "", "invesalius"]
  547 + index = self.tree_node.InsertStringItem(sys.maxint, "")
  548 + self.tree_node.SetStringItem(index, 1, "localhost")
  549 + self.tree_node.SetStringItem(index, 2, "")
  550 + self.tree_node.SetStringItem(index, 3, "invesalius")
  551 + self.tree_node.SetStringItem(index, 4, "ok")
  552 + self.tree_node.CheckItem(index)
  553 + self.tree_node.SetItemBackgroundColour(index, wx.Colour(245,245,245))
  554 + #print ">>>>>>>>>>>>>>>>>>>>>", sys.maxint
  555 + #index = self.tree_node.InsertStringItem(sys.maxint, "")#adiciona vazio a coluna de check
  556 + #self.tree_node.SetStringItem(index, 1, "200.144.114.19")
  557 + #self.tree_node.SetStringItem(index, 2, "80")
  558 + #self.tree_node.SetItemData(index, 0)
  559 +
  560 + #index2 = self.tree_node.InsertStringItem(sys.maxint, "")#adiciona vazio a coluna de check
  561 + #self.tree_node.SetStringItem(index2, 1, "200.144.114.19")
  562 + #self.tree_node.SetStringItem(index2, 2, "80")
  563 + #self.tree_node.SetItemData(index2, 0)
  564 +
  565 + self.btn_add = wx.Button(self, -1, _("Add"))
  566 + self.btn_remove = wx.Button(self, -1, _("Remove"))
  567 + self.btn_check = wx.Button(self, -1, _("Check status"))
  568 +
  569 +
  570 + sizer_btn = wx.BoxSizer(wx.HORIZONTAL)
  571 + sizer_btn.Add((90, 0), 0, wx.EXPAND|wx.HORIZONTAL)
  572 + sizer_btn.Add(self.btn_add, 10)
  573 + sizer_btn.Add(self.btn_remove, 10)
  574 + sizer_btn.Add(self.btn_check, 0, wx.ALIGN_CENTER_HORIZONTAL)
  575 +
  576 + sizer = wx.BoxSizer(wx.VERTICAL)
  577 + sizer.Add(self.tree_node, 85, wx.GROW|wx.EXPAND)
  578 + sizer.AddSizer(sizer_btn, 15)
  579 + sizer.Fit(self)
  580 + self.SetSizer(sizer)
  581 + self.Layout()
  582 + self.Update()
  583 + self.SetAutoLayout(1)
  584 + self.sizer = sizer
  585 +
  586 + def EndEdition(self, evt):
  587 + index = evt.m_itemIndex
  588 + item = evt.m_item
  589 + col = item.GetColumn()
  590 + txt = item.GetText()
  591 +
  592 + values = self.hosts[index]
  593 + values[col] = str(txt)
  594 + self.hosts[index] = values
  595 +
  596 + def OnButtonAdd(self, evt):
  597 + #adiciona vazio a coluna de check
  598 + index = self.tree_node.InsertStringItem(sys.maxint, "")
  599 +
  600 + self.hosts[index] = [True, "localhost", "80", ""]
  601 + self.tree_node.SetStringItem(index, 1, "localhost")
  602 + self.tree_node.SetStringItem(index, 2, "80")
  603 + self.tree_node.SetStringItem(index, 3, "")
  604 + self.tree_node.CheckItem(index)
  605 +
  606 + def OnLeftDown(self, evt):
  607 + evt.Skip()
  608 +
  609 + def OnButtonRemove(self, evt):
  610 + if self.selected_item != None and self.selected_item != 0:
  611 + self.tree_node.DeleteItem(self.selected_item)
  612 + self.hosts.pop(self.selected_item)
  613 + self.selected_item = None
  614 +
  615 + k = self.hosts.keys()
  616 + tmp_cont = 0
  617 +
  618 + tmp_host = {}
  619 + for x in k:
  620 + tmp_host[tmp_cont] = self.hosts[x]
  621 + tmp_cont += 1
  622 + self.hosts = tmp_host
  623 +
  624 +
  625 +
  626 + def OnButtonCheck(self, evt):
  627 + for key in self.hosts.keys():
  628 + if key != 0:
  629 + dn = dcm_net.DicomNet()
  630 + dn.SetHost(self.hosts[key][1])
  631 + dn.SetPort(self.hosts[key][2])
  632 + dn.SetAETitleCall(self.hosts[key][3])
  633 + dn.SetAETitle(self.hosts[0][3])
  634 +
  635 + if dn.RunCEcho():
  636 + self.tree_node.SetStringItem(key, 4, _("ok"))
  637 + else:
  638 + self.tree_node.SetStringItem(key, 4, _("error"))
  639 +
  640 +
  641 +
  642 +
  643 + def RightButton(self,evt):
  644 + event.Skip()
  645 +
  646 + def OnItemSelected(self, evt):
  647 + self.selected_item = evt.m_itemIndex
  648 + self.tree_node.SetSelected(evt.m_itemIndex)
  649 +
  650 + def OnItemDeselected(self, evt):
  651 + if evt.m_itemIndex != 0:
  652 + self.tree_node.SetDeselected(evt.m_itemIndex)
  653 +
  654 +
  655 + def CheckItemDict(self, evt_pub):
  656 + index, flag = evt_pub.data
  657 + if index != 0:
  658 + self.hosts[index][0] = flag
  659 + else:
  660 + self.tree_node.CheckItem(0)
... ...
invesalius/net/__init__.py 0 → 100644
... ... @@ -0,0 +1,18 @@
  1 +#--------------------------------------------------------------------------
  2 +# Software: InVesalius - Software de Reconstrucao 3D de Imagens Medicas
  3 +# Copyright: (C) 2001 Centro de Pesquisas Renato Archer
  4 +# Homepage: http://www.softwarepublico.gov.br
  5 +# Contact: invesalius@cti.gov.br
  6 +# License: GNU - GPL 2 (LICENSE.txt/LICENCA.txt)
  7 +#--------------------------------------------------------------------------
  8 +# Este programa e software livre; voce pode redistribui-lo e/ou
  9 +# modifica-lo sob os termos da Licenca Publica Geral GNU, conforme
  10 +# publicada pela Free Software Foundation; de acordo com a versao 2
  11 +# da Licenca.
  12 +#
  13 +# Este programa eh distribuido na expectativa de ser util, mas SEM
  14 +# QUALQUER GARANTIA; sem mesmo a garantia implicita de
  15 +# COMERCIALIZACAO ou de ADEQUACAO A QUALQUER PROPOSITO EM
  16 +# PARTICULAR. Consulte a Licenca Publica Geral GNU para obter mais
  17 +# detalhes.
  18 +#--------------------------------------------------------------------------
... ...
invesalius/net/dicom.py 0 → 100644
... ... @@ -0,0 +1,26 @@
  1 +import gdcm
  2 +
  3 +class DicomNet:
  4 +
  5 + def __init__(self):
  6 + self.address = ''
  7 + self.port = ''
  8 + self.aetitle_call = ''
  9 + self.aetitle = ''
  10 +
  11 + def SetHost(self, address):
  12 + self.address = address
  13 +
  14 + def SetPort(self, port):
  15 + self.port = port
  16 +
  17 + def SetAETitleCall(self, name):
  18 + self.aetitle_call = name
  19 +
  20 + def SetAETitle(self, ae_title):
  21 + self.aetitle = ae_title
  22 +
  23 + def RunCEcho(self):
  24 + cnf = gdcm.CompositeNetworkFunctions()
  25 + return cnf.CEcho(self.address, int(self.port),\
  26 + self.aetitle, self.aetitle_call)
... ...