예제 #1
0
파일: diwacs.py 프로젝트: diwa-aalto/diwacs
    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()
예제 #2
0
    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()
예제 #3
0
    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()
예제 #4
0
파일: diwacs.py 프로젝트: diwa-aalto/diwacs
    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()
예제 #5
0
    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()
예제 #6
0
파일: diwacs.py 프로젝트: diwa-aalto/diwacs
    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()
예제 #7
0
    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()
예제 #8
0
파일: diwacs.py 프로젝트: diwa-aalto/diwacs
    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()
예제 #9
0
    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()
예제 #10
0
파일: diwacs.py 프로젝트: diwa-aalto/diwacs
    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()
예제 #11
0
    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()
예제 #12
0
파일: diwacs.py 프로젝트: diwa-aalto/diwacs
    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()
예제 #13
0
    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