def OnExit(self, event): """ Exits program. :param event: GraphicalUserInterface Event :type event: Event """ if event and isinstance(event, threads.ContextMenuFailure): error_text = ( 'Socket binding error. You might have multiple instances of ' 'the software running.\n' 'Please wait for them to terminate or use the task manager ' 'to force all of them to quit.\n\n' 'Press OK to start waiting...' ) params = {'message': error_text} show_modal_and_destroy(ErrorDialog, self, params) if not self.exited: try: self.exited = True self.overlay.Destroy() self.Hide() self.trayicon.RemoveIcon() self.trayicon.Destroy() self.trayicon = None self.closebtn.SetToolTip(None) if not event == 'conn_err' and self.diwa_state.is_responsive: LOGGER.debug('On exit self is responsive') self.diwa_state.remove_observer() last_computer = controller.last_active_computer() if not event == 'conn_err' and last_computer: LOGGER.debug('On exit self is last active computer.') controller.unset_activity(diwavars.PGM_GROUP) session_id = self.diwa_state.current_session_id if session_id: controller.end_session(session_id) LOGGER.debug('Application closing...') utils.MapNetworkShare('W:') diwavars.update_responsive(0) sleep(0.5) self.diwa_state.destroy() LOGGER.debug('GraphicalUserInterface closing...') self.Destroy() LOGGER.info('Application closed!') wx.GetApp().ExitMainLoop() except CloseError: raise # Raise without parameter rises the original exception. # This also preseves the original traceback. except Exception as excp: LOGGER.exception('Exception in Close: {0!s}'.format(excp)) for thread in threading.enumerate(): LOGGER.debug(thread.getName()) self.Destroy() wx.GetApp().ExitMainLoop()
def OnExit(self, event): """ Exits program. :param event: GraphicalUserInterface Event :type event: Event """ if event and isinstance(event, threads.ContextMenuFailure): error_text = ( 'Socket binding error. You might have multiple instances of ' 'the software running.\n' 'Please wait for them to terminate or use the task manager ' 'to force all of them to quit.\n\n' 'Press OK to start waiting...') params = {'message': error_text} show_modal_and_destroy(ErrorDialog, self, params) if not self.exited: try: self.exited = True self.overlay.Destroy() self.Hide() self.trayicon.RemoveIcon() self.trayicon.Destroy() self.trayicon = None self.closebtn.SetToolTip(None) if not event == 'conn_err' and self.diwa_state.is_responsive: LOGGER.debug('On exit self is responsive') self.diwa_state.remove_observer() last_computer = controller.last_active_computer() if not event == 'conn_err' and last_computer: LOGGER.debug('On exit self is last active computer.') controller.unset_activity(diwavars.PGM_GROUP) session_id = self.diwa_state.current_session_id if session_id: controller.end_session(session_id) LOGGER.debug('Application closing...') utils.MapNetworkShare('W:') diwavars.update_responsive(0) sleep(0.5) self.diwa_state.destroy() LOGGER.debug('GraphicalUserInterface closing...') self.Destroy() LOGGER.info('Application closed!') wx.GetApp().ExitMainLoop() except CloseError: raise # Raise without parameter rises the original exception. # This also preseves the original traceback. except Exception as excp: LOGGER.exception('Exception in Close: {0!s}'.format(excp)) for thread in threading.enumerate(): LOGGER.debug(thread.getName()) self.Destroy() wx.GetApp().ExitMainLoop()
def SelectProjectDialog(self, event): """ Select project event handler. :param event: GraphicalUserInterface Event. :type event: Event """ if self.diwa_state.current_session: msg = 'Cannot change project during session.' show_modal_and_destroy(ErrorDialog, self, {'message': msg}) return show_modal_and_destroy(ProjectSelectDialog, self) if event: event.Skip()
def OpenProjectDir(self, event): """ Opens project directory in windows explorer. :param event: The GraphicalUserInterface event. :type event: Event """ project_id = self.diwa_state.current_project_id if project_id < 1: return file_path = unicode(Project.get_by_id(project_id).dir) if file_path: os.startfile(file_path, u'explore') else: log_msg = u'Failed explorer: {0}' log_msg = log_msg.format(file_path) LOGGER.exception(log_msg.encode('utf-8')) # FIXME params = {'message': 'Could not open directory.'} show_modal_and_destroy(ErrorDialog, self, params) if event: event.Skip()
def OnPreferences(self, event): """ Preferences dialog event handler. :param event: GraphicalUserInterface Event. :type event: Event """ params = {'config_object': diwavars.CONFIG} show_modal_and_destroy(PreferencesDialog, self, params) try: # Inform other nodes of new name/screen setting and update # your own screen if need be. should_update = False node_manager = self.diwa_state.swnp screens = 0 if 'SCREENS' in diwavars.CONFIG: screens = int(diwavars.CONFIG['SCREENS']) name = 'DEFAULT_NAME' if 'NAME' in diwavars.CONFIG: name = diwavars.CONFIG['NAME'] if 'STATUS_BOX' in diwavars.CONFIG: status_box = literal_eval(diwavars.CONFIG['STATUS_BOX']) diwavars.update_status_box(status_box) if node_manager.node.screens != screens: node_manager.set_screens(screens) should_update = True if node_manager.node.name != name: node_manager.set_name(name) should_update = True if should_update: pub.sendMessage('update_screens', update=True) except (ValueError, IOError, OSError): # TODO: More? LOGGER.exception('Show prefs exception.') if event: event.Skip()
def OnSession(self, event): """ Session button pressed. The user either desires to start a new session or end an existing one. :param event: GraphicalUserInterface Event. :type event: Event """ session_id = self.diwa_state.current_session_id project_id = self.diwa_state.current_project_id if project_id < 1: # We should not ever get here as the button should be disabled! params = {'message': 'No project selected.'} show_modal_and_destroy(ErrorDialog, self, params) elif session_id < 1: # We want to start a new session! try: self.diwa_state.on_session_changed(True) self.EnableSessionButton() session_id = self.diwa_state.current_session_id msg = 'Session started: {0}'.format(session_id) LOGGER.info(msg) except state.SessionChangeException: params = {'message': 'Failed to start a new session!'} LOGGER.exception('Session change failed...') show_modal_and_destroy(ErrorDialog, self, params) except Exception as excp: LOGGER.exception('OnSession exception: {0!s}'.format(excp)) else: # We want to end our session! try: self.diwa_state.on_session_changed(False) self.DisableSessionButton() LOGGER.info('Session ended.') except Exception as excp: LOGGER.exception('OnSession exception: {0!s}'.format(excp)) # TODO: Check all wx.ICON_INFORMATION uses and maybe # create a common dialog for it. params = { 'message': 'Session ended!', 'caption': 'Information', 'style': wx.OK | wx.ICON_INFORMATION } show_modal_and_destroy(wx.MessageDialog, self, params) self.panel.SetFocus() self.Refresh() self.Update() if event: event.Skip()
def __init__(self): # SUPER # kwargs = { 'parent': None, 'title': diwavars.TRAY_TOOLTIP, 'size': diwavars.FRAME_SIZE, 'style': wx.FRAME_NO_TASKBAR } GUItemplate.__init__(self, **kwargs) # UI can not be shown yet. self.Hide() self.Freeze() NodeScreen.update_bitmaps() profiles = ChooseDiwaProfileDialog.ListDatabaseProfiles() if len(profiles): params = {'profiles': profiles} ret = show_modal_and_destroy(ChooseDiwaProfileDialog, None, params) if ret: # If non-zero return value, we should exit LOGGER.info('Application closed!') self.Destroy() wx.GetApp().ExitMainLoop() return # List for choices LOGGER.debug('WxPython version {0!s}'.format(wx.version())) self.list = EventList(self) self.splash_screen = MySplashScreen() self.splash_screen.Show() self.screen_selected = None self.ui_initialized = False self.diwa_state = state.State(parent=self) self.InitUICore() self.diwa_state.initialize() pub.sendMessage('update_screens', update=True) if self.diwa_state.config_was_created: self.OnPreferences(None) # UI can be shown now. self.Thaw() self.Show() # Perform initial testing before actual initialization. initial_test = state.initialization_test() if initial_test: self.splash_screen.Hide() self.splash_screen.Destroy() if initial_test: params = {'message': initial_test} show_modal_and_destroy(ErrorDialog, self, params) self.Destroy() wx.GetApp().ExitMainLoop() return diwavars.set_default_cursor(self.GetCursor()) diwavars.set_blank_cursor(wx.StockCursor(wx.CURSOR_BLANK)) self.overlay = BlackOverlay((0, 0), wx.DisplaySize(), self, '') self.Bind(wx.EVT_SET_FOCUS, self.OnFocus) try: self.trayicon = SysTray(self) self.trayicon.Bind(wx.EVT_MENU, self.OnExit, id=wx.ID_EXIT) self.trayicon.Bind(wx.EVT_MENU, self.OnPreferences, id=wx.ID_SETUP) self.trayicon.Bind(wx.EVT_MENU, self.OnSession, id=wx.ID_NEW) self.trayicon.Bind(wx.EVT_MENU, self.OnAboutBox, id=wx.ID_ABOUT) self.trayicon.Bind(wx.EVT_MENU, self.SelectProjectDialog, id=wx.ID_VIEW_LIST) self.Bind(wx.EVT_CLOSE, self.OnExit) self.trayicon.Bind(wx.EVT_MENU, self.OpenProjectDir, id=wx.ID_INDEX) self.icon = wx.Icon(diwavars.TRAY_ICON, wx.BITMAP_TYPE_PNG) self.trayicon.SetIcon(self.icon, diwavars.TRAY_TOOLTIP) wx.EVT_TASKBAR_LEFT_UP(self.trayicon, self.OnTaskBarActivate) self.Refresh() self.Show(True) self.splash_screen.Hide() self.splash_screen.Destroy() except Exception as excp: LOGGER.exception('load exception: {0!s}'.format(excp)) self.splash_screen.Hide() self.splash_screen.Destroy() self.Destroy()
def handle_file_send(self, filenames, dialog_parameters=None): """ Sends a file link to another node. First parses all the files and folder structure, then confirms weather the users wishes to add the items to project before beginning the copy routine. The copy routine first creates all the needed sub-folders and then sums up all the file sizes to be copied. Then it will update the dialog in the beginning/end of every file transaction and whenever there's been more than 1 second from the last update dialog update. Assuming the dialog_parameters parameter has been given. The progress dialog, if supplied, is updated as follows: - If there's less than DEF_FILES (**40**) files the dialog \ will not be shown or updated. - If the data size sum is less than DEF_SIZE (**2 MB**) the \ dialog will not be shown or updated. - Title will contain the total percentage of data transfer. - Message will contain the percentage of current file transfer. - Progress bar is set to percent [0, 100] of the total data \ transfer. :param filenames: All the files/folders to be copied. :type filenames: List of String :param dialog_parameters: The progress dialog to create by show_modal_and_destroy, initialization parameters in a dictionary. :type dialog_parameters: :py:class:`dict` """ project = self.current_project tpath = os.path.join(diwavars.PROJECT_PATH, 'temp') project_id = 0 if project is not None: tpath = project.dir project_id = project.id src_dst_list = [] returnvalue = [] contains_folders = False mydirs = [] for filename in filenames: is_folder = os.path.isdir(filename) LOGGER.debug('File: %s', filename) if is_folder: contains_folders = True copyroot = filename cidx = len(copyroot) + 1 res = os.path.join(tpath, os.path.basename(filename)) mydirs.append(res) returnvalue.append(res) for (currentroot, dirs, files) in os.walk(copyroot): relativeroot = '' if len(currentroot) > cidx: relativeroot = currentroot[cidx:] targetroot = os.path.join(tpath, os.path.basename(filename), relativeroot) for directory in dirs: temp_path = os.path.join(targetroot, directory) if not os.path.exists(temp_path): mydirs.append(temp_path) # os.makedirs(temp_path) for fname in files: t_source = os.path.join(currentroot, fname) t_destination = os.path.join(targetroot, fname) item = (t_source, t_destination) src_dst_list.append(item) else: path_ = os.path.join(tpath, os.path.basename(filename)) returnvalue.append(path_) src_dst_list.append((filename, path_)) params = { 'message': 'Add the dragged objects to project?', 'caption': 'Add to project?', 'style': (wx.ICON_QUESTION | wx.STAY_ON_TOP | wx.YES_DEFAULT | wx.YES_NO) } if project is None: result = wx.ID_NO else: result = show_modal_and_destroy(wx.MessageDialog, self.parent, params) if contains_folders and result == wx.ID_NO: params = { 'message': ('When dragging folders, you need to add ' 'them to project.'), 'caption': 'Denied action', 'style': (wx.ICON_WARNING | wx.OK | wx.OK_DEFAULT | wx.STAY_ON_TOP) } if project is None: params['message'] = (params['message'] + '\n' 'You also have no project selected ' 'so it is currently not possible for ' 'you to drag-and-drop a folder.\n' 'Please select a project to enable this ' 'functionality.') show_modal_and_destroy(wx.MessageDialog, self.parent, params) return [] if not contains_folders and result == wx.ID_NO: # Change project folders to temp folder. tmp = os.path.join(diwavars.PROJECT_PATH, 'temp') for i, src_dst in enumerate(src_dst_list): src, dst = src_dst dst = dst.replace(tpath, tmp) src_dst_list[i] = (src, dst) for i, directory in enumerate(mydirs): mydirs[i] = directory.replace(tpath, tmp) for i, item in enumerate(returnvalue): returnvalue[i] = item.replace(tpath, tmp) # src_dst_list = [(src, dst.replace(tpath, tmp)) # for (src, dst) in src_dst_list] try: self._handle_file_copy(src_dst_list, mydirs, dialog_parameters) except IOError as excp: LOGGER.exception('MYCOPY: {0!s}'.format(excp)) if result == wx.ID_YES: for src_dst in src_dst_list: controller.create_file_action(src_dst[1], REVERSE_ACTIONS['Created'], self.current_session_id, project_id) return returnvalue