class MyFrame(wx.Frame): results = [] downloads = [] def __init__(self, *args, **kwds): kwds["style"] = wx.DEFAULT_FRAME_STYLE wx.Frame.__init__(self, *args, **kwds) font = wx.Font(9, wx.FONTFAMILY_DEFAULT, style=wx.FONTSTYLE_NORMAL, weight=wx.FONTWEIGHT_NORMAL) self.lbl_query = wx.StaticText(self, -1, " Song: ", style=wx.ALIGN_CENTRE) self.lbl_query.SetFont(font) self.txt_query = wx.TextCtrl(self, 1, "", style=wx.TE_PROCESS_ENTER) self.fb = wx.StaticBitmap(self, bitmap=wx.BitmapFromImage( wx.ImageFromStream( fbicon, wx.BITMAP_TYPE_PNG)), size=(22, 22)) self.folder_chooser = wx.Button( self, -1, "Choose Destination", size=[-1, self.txt_query.GetSize().GetHeight()]) self.lst_results = ObjectListView(self, -1, style=wx.LC_REPORT) self.lst_downloads = GroupListView(self, -1, style=wx.LC_REPORT) self.lst_artists = ObjectListView(self, -1, style=wx.LC_REPORT) self.lst_albums = ObjectListView(self, -1, style=wx.LC_REPORT) self.lst_songs = ObjectListView(self, -1, style=wx.LC_REPORT) self.frame_statusbar = self.CreateStatusBar(1, wx.SB_RAISED) self.__set_properties() self.__do_layout() self.Bind(EVT_EXEC_FUNC, self._ExecFunc) self.Bind(wx.EVT_TEXT_ENTER, self._TextEnter, self.txt_query) self.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self._ResultsContext, self.lst_results) self.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self._ResultsContext, self.lst_songs) self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self._DoubleClick, self.lst_results) self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self._DoubleClick, self.lst_songs) self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self._DoubleClick, self.lst_downloads) self.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self._DownloadsContext, self.lst_downloads) self.Bind(wx.EVT_BUTTON, self._ChooseFolder, self.folder_chooser) self.Bind(wx.EVT_LIST_ITEM_SELECTED, self._ObjectSelected, self.lst_artists) self.Bind(wx.EVT_LIST_ITEM_SELECTED, self._ObjectSelected, self.lst_albums) self.fb.Bind(wx.EVT_LEFT_DOWN, self._FBClick) self.txt_query.Bind(wx.EVT_KEY_DOWN, self._Tab) self.Bind(wx.EVT_CLOSE, self._Close) self.menu_results = {} self.menu_downloads = {} self.menu_results[ID_DOWNLOAD] = "Download" self.menu_downloads[ID_REMOVE] = "Remove" self.artists = [] if sys.platform == 'win32': self.SetIcon(wx.Icon(sys.executable, wx.BITMAP_TYPE_ICO)) else: if os.path.exists("groove.ico"): self.SetIcon(wx.Icon("groove.ico", wx.BITMAP_TYPE_ICO)) def __set_properties(self): self.SetTitle("JTR's Grooveshark Downloader v" + version) self.SetSize((600, 400)) self.frame_statusbar.SetStatusWidths([-1]) frame_statusbar_fields = [""] columns = [ ColumnDefn("Title", "left", 0, valueGetter="SongName", isSpaceFilling=True), ColumnDefn("Album", "center", 0, valueGetter="AlbumName", isSpaceFilling=True), ColumnDefn("Artist", "center", 0, valueGetter="ArtistName", isSpaceFilling=True) ] columns[0].freeSpaceProportion = 2 columns[1].freeSpaceProportion = columns[2].freeSpaceProportion = 1 self.lst_results.SetColumns(columns) self.lst_results.SetObjects(self.results) self.lst_results.SetEmptyListMsg(emptylistmsg) self.lst_results._ResizeSpaceFillingColumns() self.lst_results.useAlternateBackColors = False columns = [ ColumnDefn("Title", "left", 160, valueGetter="filename", groupKeyGetter="album", isSpaceFilling=True), ColumnDefn("Bitrate", "center", 60, valueGetter="bitrate"), ColumnDefn("Speed", "center", 75, valueGetter="speed"), ColumnDefn("Done/Total", "center", 100, valueGetter="size"), ColumnDefn("Progress", "center", 80, valueGetter="progress") ] self.lst_downloads.SetColumns(columns) self.lst_downloads.SetObjects(self.downloads) self.lst_downloads.SetEmptyListMsg("N/A") self.lst_downloads.SortBy(1) self.lst_downloads.useAlternateBackColors = False self.lst_downloads.putBlankLineBetweenGroups = False self.lst_downloads.SetShowGroups(False) columns = [ ColumnDefn("Artist", "center", 100, valueGetter="name", isSpaceFilling=True) ] self.lst_artists.SetColumns(columns) self.lst_artists.SetEmptyListMsg("N/A") self.lst_artists.useAlternateBackColors = False columns = [ ColumnDefn("Album", "center", 100, valueGetter="name", isSpaceFilling=True) ] self.lst_albums.SetColumns(columns) self.lst_albums.SetEmptyListMsg("N/A") self.lst_albums.useAlternateBackColors = False columns = [ ColumnDefn("Song", "center", 100, valueGetter="Name", isSpaceFilling=True) ] self.lst_songs.SetColumns(columns) self.lst_songs.SetEmptyListMsg("N/A") self.lst_songs.useAlternateBackColors = False for i in range(len(frame_statusbar_fields)): self.frame_statusbar.SetStatusText(frame_statusbar_fields[i], i) self.frame_statusbar.SetStatusStyles([wx.SB_FLAT]) self.list_by_mode = self.lst_results def __do_layout(self): self.sizer_1 = wx.BoxSizer(wx.VERTICAL) self.sizer_2 = wx.BoxSizer(wx.HORIZONTAL) self.sizer_3 = wx.BoxSizer(wx.HORIZONTAL) self.sizer_2.Add(self.lbl_query, 0, wx.ALIGN_CENTER, 0) self.sizer_2.Add(self.txt_query, 2, 0, 0) self.sizer_2.Add(self.folder_chooser, 0, wx.ALIGN_CENTER, 0) self.sizer_2.Add(self.fb, 0, wx.ALIGN_CENTER, 0) self.sizer_1.Add(self.sizer_2, 0, wx.EXPAND, 0) self.sizer_1.Add(self.lst_results, 2, wx.EXPAND, 0) self.sizer_1.Add(self.sizer_3, 2, wx.EXPAND, 0) self.sizer_1.Add(self.lst_downloads, 1, wx.EXPAND, 0) self.sizer_3.Add(self.lst_artists, 1, wx.EXPAND, 0) self.sizer_3.Add(self.lst_albums, 1, wx.EXPAND, 0) self.sizer_3.Add(self.lst_songs, 2, wx.EXPAND, 0) self.SetSizer(self.sizer_1) self.sizer_1.Show(self.sizer_3, False) self.Layout() def _TextEnter(self, event): self.artists = [] if self.lbl_query.GetLabel() == " Artist: ": self.lst_albums.DeleteAllItems() self.lst_songs.DeleteAllItems() search_thread = t_search_object(self, _query=event.GetString()) elif self.lbl_query.GetLabel() == " Song: ": search_thread = t_search_flat(self, event.GetString()) search_thread.start() def _ExecFunc(self, event): event.func(self, event) def _FBClick(self, event): webbrowser.open_new_tab('http://www.facebook.com/groove.dl') def _ResultsContext(self, event): menu = wx.Menu() menu.Append(ID_DOWNLOAD, "Download") wx.EVT_MENU(menu, ID_DOWNLOAD, self._ContextSelection) if self.lbl_query.GetLabel() == " Song: ": lst = self.lst_results elif self.lbl_query.GetLabel() == " Artist: ": lst = self.lst_songs self.PopupMenu(menu, event.GetPoint() + lst.GetPosition()) menu.Destroy() def _DownloadsContext(self, event): menu = wx.Menu() for (id, title) in self.menu_downloads.items(): menu.Append(id, title) wx.EVT_MENU(menu, id, self._ContextSelection) self.PopupMenu(menu, event.GetPoint() + self.lst_downloads.GetPosition()) menu.Destroy() def _DoubleClick(self, event): if event.GetEventObject() in [self.lst_results, self.lst_songs]: self._ContextSelection(ID_DOWNLOAD) elif event.GetEventObject() == self.lst_downloads: try: path = os.path.join( dest, self.lst_downloads.GetSelectedObjects()[0]["filename"]) if sys.platform == 'win32': os.startfile(path) elif sys.platform == 'linux2': subprocess.Popen(['xdg-open', path]) except: pass def _ContextSelection(self, event, flag=None): if (event == ID_DOWNLOAD) or (event.GetId() == ID_DOWNLOAD): if self.lbl_query.GetLabel() == " Song: ": lst = self.lst_results name = 'SongName' elif self.lbl_query.GetLabel() == " Artist: ": lst = self.lst_songs name = 'Name' for song in lst.GetSelectedObjects(): filename = format filename = filename.replace( 'artist', strip(song["ArtistName"], "<>:\"/\|?*")) filename = filename.replace('title', strip(song[name], "<>:\"/\|?*")) filename = filename.replace( 'album', strip(song["AlbumName"], "<>:\"/\|?*")) c = 2 while os.path.exists(os.path.join(dest, filename + '.mp3')): filename = filename + ' (%d)' % c c += 1 filename += '.mp3' t = t_download(self, song) t.download = { "progress": "Initializing", "thread": t, "filename": filename, "album": song["AlbumName"] } self.downloads.append(t.download) self.lst_downloads.SetObjects(self.downloads) t.start() elif (flag != None and flag.flag == ID_REMOVE) or (event.GetId() == ID_REMOVE): for d in self.lst_downloads.GetSelectedObjects(): d["thread"].cancelled = True self.downloads.remove(d) self.lst_downloads.RemoveObjects( self.lst_downloads.GetSelectedObjects()) def _ChooseFolder(self, event): global dest dialog = wx.DirDialog( None, "Please choose the destination directory:", os.getenv('USERPROFILE') if sys.platform == 'win32' else os.getenv('HOME')) if dialog.ShowModal() == wx.ID_OK: dest = dialog.GetPath() dialog.Destroy() def _Tab(self, event): if event.GetKeyCode() == 9: if self.lbl_query.GetLabel() == " Song: ": self.sizer_1.Show(self.sizer_3, True) self.sizer_1.Show(self.lst_results, False) self.sizer_1.Layout() self.lbl_query.SetLabel(" Artist: ") self.list_by_mode = self.lst_artists self.lst_downloads.SetShowGroups(True) self.lst_downloads._ResizeSpaceFillingColumns() elif self.lbl_query.GetLabel() == " Artist: ": self.sizer_1.Show(self.sizer_3, False) self.sizer_1.Show(self.lst_results, True) self.sizer_1.Layout() self.lbl_query.SetLabel(" Song: ") self.list_by_mode = self.lst_results self.lst_downloads.SetShowGroups(False) self.lst_downloads._ResizeSpaceFillingColumns() event.Skip() def _ObjectSelected(self, event): if event.GetEventObject() == self.lst_artists: self.lst_albums.DeleteAllItems() self.lst_songs.DeleteAllItems() obj = self.lst_artists.GetSelectedObject() artist_thread = t_search_object(self, obj) artist_thread.start() elif event.GetEventObject() == self.lst_albums: self.lst_songs.SetObjects( self.lst_albums.GetSelectedObject().Songs) def _Close(self, event): l = 0 for i in self.downloads: if i["progress"] != "Completed" and i["progress"] != "Error": l += 1 if l > 0: if wx.MessageDialog( self, "There are currently %d active downloads. Are you sure you want to cancel them and exit ?" % l, "Active downloads", wx.YES_NO | wx.CENTRE).ShowModal() == wx.ID_NO: return print "BWAH" for d in self.downloads: d["thread"].cancelled = True config = ConfigParser.RawConfigParser() config.add_section("groove-dl") config.set("groove-dl", "dest", dest) print "BWAH" config.set("groove-dl", "format", format) config.write(open(os.path.join(conf, "settings.ini"), "wb")) sys.stdout.close() sys.stderr.close() while (threading.active_count() > 3): time.sleep(0.1) os._exit(0)
class SkeletonPanel(wx.Panel): """ Skeleton panel widget """ def __init__(self, parent): super().__init__(parent) self.db_name = "" self.skeleton_results = [] self.session = None self.parent = parent # self.session = controller.connect_to_database() main_sizer = wx.BoxSizer(wx.VERTICAL) search_sizer = wx.BoxSizer(wx.HORIZONTAL) btn_sizer = wx.BoxSizer(wx.HORIZONTAL) font = wx.Font(10, wx.SWISS, wx.NORMAL, wx.NORMAL) # create the search related widgets categories = ["Site", "Location", "Observer", "Skeleton"] search_label = wx.StaticText(self, label=" Filter By:") search_label.SetFont(font) search_sizer.Add(search_label, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT, 5) search_sizer.AddSpacer(5) if platform.system().lower() == 'linux': self.categories = wx.ComboBox(self, value="Skeleton", choices=categories, style=wx.CB_READONLY, size=(150, -1)) else: self.categories = wx.ComboBox(self, value="Skeleton", choices=categories, style=wx.CB_READONLY) search_sizer.Add(self.categories, 0, wx.ALL, 5) search_sizer.AddSpacer(5) if platform.system().lower() == 'linux': self.search_ctrl = wx.SearchCtrl(self, style=wx.TE_PROCESS_ENTER, size=(200, 27)) else: self.search_ctrl = wx.SearchCtrl(self, style=wx.TE_PROCESS_ENTER, size=(200, -1)) # self.search_ctrl.ShowCancelButton(True) self.search_ctrl.SetDescriptiveText('Filter') self.search_ctrl.Bind(wx.EVT_TEXT_ENTER, self.search) search_sizer.Add(self.search_ctrl, 0, wx.ALIGN_CENTER_VERTICAL, 5) search_sizer.AddSpacer(5) self.show_all_btn = wx.Button(self, label="Show All") self.show_all_btn.Bind(wx.EVT_BUTTON, self.on_show_all) search_sizer.Add(self.show_all_btn, 0, wx.ALL, 5) lfont = self.GetFont() lfont.SetPointSize(10) self.skeleton_results_olv = ObjectListView( self, style=wx.LC_REPORT | wx.SUNKEN_BORDER | wx.LC_SINGLE_SEL) self.skeleton_results_olv.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.onDoubleClick) self.skeleton_results_olv.EnableBellOnNoMatch(on=False) self.skeleton_results_olv.SetFont(lfont) self.skeleton_results_olv.SetEmptyListMsg("No Records Found") self.update_skeleton_results() # create the button row self.add_record_btn = wx.Button(self, label="&Add") self.add_record_btn.Bind(wx.EVT_BUTTON, self.add_record) btn_sizer.Add(self.add_record_btn, 0, wx.ALL, 5) self.edit_record_btn = wx.Button(self, label="&Edit") self.edit_record_btn.Bind(wx.EVT_BUTTON, self.edit_record) btn_sizer.Add(self.edit_record_btn, 0, wx.ALL, 5) self.pre_record_btn = wx.Button(self, label="&Preservation") self.pre_record_btn.Bind(wx.EVT_BUTTON, self.edit_preservation) btn_sizer.Add(self.pre_record_btn, 0, wx.ALL, 5) self.delete_record_btn = wx.Button(self, label="&Delete") self.delete_record_btn.Bind(wx.EVT_BUTTON, self.delete_record) btn_sizer.Add(self.delete_record_btn, 0, wx.ALL, 5) self.report_btn = wx.Button(self, label="&Create a report") self.report_btn.Bind(wx.EVT_BUTTON, self.create_report) btn_sizer.Add(self.report_btn, 0, wx.ALL, 5) self.controls_state(False) main_sizer.Add(search_sizer) main_sizer.Add(self.skeleton_results_olv, 1, wx.ALL | wx.EXPAND, 5) main_sizer.Add(btn_sizer, 0, wx.CENTER) self.SetSizer(main_sizer) def controls_state(self, state): self.add_record_btn.Enable(state) self.edit_record_btn.Enable(state) self.pre_record_btn.Enable(state) self.delete_record_btn.Enable(state) self.report_btn.Enable(state) self.show_all_btn.Enable(state) self.search_ctrl.Enable(state) def on_open_file(self, event): wildcard = "DATABASE files (*.db)|*.db" with wx.FileDialog(self, "Choose a file", wildcard=wildcard, style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) as dialog: if dialog.ShowModal() == wx.ID_OK: self.db_name = dialog.GetPath() # zapis w ostatnio używanych plikach self.parent.filehistory.AddFileToHistory(dialog.GetPath()) self.parent.filehistory.Save(self.parent.config) self.parent.config.Flush() if self.session != None: self.skeleton_results_olv.DeleteAllItems() self.parent.SetTitle("{}: ".format(APP_NAME)) self.session.close() self.session = controller.connect_to_database(self.db_name) self.parent.SetTitle("{}: ".format(APP_NAME) + self.db_name) self.controls_state(True) self.show_all_records() def on_create_file(self, event): wildcard = "DATABASE files (*.db)|*.db" with wx.FileDialog(self, "Create a file", wildcard=wildcard, style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) as dialog: if dialog.ShowModal() == wx.ID_OK: self.db_name = dialog.GetPath() # zapis w ostatnio używanych plikach self.parent.filehistory.AddFileToHistory(dialog.GetPath()) self.parent.filehistory.Save(self.parent.config) self.parent.config.Flush() if self.session != None: self.skeleton_results_olv.DeleteAllItems() self.parent.SetTitle("{}: ".format(APP_NAME)) self.session.close() self.session = controller.connect_to_database(self.db_name) self.parent.SetTitle("{}: ".format(APP_NAME) + self.db_name) self.controls_state(True) self.show_all_records() def on_export_file(self, event): """ export db to xlsx """ if self.session == None: dialogs.show_message('No data available for export.', 'Error') return wildcard = "XLSX files (*.xlsx)|*.xlsx" with wx.FileDialog(self, "Export to XLSX", wildcard=wildcard, style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) as dialog: if dialog.ShowModal() == wx.ID_OK: self.xlsx_name = dialog.GetPath() result = controller.export_xlsx(self.session, self.xlsx_name) if result != '': dialogs.show_message(result, 'Error') self.skeleton_results_olv.SetFocus() def add_record(self, event): """ Add a record to the database """ with dialogs.RecordDialog(self.session) as dlg: dlg.CenterOnScreen() dlg.ShowModal() if dlg.result == 1: data = {} data['skeleton_id'] = dlg.skeleton_id data['site'] = dlg.skeleton_dict['site'] data['location'] = dlg.skeleton_dict['location'] data['skeleton'] = dlg.skeleton_dict['skeleton'] data['observer'] = dlg.skeleton_dict['observer'] data['obs_date'] = dlg.skeleton_dict['obs_date'] new_skeleton = olvSkeleton(data) self.skeleton_results_olv.AddObject(new_skeleton) idx = self.skeleton_results_olv.GetIndexOf(new_skeleton) self.skeleton_results_olv.Select(idx) self.skeleton_results_olv.SelectObject(new_skeleton) self.skeleton_results_olv.SetFocus() def edit_skeleton(self): selected_row = self.skeleton_results_olv.GetSelectedObject() active_row = self.skeleton_results_olv.GetIndexOf(selected_row) if selected_row is None: dialogs.show_message('No record selected!', 'Error') return with dialogs.RecordDialog(self.session, selected_row, title='Modify', addRecord=False) as dlg: dlg.CenterOnScreen() dlg.ShowModal() if dlg.result == 1: self.skeleton_results_olv.RefreshObject(selected_row) self.skeleton_results_olv.SetFocus() def edit_record(self, event): """ Edit a record """ self.edit_skeleton() def onDoubleClick(self, event): self.edit_skeleton() def delete_record(self, event): """ Delete a record """ selected_row = self.skeleton_results_olv.GetSelectedObject() row_index = self.skeleton_results_olv.GetIndexOf(selected_row) if selected_row is None: dialogs.show_message('No record selected!', 'Error') return info = 'Delete current record?\n\nSite: {}\nLocation: {}\nSkeleton: {}'.format( selected_row.site, selected_row.location, selected_row.skeleton) if dialogs.ask_message(info, 'Delete record'): controller.delete_record(self.session, selected_row.skeleton_id) self.skeleton_results_olv.RemoveObject(selected_row) if row_index > 0: row_index -= 1 self.skeleton_results_olv.Select(row_index) self.skeleton_results_olv.SetFocus() def edit_preservation(self, event): selected_row = self.skeleton_results_olv.GetSelectedObject() active_row = self.skeleton_results_olv.GetIndexOf(selected_row) if selected_row is None: dialogs.show_message('No record selected!', 'Error') return with dialogs.PreservationDialog(self.session, selected_row) as dlg: dlg.CenterOnScreen() dlg.ShowModal() self.skeleton_results_olv.SetFocus() def show_all_records(self, active_row=0): """ Updates the record list to show all of them """ self.skeleton_results = controller.get_all_records(self.session) self.update_skeleton_results(active_row) def create_report(self, event): """ select report """ dlg = wx.SingleChoiceDialog(self, 'Select report:', 'Create report', [ 'Skull report', 'Skull report - SVG', 'Inventory sheet', 'Full report' ], wx.CHOICEDLG_STYLE) if dlg.ShowModal() == wx.ID_OK: selected = dlg.GetStringSelection() else: selected = '' dlg.Destroy() if selected == '': return if selected == 'Skull report': self.create_report_skull() elif selected == 'Skull report - SVG': self.create_report_skull_svg() else: dialogs.show_message( 'Sorry, report "{}" not ready yet.'.format(selected), 'Error') def create_report_skull(self): """ generating a skeleton report """ filename = "" wildcard = "PDF files (*.pdf)|*.pdf" with wx.FileDialog(self, "Create a report", wildcard=wildcard, style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) as dialog: if dialog.ShowModal() == wx.ID_OK: filename = dialog.GetPath() if filename == "": return my_id = self.skeleton_results_olv.GetSelectedObject().skeleton_id rekord = controller.find_skeleton(self.session, my_id) if rekord == None: dialogs.show_message('No record was found', 'Error') return data = {} data['site'] = rekord.site data['location'] = rekord.location data['skeleton'] = rekord.skeleton data['observer'] = rekord.observer data['obs_date'] = rekord.obs_date # rekord.frontal if rekord.frontal != None else 0 data['frontal'] = rekord.frontal data['sphenoid'] = rekord.sphenoid data['mandible'] = rekord.mandible data['ethmoid'] = rekord.ethmoid data['parietal_l'] = rekord.parietal_l data['parietal_r'] = rekord.parietal_r data['nasal_l'] = rekord.nasal_l data['nasal_r'] = rekord.nasal_r data['palatine_l'] = rekord.palatine_l data['palatine_r'] = rekord.palatine_r data['thyroid'] = rekord.thyroid data['occipital'] = rekord.occipital data['maxilla_l'] = rekord.maxilla_l data['maxilla_r'] = rekord.maxilla_r data['lacrimal_l'] = rekord.lacrimal_l data['lacrimal_r'] = rekord.lacrimal_r data['hyoid'] = rekord.hyoid data['temporal_l'] = rekord.temporal_l data['temporal_r'] = rekord.temporal_r data['zygomatic_l'] = rekord.zygomatic_l data['zygomatic_r'] = rekord.zygomatic_r data['orbit_l'] = rekord.orbit_l data['orbit_r'] = rekord.orbit_r data['calotte'] = rekord.calotte report = SheetExport() result = report.export_sheet(filename, data) if result != '': dialogs.show_message( 'Problems occurred during the creation of the report:\n{}'. format(result), 'Error') self.skeleton_results_olv.SetFocus() def create_report_skull_svg(self): """ generating a skull picture """ filename = "" wildcard = "SVG files (*.svg)|*.svg" with wx.FileDialog(self, "Create a picture", wildcard=wildcard, style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) as dialog: if dialog.ShowModal() == wx.ID_OK: filename = dialog.GetPath() if filename == "": return my_id = self.skeleton_results_olv.GetSelectedObject().skeleton_id rekord = controller.find_skeleton(self.session, my_id) if rekord == None: dialogs.show_message('No record was found', 'Error') return data = {} data['site'] = rekord.site data['location'] = rekord.location data['skeleton'] = rekord.skeleton data['observer'] = rekord.observer data['obs_date'] = rekord.obs_date data['frontal'] = rekord.frontal data['sphenoid'] = rekord.sphenoid data['mandible'] = rekord.mandible data['ethmoid'] = rekord.ethmoid data['parietal_l'] = rekord.parietal_l data['parietal_r'] = rekord.parietal_r data['nasal_l'] = rekord.nasal_l data['nasal_r'] = rekord.nasal_r data['palatine_l'] = rekord.palatine_l data['palatine_r'] = rekord.palatine_r data['thyroid'] = rekord.thyroid data['occipital'] = rekord.occipital data['maxilla_l'] = rekord.maxilla_l data['maxilla_r'] = rekord.maxilla_r data['lacrimal_l'] = rekord.lacrimal_l data['lacrimal_r'] = rekord.lacrimal_r data['hyoid'] = rekord.hyoid data['temporal_l'] = rekord.temporal_l data['temporal_r'] = rekord.temporal_r data['zygomatic_l'] = rekord.zygomatic_l data['zygomatic_r'] = rekord.zygomatic_r data['orbit_l'] = rekord.orbit_l data['orbit_r'] = rekord.orbit_r data['calotte'] = rekord.calotte report = SheetExport() result = report.export_skull_svg(filename, data) if result != '': dialogs.show_message( 'Problems occurred during the creation of the picture:\n{}'. format(result), 'Error') self.skeleton_results_olv.SetFocus() def search(self, event): """ Searches database based on the user's filter choice and keyword """ filter_choice = self.categories.GetValue() keyword = self.search_ctrl.GetValue() self.skeleton_results = controller.search_records( self.session, filter_choice, keyword) self.update_skeleton_results() def on_show_all(self, event): """ Updates the record list to show all the records """ self.show_all_records() def update_skeleton_results(self, active_row=0): """ Updates the ObjectListView's contents """ self.skeleton_results_olv.SetColumns([ ColumnDefn("Site", "left", 350, "site", isSpaceFilling=True, minimumWidth=50), ColumnDefn("Location", "left", 150, "location", isSpaceFilling=True, minimumWidth=50), ColumnDefn("Skeleton", "left", 150, "skeleton", isSpaceFilling=True, minimumWidth=50), ColumnDefn("Observer", "left", 150, "observer", isSpaceFilling=True, minimumWidth=50), ColumnDefn("Observation date", "center", 80, "obs_date", isSpaceFilling=True, minimumWidth=50) ]) self.skeleton_results_olv.SetObjects(self.skeleton_results) if self.skeleton_results_olv.GetItemCount() > 0: self.skeleton_results_olv.Select(active_row) self.skeleton_results_olv.SetFocus()
class PCapMainFrame(wx.Frame): FRAME_VIEW_WIDTH = 480 FRAME_VIEW_HEIGHT = 270 def __init__(self, controller, resources_path): wx.Frame.__init__(self, None) self.control = controller self.resources_path = resources_path self.cam_pos = None self.cam_ray = None self.cam_pos_lock = RLock() self.pointer = 0 self.SetTitle("3-Demeter PlantCapture") self.status_bar = self.CreateStatusBar() self.is_mvs_on = False self.map_points = None self._update_counter = 0 # Creating menus filemenu = wx.Menu() menuAbout = filemenu.Append(wx.ID_ABOUT, "&About", " Information about this program") menuExit = filemenu.Append(wx.ID_EXIT, "E&xit", " Terminate the program") menuBar = wx.MenuBar() menuBar.Append(filemenu, "&File") setmenu = wx.Menu() device_menu_item = setmenu.Append( 0, "&Camera device", " Choose an \ available camera for capturing") scale_menu_item = setmenu.Append(1, "&Scale correction", " Look for a\ scale pattern") menuBar.Append(setmenu, "S&ettings") self.SetMenuBar(menuBar) # Tools actions = { 'cap_new': ('New capture', 'image_add.svg', 'Start new image acquisition', self.OnNewAcq), 'cap_continue': ('Continue', 'image_run.svg', 'Resume acquisition', self.OnResumeAcq), 'cap_pause': ('Pause', 'image_pause.svg', 'Pause acquisition', self.OnPauseAcq), 'cap_finish': ('Finish capture', 'image_stop.svg', 'Finish acquisition', self.OnFinishAcq), 'dir_save_to': ('Save as...', 'folder_downloads.svg', 'Save capture files to a new directory', self.OnSave2Dir), 'dir_open': ('Open...', 'folder_image.svg', 'Open a directory with previously captured frames', self.OnOpenDir), 'mvs_export': ('Export to MVS', 'download.svg', 'Export files to the MVS subsystem', self.OnExportMVS), 'mvs_run': ('Multiple View Stereo', 'tree.svg', 'Start 3-D reconstruction', self.OnMVS), 'norm': ('Normalize', 'size_height_accept.svg', 'Normalize scale and orientation', self.OnNormalize), 'exit': ('Quit', 'logout.svg', 'Exit application', self.OnExit) } # Creating the toolbar self._toolbar = self.CreateToolBar() self._tools = {} tools_list = [ 'cap_new', 'cap_continue', 'cap_pause', 'cap_finish', '|', 'dir_save_to', 'dir_open', 'mvs_export', 'mvs_run', 'norm', '|', 'exit' ] for t in tools_list: if t is '|': self._toolbar.AddSeparator() else: label, icon, help, command = actions[t] bitmap_path = self.resources_path + '/picol/' + icon bitmap = wx.Bitmap(bitmap_path) self._tools[t] = self._toolbar.AddLabelTool(wx.ID_ANY, label, bitmap, shortHelp=help) self.Bind(wx.EVT_TOOL, command, self._tools[t]) self._toolbar.Realize() # Creating the main window self.main_window = wx.SplitterWindow(self, wx.ID_ANY) self.left_pane = wx.Panel(self.main_window, wx.ID_ANY) self.right_pane = wx.Panel(self.main_window, wx.ID_ANY) self.main_window.SplitVertically(self.left_pane, self.right_pane, sashPosition=256) self.main_vsizer = wx.BoxSizer(wx.VERTICAL) self.main_vsizer.Add(self.main_window, 1, wx.EXPAND) # Adding frame list self.keyframes = [] self.frame_list = ObjectListView(self, wx.ID_ANY, style=wx.LC_REPORT) self.frame_list.SetColumns([ ColumnDefn("#", "left", 30, "num"), ColumnDefn("Frame", "left", 100, "frame"), ColumnDefn("Path", "left", 130, "path") ]) self.updateKeyFrames() lsizer = wx.BoxSizer(wx.VERTICAL) lsizer.Add(self.frame_list, 1, wx.EXPAND) self.left_pane.SetSizer(lsizer) lsizer.Fit(self.left_pane) rsizer = wx.BoxSizer(wx.VERTICAL) # Adding frame display self.frame_image = None self.bitmap = wx.EmptyBitmap(PCapMainFrame.FRAME_VIEW_WIDTH, PCapMainFrame.FRAME_VIEW_HEIGHT) pnl_f = wx.Panel(self.right_pane) sb = wx.StaticBox(pnl_f, label='Camera frame') sbs = wx.StaticBoxSizer(sb, orient=wx.HORIZONTAL) sbs.AddSpacer(11) self.frame_view = wx.StaticBitmap(pnl_f, bitmap=self.bitmap) sbs.Add(self.frame_view, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ADJUST_MINSIZE, 10) sbs.AddSpacer(11) pnl_f.SetSizer(sbs) # Adding Mayavi view pnl_m = wx.Panel(self.right_pane) sb = wx.StaticBox(pnl_m, label='3-D Viewer') sbs = wx.StaticBoxSizer(sb, orient=wx.HORIZONTAL) sbs.AddSpacer(11) self.mayavi_view = MayaviView() traits_ui = self.mayavi_view.edit_traits(parent=pnl_m, kind='subpanel') self.mayavi_control = traits_ui.control sbs.Add(self.mayavi_control, 1, wx.CENTER | wx.EXPAND) sbs.AddSpacer(11) pnl_m.SetSizer(sbs) rsizer.Add(pnl_f, 0, wx.LEFT) rsizer.Add(pnl_m, 1, wx.CENTER | wx.EXPAND) self.right_pane.SetSizer(rsizer) rsizer.Fit(self.right_pane) # Set events: self.Bind(wx.EVT_MENU, self.OnAbout, menuAbout) self.Bind(wx.EVT_MENU, self.OnExit, menuExit) self.Bind(wx.EVT_MENU, self.OnSetDevice, device_menu_item) self.Bind(wx.EVT_MENU, self.OnSetScaleCor, scale_menu_item) self.frame_list.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnFrameSelected) self.SetSizer(self.main_vsizer) self.SetAutoLayout(1) self.main_vsizer.Fit(self) self.SetSize((900, 800)) logo_path = self.resources_path + '/splash-logo.png' logo = cv2.imread(logo_path)[:, :, (2, 1, 0)] self.updateFrame(logo, 0) self.viewer_updater = MayaviUpdater(self) def updateFrame(self, frame, frame_num): """Update the bitmap to the frame from new frame event.""" w, h = PCapMainFrame.FRAME_VIEW_WIDTH, PCapMainFrame.FRAME_VIEW_HEIGHT thumbnail = cv2.resize(frame, (w, h)) self.frame_image = wx.ImageFromData(w, h, thumbnail.tostring()) self.bitmap = wx.BitmapFromImage(self.frame_image) self.frame_view.SetBitmap(self.bitmap) if frame_num > 0: h, w, _ = frame.shape msg = 'Frame %d (%d x %d)' % (frame_num, w, h) self.status_bar.SetStatusText(msg) def updateOdometry(self, Tcw): """Add the new odometry data and refresh the 3-D viewer.""" with self.cam_pos_lock: cam_center = Tcw[0:3, 3] cam_center.shape = 1, 3 cam_p_ray = np.dot(Tcw[0:3, 0:3], np.array([0, 0, 1.])) if self.cam_pos is None: self.cam_pos = cam_center.copy() self.cam_ray = cam_p_ray.copy() else: self.cam_pos = np.vstack((self.cam_pos, cam_center)) self.cam_ray = np.vstack((self.cam_ray, cam_p_ray)) def appendKeyFrame(self, frame_num, frame_path, map_points=None): n = len(self.keyframes) + 1 self.keyframes.append({ 'num': n, 'frame': 'Frame %.5d' % frame_num, 'path': frame_path }) self.updateKeyFrames() if map_points is not None: self.map_points = map_points def updateKeyFrames(self): self.frame_list.SetObjects(self.keyframes) def update3DViewer(self): with self.cam_pos_lock: self._update_counter += 1 if self.cam_pos is not None and self.cam_pos.shape[0] > 3: self.mayavi_view.scene.disable_render = True # Update path plot ms = self.mayavi_view.cam_path_plot.mlab_source ms.reset(x=self.cam_pos[:, 0], y=self.cam_pos[:, 1], z=self.cam_pos[:, 2], scalars=np.arange(self.cam_pos.shape[0])) # Update quiver plot (current camera position) ms = self.mayavi_view.cam_pos_plot.mlab_source ms.reset(x=self.cam_pos[-1, 0], y=self.cam_pos[-1, 1], z=self.cam_pos[-1, 2], u=self.cam_ray[-1, 0], v=self.cam_ray[-1, 1], w=self.cam_ray[-1, 2]) # Update the map once each 30 updates if self._update_counter % 30 == 0 \ and self.map_points is not None: ms = self.mayavi_view.map_plot.mlab_source ms.reset(x=self.map_points[:, 0], y=self.map_points[:, 1], z=self.map_points[:, 2]) if self._update_counter == 30: self.mayavi_view.scene.reset_zoom() mlab = self.mayavi_view.scene.mlab dist = la.norm(self.cam_pos[-1] - self.cam_pos[-2]) self.mayavi_view.scene.disable_render = False def loadPLY(self, ply_path, clear_previous=False): self.mayavi_view.scene.disable_render = True with open(ply_path, 'r') as fp: line_num = 0 line = 'X' while len(line) > 0: line = fp.readline() line_num += 1 if line.startswith('end_header'): break data = np.loadtxt(ply_path, skiprows=line_num) X = data[:, 0:3] color = data[:, 6:] s = np.max(color, axis=1) mlab = self.mayavi_view.scene.mlab if clear_previous: mlab.clf() mlab.points3d(X[:, 0], X[:, 1], X[:, 2], s, colormap='gray', mode='point') self.mayavi_view.scene.reset_zoom() self.mayavi_view.scene.disable_render = False def loadOdometry(self, filename): with open(filename, 'r') as f: params = [line.split() for line in f.readlines()] kf_ts = [int(float(p[0])) for p in params] # Translation vectors t = [np.array([float(v) for v in p[1:4]]) for p in params] for ti in t: ti.shape = 3, 1 # q for quaternions q = [np.array([float(v) for v in p[4:]]) for p in params] # Get Tcw Tcw = [] pr = [] for (qx, qy, qz, qw), t_ts in zip(q, t): R = np.array([[ 1 - 2 * qy**2 - 2 * qz**2, 2 * qx * qy - 2 * qz * qw, 2 * qx * qz + 2 * qy * qw ], [ 2 * qx * qy + 2 * qz * qw, 1 - 2 * qx**2 - 2 * qz**2, 2 * qy * qz - 2 * qx * qw ], [ 2 * qx * qz - 2 * qy * qw, 2 * qy * qz + 2 * qx * qw, 1 - 2 * qx**2 - 2 * qy**2 ]]) T_ts = np.hstack((R, t_ts)) pr_ts = np.dot(R, np.array([0, 0, 1.])) Tcw.append(T_ts) pr.append(pr_ts) self.mayavi_view.scene.mlab.clf() self.mayavi_view.scene.mlab.quiver3d([T[0, 3] for T in Tcw], [T[1, 3] for T in Tcw], [T[2, 3] for T in Tcw], [p[0] for p in pr], [p[1] for p in pr], [p[2] for p in pr], opacity=0.5, color=(1, 0, 0), mode='2darrow') if self.map_points is not None: mlab = self.mayavi_view.scene.mlab mlab.points3d(self.map_points[:, 0], self.map_points[:, 1], self.map_points[:, 2], color=(0, 1, 0.2), mode='point') work_dir = os.path.dirname(filename) fpaths = glob.glob(work_dir + os.sep + '*.jpg') fpaths.sort() fnames = [os.path.basename(fpath) for fpath in fpaths] fnums = [re.match('frame\-0*(\d+)\.jpg', fn).group(1) for fn in fnames] fnames = ['Frame %s' % n for n in fnums] self.keyframes = [{ 'num': i + 1, 'frame': fn, 'path': fp } for i, (fn, fp) in enumerate(zip(fnames, fpaths))] self.frame_list.DeleteAllItems() self.updateKeyFrames() def OnAbout(self, e): dlg = wx.MessageDialog(self, "Create 3-D models for plants.", "About 3-Demeter PlantCapture", wx.OK) dlg.ShowModal() dlg.Destroy() def OnSetDevice(self, e): args = ['v4l2-ctl', '--list-devices'] l_cams = subprocess.check_output(args).split('\n') l_cams = [u.strip() for u in l_cams if len(u) > 0] cams = {l_cams[i]: l_cams[i + 1] for i in range(0, len(l_cams), 2)} dialog = wx.SingleChoiceDialog(self, "Select camera device:", "Camera", cams.keys()) if dialog.ShowModal() == wx.ID_OK: sel_device = dialog.GetStringSelection() self.control.set_cap_device(cams[sel_device]) dialog.Destroy() def OnSetScaleCor(self, e): options = { 'Look for scale correction pattern': True, 'Do not perform scale correction': False } dialog = wx.SingleChoiceDialog(self, "Scale correction:", "Options", options.keys()) if dialog.ShowModal() == wx.ID_OK: sel_opt = dialog.GetStringSelection() self.control.setScaleCor(options[sel_opt]) dialog.Destroy() def OnError(self, message): dialog = wx.MessageDialog(self, message, "Error", wx.OK) dialog.ShowModal() dialog.Destroy() def OnNewAcq(self, e): self.viewer_updater.updating = True self.viewer_updater.start() self.control.new_acquisition() def OnResumeAcq(self, e): self.viewer_updater = MayaviUpdater(self) self.viewer_updater.updating = True self.viewer_updater.start() self.control.resume_acquisition() def OnPauseAcq(self, e): self.viewer_updater.updating = False self.control.pause_acquisition() def OnFinishAcq(self, e): for t in ['cap_new', 'cap_continue', 'cap_pause', 'cap_finish']: self._tools[t].Enable(False) self._toolbar.Realize() self.control.finish_acquisition() self.viewer_updater.updating = False def OnSave2Dir(self, e): dlg = wx.DirDialog(self, message="Choose a directory") if dlg.ShowModal() == wx.ID_OK: full_path = dlg.GetPath() self.control.save_capture(full_path) dlg.Destroy() def OnOpenDir(self, e): dlg = wx.DirDialog(self, message="Choose an existing directory", style=wx.DD_DIR_MUST_EXIST) if dlg.ShowModal() == wx.ID_OK: dir_path = dlg.GetPath() self.control.open_cap_dir(dir_path) dlg.Destroy() def OnExportMVS(self, e): self.control.export_to_mvs() def OnMVS(self, e): self.is_mvs_on = True dialog = pp.PyProgress(self, -1, "3-D Reconstruction", "Running PMVS...", agwStyle=wx.PD_APP_MODAL | wx.PD_ELAPSED_TIME) dialog.SetGaugeProportion(0.2) dialog.SetGaugeSteps(50) dialog.SetGaugeBackground(wx.WHITE) dialog.SetFirstGradientColour(wx.WHITE) dialog.SetSecondGradientColour(wx.BLACK) self.control.start_mvs() while self.is_mvs_on: wx.MilliSleep(100) dialog.UpdatePulse() dialog.Destroy() def MVSFinished(self): self.is_mvs_on = False def notify(message, msg_type): if msg_type == 'error': wx.MessageBox(message, 'Error', wx.OK | wx.ICON_ERROR) elif msg_type == 'info': wx.MessageBox(message, 'Info', wx.OK | wx.ICON_INFORMATION) def OnNormalize(self, e): self.control.normalize() def OnExit(self, e): self.Close(True) # Close the frame. def OnFrameSelected(self, event): i = event.GetIndex() kf_data = self.keyframes[i] frame = cv2.imread(kf_data['path']) squares = scale.preprocess_and_find_squares(frame) mapping = scale.detect_markers(frame, squares) frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) pts = [s.reshape((-1, 1, 2)) for s, _ in mapping.values()] frame_rgb = cv2.polylines(frame_rgb, pts, True, (255, 0, 0), thickness=3, lineType=cv2.LINE_AA) for k, (pt, _) in mapping.iteritems(): x, y = pt.mean(axis=0) pos = (int(x), int(y)) cv2.putText(frame_rgb, '%d' % (k), pos, cv2.FONT_ITALIC, 2, (255, 0, 0), 2, cv2.LINE_AA) w, h = PCapMainFrame.FRAME_VIEW_WIDTH, PCapMainFrame.FRAME_VIEW_HEIGHT thumbnail = cv2.resize(frame_rgb, (w, h)) self.frame_image = wx.ImageFromData(w, h, thumbnail.tostring()) self.bitmap = wx.BitmapFromImage(self.frame_image) self.frame_view.SetBitmap(self.bitmap) self.status_bar.SetStatusText('Frame %d' % kf_data['num']) def SetStatus(self, message): self.status_bar.SetStatusText(message)
class BooksDBPanel(wx.Panel): """ A panel for Books database construction. """ def __init__(self, parent): self.engine = None if not os.path.exists("books.db"): self.CreateDB("books.db") else: self.engine = create_engine("sqlite:///books.db") self.session = sqlafuns.getsqlsess(self.engine) super().__init__(parent) vsizer = VBoxSizer() hsizer1 = wx.BoxSizer() combolab = wx.StaticText(self, label="Pick a table:") self.tablenames = [BookTable.__tablename__, SeriesTable.__tablename__] self.tablecombo = wx.Choice(self, choices=self.tablenames) self.tablecombo.SetSelection(0) self.tablecombo.Bind(wx.EVT_CHOICE, self.OnChoice) self.current_table = self.tablecombo.GetStringSelection() hsizer1.Add(combolab) hsizer1.Add(self.tablecombo) vsizer.Add(hsizer1, 0, wx.CENTER) self.olvtable = ObjectListView(self, style=wx.LC_REPORT) vsizer.Add(self.olvtable, 1, wx.EXPAND) hsizer2 = wx.BoxSizer() addbtn = wx.Button(self, label="Add a row") addbtn.Bind(wx.EVT_BUTTON, self.OnAdd) hsizer2.Add(addbtn) editbtn = wx.Button(self, label="Edit a row") editbtn.Bind(wx.EVT_BUTTON, self.OnEdit) hsizer2.Add(editbtn) delbtn = wx.Button(self, label="Delete a row") delbtn.Bind(wx.EVT_BUTTON, self.OnDelete) hsizer2.Add(delbtn) vsizer.Add(hsizer2, 0, wx.CENTER) self.SetSizer(vsizer) self.AddCols("book") def CreateDB(self, dbfilename): self.engine = create_engine(f"sqlite:///{dbfilename}") Base.metadata.create_all(self.engine) def AddCols(self, current_table): self.olvtable.ClearAll() if current_table == "book": self.olvtable.SetColumns([ ColumnDefn("Book Id", "left", 50, "book_id"), ColumnDefn("Title", "left", 200, "title"), ColumnDefn("Author", "left", 200, "author"), ColumnDefn("Copyright Year", 'left', 200, "copyright_year"), ColumnDefn("Series", "left", 200, "seriesname") ]) elif current_table == "series": self.olvtable.SetColumns([ ColumnDefn("Series Id", "left", 50, "series_id"), ColumnDefn("Series Name", "left", 200, "seriesname"), ColumnDefn("Books Total", "left", 200, "bookstotal") ]) self.ShowAll(current_table) def ShowAll(self, current_table): self.olvtable.DeleteAllItems() if current_table == "book": result = self.session.query( BookTable.book_id, BookTable.title, BookTable.author, BookTable.copyright_year, SeriesTable.seriesname).join(SeriesTable) for row in result: rowinstance = OlvBookTable(row.book_id, row.title, row.author, row.copyright_year, row.seriesname) self.olvtable.AddObject(rowinstance) elif current_table == "series": result = self.session.query(SeriesTable) for row in result: rowinstance = OlvSeriesTable(row.series_id, row.seriesname, row.bookstotal) self.olvtable.AddObject(rowinstance) def OnChoice(self, event): self.current_table = self.tablecombo.GetStringSelection() self.AddCols(self.current_table) event.Skip() def OnAdd(self, event): if self.current_table == "book": AddRowtoBookDBDialog(self).ShowModal() elif self.current_table == "series": AddRowtoSeriesDBDialog(self).ShowModal() self.ShowAll(self.current_table) event.Skip() def OnEdit(self, event): rowobj = self.olvtable.GetSelectedObject() if self.current_table == "book": EditBookRowDialog(self, rowobj=rowobj).ShowModal() elif self.current_table == "series": EditSeriesRowDialog(self, rowobj=rowobj).ShowModal() self.ShowAll(self.current_table) event.Skip() def OnDelete(self, event): rowobj = self.olvtable.GetSelectedObject() if self.current_table == "book": target = self.session.query(BookTable).filter_by( book_id=rowobj.book_id).one() self.session.delete(target) self.session.commit() self.session.close() if self.current_table == "series": target = self.session.query(SeriesTable).filter_by( book_id=rowobj.book_id).one() self.session.delete(target) self.session.commit() self.session.close() self.ShowAll(self.current_table) event.Skip()
class PanelLogs(wx.Panel): lock = threading.RLock() def __init__(self, parentNotebook, frame_myr, size=None, style=wx.BORDER_DEFAULT): wx.Panel.__init__(self, parent=parentNotebook, size=size, id=wx.ID_ANY, style=style) self.parentNotebook = parentNotebook self.frame_myr = frame_myr self.logPath = self.frame_myr.notebook.getTempConfigParam("logPath") self.wvLogs = webview.WebView.New(self) self.selection = None #scrollPanel = wx.Panel(self) self.listLogs = ObjectListView(self, size=(108, -1), style=wx.LC_REPORT, sortable=False) self.listLogs.oddRowsBackColor = wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW) self.listLogs.SetColumns([ ColumnDefn("Log File", "center", 94, "log") ]) self.listLogs.SetFont(wx.Font(8.5, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False)) self.loadList() self.listLogs.Bind(wx.EVT_LIST_ITEM_SELECTED, self.onLogSelected) self.listLogs.Bind(wx.EVT_COMMAND_RIGHT_CLICK, self.OnRightClick) self.wvLogs.Bind(webview.EVT_WEBVIEW_TITLE_CHANGED, self.onFocusLost) sizer = wx.BoxSizer(wx.HORIZONTAL) self.wvLogs.SetPage('<html><body style="background-color: #111111;"></body></html>', "") sizer.Add(self.wvLogs, 1, wx.EXPAND | wx.BOTTOM | wx.LEFT | wx.TOP, -3) sizer.Add(self.listLogs, 0, wx.EXPAND | wx.LEFT, 0) self.SetSizer(sizer) def onFocusLost(self, event): self.listLogs.SetFocus() event.Skip() def loadList(self): with self.lock: self.logPath = self.frame_myr.notebook.getTempConfigParam("logPath") if not self.logPath or not os.path.isdir(self.logPath): self.listLogs.DeleteAllItems() return logFiles = [ {"log": os.path.splitext(f)[0] } for f in reversed(listdir(self.logPath)) if isfile(join(self.logPath, f)) and f.endswith('.html') ] self.listLogs.DeleteAllItems() self.listLogs.SetObjects(logFiles) if self.selection is not None: try: self.listLogs.SelectObjects([self.selection]) except IndexError: self.selection = None self.listLogs.SetFocus() def onLogSelected(self, event): self.selection = self.listLogs.GetObjects()[event.GetEventObject().GetFirstSelected()] self.onLogSelectedIndex(self.selection) self.listLogs.SetFocus() event.Skip() def onLogSelectedIndex(self, selectedObj): #logFile = event.GetEventObject().GetValue(self.selection, 0) #logFile = self.listLogs.GetValue(index, 0) logFile = selectedObj['log'] self.loadLogFile(logFile) def loadLogFile(self, logFile): f = open(self.logPath + "/" + logFile + ".html") html = f.read() f.close() self.onLog(html) def onLog(self, html): self.wvLogs.SetPage(html, "") self.wvLogs.Reload() def reloadLog(self): #self.wvLogs.Reload() if self.selection: self.loadLogFile(self.selection['log']) def OnRightClick(self, event): #self.log.WriteText("OnRightClick %s\n" % self.list.GetItemText(self.currentItem)) # only do this part the first time so the events are only bound once if not hasattr(self, "popupID1"): self.popupOpenLocation = wx.NewId() self.popupDelete = wx.NewId() self.Bind(wx.EVT_MENU, self.onPopUpOpenLocation, id=self.popupOpenLocation) self.Bind(wx.EVT_MENU, self.onPopUpDelete, id=self.popupDelete) # make a menu menu = wx.Menu() # add some items menu.Append(self.popupOpenLocation, "Open file location") menu.Append(self.popupDelete, "Delete files...") # Popup the menu. If an item is selected then its handler # will be called before PopupMenu returns. self.PopupMenu(menu) menu.Destroy() def onPopUpOpenLocation(self, event): if os.name == "nt": #os.spawnl(os.P_NOWAIT, os.getenv('windir') + '\\explorer.exe', '.', '/n,/e,/select,"%s"'%self.logPath+"\\") psutil.Popen('explorer ' + '"' + self.logPath + '"') if os.name == "posix": pass def onPopUpDelete(self, event): question = "Are you sure you want to delete those files?" dlg = GMD.GenericMessageDialog(self, question, "Confirm deletion", wx.YES_NO | wx.NO_DEFAULT | wx.ICON_WARNING) result = dlg.ShowModal() == wx.ID_YES dlg.Destroy() if result: selected = self.listLogs.GetSelectedObjects() for file in selected: os.remove(self.logPath + '/' + file['log'] + '.html') self.loadList()