Beispiel #1
0
class PayloadView:
    """
    PayloadView is a TextView viewer and editor.
    """
    def __init__(self, payload=None, label=None):
        if not label: label = "PayloadView"

        self.this = JPanel()
        self.this.setLayout(BorderLayout())

        # Add a label
        self.this.add(BorderLayout.PAGE_START, JLabel(label))

        # Create textarea here and add to the JPanel
        scrollPane = JScrollPane()
        self._textarea = JTextArea()
        self._textarea.setColumns(20)
        self._textarea.setRows(5)
        self._textarea.setLineWrap(True)
        self._textarea.setWrapStyleWord(True)
        self._textarea.setEditable(True)
        self._textarea.setName("TextArea")
        self._textarea.setSelectionColor(Color(255, 153, 51))
        self._textarea.requestFocus()
        scrollPane.setViewportView(self._textarea)
        self.this.add(BorderLayout.CENTER, scrollPane)

        self.refresh(payload)

    def set_editable(self, editable):
        """
        Enable or Disable the editable textview

        :param editable: boolean parameter representing the editability
        :return: None
        """
        self._textarea.setEditable(editable)

    def refresh(self, payload):
        """
        Refresh the textarea content with a new payload, if present

        :param payload:
        :return: None
        """
        if payload:
            self._textarea.setText(payload)

    def add_listener(self, listener):
        """
        add a new listener to the textarea

        :param listener: this parameter should be a lambda or a method
        :return: None
        """
        self._textarea.getDocument().addDocumentListener(
            _PayloadListener(listener))
Beispiel #2
0
class ConsoleView(JPanel):
    '''
    Initializes the console view and sets its layout.
    '''
    def __init__(self, controller):
        '''
        Creates default empty console-looking panel.
        It should be separated from the rest of the GUI so that users can
        choose to show or hide the console. Or should it be a split panel?
        This panel will display log and validation/lemmatization messages.
        It might need its own toolbar for searching, etc.
        It will also accept commands in later stages of development, if need
        be.
        '''
        # Give reference to controller to delegate action response
        self.controller = controller

        # Make text area occupy all available space and resize with parent
        # window
        self.setLayout(BorderLayout())

        # Create console-looking area
        self.edit_area = JTextArea()
        self.edit_area.setLineWrap(True)
        self.edit_area.setWrapStyleWord(True)
        self.edit_area.border = BorderFactory.createEmptyBorder(4, 4, 4, 4)
        self.edit_area.font = Font("Courier New", Font.BOLD, 14)
        self.edit_area.background = Color.BLACK
        self.edit_area.foreground = Color.WHITE

        # Disable writing in the console
        self.edit_area.setEditable(False)

        # Will need scrolling controls
        scrollingText = JScrollPane(self.edit_area)
        scrollingText.setPreferredSize(Dimension(1, 150))

        # Make text area auto scroll down to last printed line
        caret = self.edit_area.getCaret()
        caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE)

        # Add to parent panel
        self.add(scrollingText, BorderLayout.CENTER)

    def scroll(self):
        '''
        Scroll down to bottom.
        '''
        length = self.edit_area.getDocument().getLength()
        self.edit_area.setCaretPosition(length)
Beispiel #3
0
class ConsoleView(JPanel):

    def __init__(self, controller):
        '''
        Creates default empty console-looking panel.
        It should be separated from the rest of the GUI so that users can choose
        to show or hide the console. Or should it be a split panel?
        This panel will display log and validation/lemmatization messages.
        It might need its own toolbar for searching, etc.
        It will also accept commands in later stages of development, if need be.
        '''

        # Give reference to controller to delegate action response
        self.controller = controller

        # Make text area occupy all available space and resize with parent window
        self.setLayout(BorderLayout())

        #Create console-looking area
        self.editArea = JTextArea()
        self.editArea.border = BorderFactory.createEmptyBorder(4,4,4,4)
        self.editArea.font = Font("Courier New", Font.BOLD, 14)
        self.editArea.background = Color.BLACK
        self.editArea.foreground = Color.WHITE
        self.editArea.text = "Console started. Nammu's log will appear here.\n\n"

        # Disable writting in the console
        self.editArea.setEditable(False)

        # Will need scrolling controls
        scrollingText = JScrollPane(self.editArea)
        scrollingText.setPreferredSize(Dimension(1,150))

        # Make text area auto scroll down to last printed line
        caret = self.editArea.getCaret();
        caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);

        # Add to parent panel
        self.add(scrollingText, BorderLayout.CENTER)


    def scroll(self):
        '''
        Scroll down to bottom.
        '''
        self.editArea.setCaretPosition(self.editArea.getDocument().getLength())
Beispiel #4
0
    def _create_texteditor(self, name=None, label=None):
        _textarea = None

        if name and name in self._widgets:
            return self._widgets[name]

        if not name:
            name = "TextArea#%s" % self._idx
            self._idx += 1

        this = JPanel()

        # Add a label
        if label:
            this.setLayout(BorderLayout())
            this.add(BorderLayout.PAGE_START, JLabel(label))

        if self._texteditor_factory:
            _texteditor = self._texteditor_factory()
            _component = _texteditor.getComponent()
            this.add(BorderLayout.CENTER, _component)
            _textarea = self._get_textarea(_component)

        if not _textarea:
            _textarea = JTextArea()
            _textarea.setColumns(20)
            _textarea.setRows(5)
            _textarea.setLineWrap(True)
            _textarea.setWrapStyleWord(True)
            _textarea.setEditable(True)
            _textarea.setName(name)
            _textarea.setSelectionColor(Color(255, 153, 51))
            _textarea.requestFocus()
            # Add textarea to a scrollable JPane
            _scrollpane = JScrollPane()
            _scrollpane.setViewportView(_textarea)
            this.add(BorderLayout.CENTER, _scrollpane)

        _textarea.setEditable(self.editable)

        self._textareas[name] = _textarea
        self._widgets[name] = this

        def on_change(evt):
            if not self._textareas[name].hasFocus():
                return
            try:
                if name == "raw":
                    SwingUtilities.invokeLater(lambda: self._refresh_queries(
                        self._textareas['raw'].getText()))
                elif name.startswith('gql_query#'):
                    id = int(name.split("#")[1])
                    content = json.loads(self._textareas['raw'].getText())
                    if id == 0 and not isinstance(content, list):
                        content['query'] = self._textareas[name].getText()
                    else:
                        content[id]['query'] = self._textareas[name].getText()
                    SwingUtilities.invokeLater(lambda: self._textareas['raw'].
                                               setText(json.dumps(content)))
                elif name.startswith('gql_variables#'):
                    id = int(name.split("#")[1])
                    content = json.loads(self._textareas['raw'].getText())
                    if id == 0 and not isinstance(content, list):
                        content['variables'] = json.loads(
                            self._textareas[name].getText())
                    else:
                        content[id]['variables'] = json.loads(
                            self._textareas[name].getText())
                    SwingUtilities.invokeLater(lambda: self._textareas['raw'].
                                               setText(json.dumps(content)))
            except ValueError:
                pass  # Avoid crashing for JSON not valid incompatibilities

        _textarea.getDocument().addDocumentListener(
            _PayloadListener(changed_update=on_change))

        return this
Beispiel #5
0
    class ConsoleController:
        def __init__(self, parent):
            self._parent = parent
            self._sessions = self._parent.sessions()
            self._request = None #TODO I'll need a request in order to connect to something
            self._position = None #TODO I'll need a position, something to change in the header to insert the command
            self._pwd = None
            self._commandHistory = []
            self._historyIndex = 0
            self._tabComplete = []

        def getMainComponent(self):
            self._mainPanel = JPanel(BorderLayout())
            # input
            self._consolePwd = JTextField()
            self._consolePwd.setEditable(False)
            self._consolePwd.setText("Not initialized")
            self._consoleInput = JTextField()
            #Remove 'tab' low-level tab-function of jumping to other component, so I can use it
            self._consoleInput.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, Collections.EMPTY_SET)
            self._consoleInput.addActionListener(self.EnterPress())
            self._consoleInput.addKeyListener(self.KeyPress())
            self._inputPanel = JPanel(BorderLayout())
            self._inputPanel.add(self._consolePwd, BorderLayout.WEST)
            self._inputPanel.add(self._consoleInput, BorderLayout.CENTER)
            # output
            self._consoleOutput = JTextArea()
            self._consoleOutput.setEditable(False)
            self._consoleOutput.setForeground(Color.WHITE)
            self._consoleOutput.setBackground(Color.BLACK)
            self._consoleOutput.setFont(self._consoleOutput.getFont().deriveFont(12.0))

            self._scrollPaneConsoleOutput = JScrollPane(self._consoleOutput)

            # Add to main panel and return the main panel
            self._mainPanel.add(self._scrollPaneConsoleOutput, BorderLayout.CENTER)
            self._mainPanel.add(self._inputPanel, BorderLayout.SOUTH)
            return self._mainPanel

        def sendCommand(self, requestId, cmd, directTo):
            Utils.out("ConsoleController > sendCommand > 'cmd'")
            Utils.out(cmd)
            if cmd == 'clear':
                self.resetOutput()
                self._commandHistory.append(cmd)
                self.resetHistoryIndex()
                self.clearCmd()
                return
            cmdModified = cmd
            requestHttpMethod = self._parent.getRequestHttpService(requestId)
            #If I use virtual persistence and there's already a pwd set
            if Utils.shellController._virtualPersistence and self.pwd():
                #Then always prepend 'cd <pwd>' to any command executed. In reality we
                # always enter in the same directory, but because this shell keeps track
                # of where the user thinks he is, and always goes to that directory first
                # the illusion of a persistence is created
                cmdVirtual = "cd " + self.pwd()
                cmdModified = cmdVirtual + "; " + cmd
            requestWithCommand = self._parent.getRequestWithCommand(requestId, cmdModified)
            Thread(GetThreadForRequest(requestHttpMethod, requestWithCommand, directTo)).start()
            self._commandHistory.append(cmd)
            self.resetHistoryIndex()
            self.clearCmd()

            if Utils.shellController._virtualPersistence:
                if cmd.startswith('cd '):
                    Utils.out("ConsoleController > sendCommand: detected 'cd '")
                    #ask for pwd
                    cmdPwd = cmdModified + "; " + Commands.pwd(Commands.OS_LINUX)
                    requestWithCommand = self._parent.getRequestWithCommand(requestId, cmdPwd)
                    Thread(GetThreadForRequest(requestHttpMethod, requestWithCommand, 'pwd')).start()
                if Utils.shellController._tabCompletion:
                    #ask 'ls -1a' for tab-completion
                    # The first command, pwd is set here, but cmdVirtual ain't. But this
                    # also means we are at the entry directory anyway, so we can just ask ls
                    # and get the correct tab completion anyway
                    try:
                        cmdTabComplete = cmdVirtual + "; " + Commands.ls(Commands.OS_LINUX)
                    except:
                        cmdTabComplete = Commands.ls(Commands.OS_LINUX)
                    requestWithCommand = self._parent.getRequestWithCommand(requestId, cmdTabComplete)
                    Thread(GetThreadForRequest(requestHttpMethod, requestWithCommand, 'tabComplete')).start()
            else:
                if Utils.shellController._tabCompletion:
                    cmdTabComplete = Commands.ls(Commands.OS_LINUX)
                    requestWithCommand = self._parent.getRequestWithCommand(requestId, cmdTabComplete)
                    Thread(GetThreadForRequest(requestHttpMethod, requestWithCommand, 'tabComplete')).start()

            #either way execute the requested command

        def startSession(self):
            #TODO when starting a session I want to test for a number of things:
            # if I can reform the request to a post request and still have it work
            # if base 64 is available
            # if bash is available
            self.setPwd(None)
            if Utils.shellController._virtualPersistence and Utils.shellController._outputIsolator:
                Utils.out("startSession > virtualPersistence enabled > Requesting pwd")
                self.sendCommand(self._parent.currentRequestId(), Commands.pwd(Commands.OS_LINUX), 'pwd')

        def appendOutput(self, text, printCommand=True):
            try:
                if printCommand:
                    self.printCommand(self._commandHistory[-1])
            except:
                pass

            self._consoleOutput.append("\n" + text)
            #auto scroll down if needed
            self._consoleOutput.setCaretPosition(self._consoleOutput.getDocument().getLength())

        def resetOutput(self):
            Utils.setConsole('')

        def printCommand(self, cmd):
            self._consoleOutput.append("\n" + self._pwd + "# " + cmd)

        def printCurrentCommand(self):
            self.printCommand(self.cmd())

        def setPwd(self, pwd):
            self._pwd = pwd
            if pwd is None:
                self._consolePwd.setText('')
            else:
                self._consolePwd.setText(pwd)
            Utils.consoleController._mainPanel.revalidate()

        def pwd(self):
            return self._pwd

        def cmdHistoryCount(self):
            return len(self._commandHistory) #TODO - 1

        def setCmd(self, cmd):
            self._consoleInput.setText(cmd)

        def cmd (self):
            return self._consoleInput.getText()

        def clearCmd(self):
            self._consoleInput.setText('')

        def resetHistoryIndex(self):
            self._historyIndex = self.cmdHistoryCount()

        def previousCommand(self):
            if self._historyIndex > 0:
                self._historyIndex -= 1
                self.setCmd(self._commandHistory[self._historyIndex])

        def nextCommand(self):
            if self._historyIndex < self.cmdHistoryCount():
                self._historyIndex += 1
                self.setCmd(self._commandHistory[self._historyIndex])
            else:
                self.clearCmd()
                self.resetHistoryIndex()

        def setTabComplete(self, text):
            self._tabComplete = text.splitlines()

        def findTabComplete(self, beginCharacters=''):
            suggestions = []
            if beginCharacters:
                for suggestion in self._tabComplete:
                    Utils.debug("suggestion", suggestion)
                    Utils.debug("text", beginCharacters)
                    if suggestion[0:len(beginCharacters)] == beginCharacters:
                        suggestions.append(suggestion)
            else:
                suggestions = self._tabComplete
            return suggestions

        def tabComplete(self):
            currentCommand = self.cmd()
            Utils.debug("currentCommand", currentCommand)
            if currentCommand:
                commandArray = currentCommand.split(' ')
                lastword = commandArray.pop()
                Utils.debug("lastword", lastword)
                suggestions = self.findTabComplete(lastword)
                if suggestions:
                    if len(suggestions) > 1:
                        self.printCurrentCommand()
                        for suggestion in suggestions:
                            self.appendOutput(suggestion, False)
                    if len(suggestions) == 1:
                        self.setCmd(' '.join(commandArray) + ' ' + suggestions.pop())
            else:
                suggestions = self.findTabComplete()
                if len(suggestions) > 1:
                    self.printCurrentCommand()
                    for suggestion in suggestions:
                        self.appendOutput(suggestion, False)

        class EnterPress(ActionListener): #TODO remove: AbstractAction
            def actionPerformed(self, e):
                Utils.consoleController.sendCommand(Utils.shellController.currentRequestId(), Utils.consoleInput.getText(), 'console')

            def keyPressed(self, e):
                Utils.out("key pressed")

        class KeyPress(KeyListener):
            def keyTyped(self, e):
                pass

            def keyReleased(self, e):
                if e.getKeyCode() == e.VK_DOWN:
                    Utils.consoleController.nextCommand()
                    Utils.out("released down")
                if e.getKeyCode() == e.VK_UP:
                    Utils.consoleController.previousCommand()
                    Utils.out("released up")

                if e.getKeyCode() == e.VK_TAB:
                    Utils.out("pressed tab")
                    Utils.consoleController.tabComplete()

            def keyPressed(self, e):
                pass
class JythonGui(ItemListener):
    def __init__(self, instructionsURI=''):
        self.instructionsURI = instructionsURI

        self.logger = logging.getLogger('sasi_runner_gui')
        self.logger.addHandler(logging.StreamHandler())
        def log_fn(msg):
            self.log_msg(msg)
        self.logger.addHandler(FnLogHandler(log_fn))
        self.logger.setLevel(logging.DEBUG)

        self.selected_input_file = None
        self.selected_output_file = None

        self.frame = JFrame(
            "SASI Runner",
            defaultCloseOperation = WindowConstants.EXIT_ON_CLOSE,
        )
        self.frame.size = (650, 600,)

        self.main_panel = JPanel()
        self.main_panel.layout = BoxLayout(self.main_panel, BoxLayout.Y_AXIS)
        self.frame.add(self.main_panel)

        self.top_panel = JPanel(SpringLayout())
        self.top_panel.alignmentX = Component.CENTER_ALIGNMENT
        self.main_panel.add(self.top_panel)

        self.stageCounter = 1
        def getStageLabel(txt):
            label = JLabel("%s. %s" % (self.stageCounter, txt))
            self.stageCounter += 1
            return label

        # Instructions link.
        self.top_panel.add(getStageLabel("Read the instructions:"))
        instructionsButton = JButton(
            ('<HTML><FONT color="#000099">'
             '<U>open instructions</U></FONT><HTML>'),
            actionPerformed=self.browseInstructions)
        instructionsButton.setHorizontalAlignment(SwingConstants.LEFT);
        instructionsButton.setBorderPainted(False);
        instructionsButton.setOpaque(False);
        instructionsButton.setBackground(Color.WHITE);
        instructionsButton.setToolTipText(self.instructionsURI);
        self.top_panel.add(instructionsButton)

        # 'Select input' elements.
        self.top_panel.add(getStageLabel(
            "Select a SASI .zip file or data folder:"))
        self.top_panel.add(
            JButton("Select input...", actionPerformed=self.openInputChooser))

        # 'Select output' elements.
        self.top_panel.add(getStageLabel("Specify an output file:"))
        self.top_panel.add(
            JButton("Specify output...", actionPerformed=self.openOutputChooser))

        # 'Set result fields' elements.
        result_fields = [
            {'id': 'gear_id', 'label': 'Gear', 'selected': True, 
             'enabled': False}, 
            {'id': 'substrate_id', 'label': 'Substrate', 'selected': True}, 
            {'id': 'energy_id', 'label': 'Energy', 'selected': False},
            {'id': 'feature_id', 'label': 'Feature', 'selected': False}, 
            {'id': 'feature_category_id', 'label': 'Feature Category', 
             'selected': False}
        ]
        self.selected_result_fields = {}
        resolutionLabelPanel = JPanel(GridLayout(0,1))
        resolutionLabelPanel.add(getStageLabel("Set result resolution:"))
        resolutionLabelPanel.add(
            JLabel(("<html><i>This sets the specificity with which<br>"
                    "results will be grouped. Note that enabling<br>"
                    "more fields can *greatly* increase resulting<br>"
                    "output sizes and run times.</i>")))
        #self.top_panel.add(getStageLabel("Set result resolution:"))
        self.top_panel.add(resolutionLabelPanel)
        checkPanel = JPanel(GridLayout(0, 1))
        self.top_panel.add(checkPanel) 
        self.resultFieldCheckBoxes = {}
        for result_field in result_fields:
            self.selected_result_fields.setdefault(
                result_field['id'], result_field['selected'])
            checkBox = JCheckBox(
                result_field['label'], result_field['selected'])
            checkBox.setEnabled(result_field.get('enabled', True))
            checkBox.addItemListener(self)
            checkPanel.add(checkBox)
            self.resultFieldCheckBoxes[checkBox] = result_field

        # 'Run' elements.
        self.top_panel.add(getStageLabel("Run SASI: (this might take a while)"))
        self.run_button = JButton("Run...", actionPerformed=self.runSASI)
        self.top_panel.add(self.run_button)

        SpringUtilities.makeCompactGrid(
            self.top_panel, self.stageCounter - 1, 2, 6, 6, 6, 6)

        # Progress bar.
        self.progressBar = JProgressBar(0, 100)
        self.main_panel.add(self.progressBar)

        # Log panel.
        self.log_panel = JPanel()
        self.log_panel.alignmentX = Component.CENTER_ALIGNMENT
        self.log_panel.setBorder(EmptyBorder(10,10,10,10))
        self.main_panel.add(self.log_panel)
        self.log_panel.setLayout(BorderLayout())
        self.log = JTextArea()
        self.log.editable = False
        self.logScrollPane = JScrollPane(self.log)
        self.logScrollPane.setVerticalScrollBarPolicy(
            JScrollPane.VERTICAL_SCROLLBAR_ALWAYS)
        self.logScrollBar = self.logScrollPane.getVerticalScrollBar()
        self.log_panel.add(self.logScrollPane, BorderLayout.CENTER)

        # File selectors
        self.inputChooser = JFileChooser()
        self.inputChooser.fileSelectionMode = JFileChooser.FILES_AND_DIRECTORIES

        self.outputChooser = JFileChooser()
        defaultOutputFile = os.path.join(System.getProperty("user.home"),
                                         "sasi_project.zip")

        self.outputChooser.setSelectedFile(File(defaultOutputFile));
        self.outputChooser.fileSelectionMode = JFileChooser.FILES_ONLY

        self.frame.setLocationRelativeTo(None)
        self.frame.visible = True

    def browseInstructions(self, event):
        """ Open a browser to the instructions page. """
        browseURI(self.instructionsURI)

    def itemStateChanged(self, event):
        """ Listen for checkbox changes. """
        checkBox = event.getItemSelectable()
        is_selected = (event.getStateChange() == ItemEvent.SELECTED)
        result_field = self.resultFieldCheckBoxes[checkBox]
        self.selected_result_fields[result_field['id']] = is_selected

    def log_msg(self, msg):
        """ Print message to log and scroll to bottom. """
        self.log.append(msg + "\n")
        self.log.setCaretPosition(self.log.getDocument().getLength())

    def openInputChooser(self, event):
        ret = self.inputChooser.showOpenDialog(self.frame)
        if ret == JFileChooser.APPROVE_OPTION:
            self.selected_input_file = self.inputChooser.selectedFile
            self.log_msg("Selected '%s' as input." % self.selected_input_file.path)

    def openOutputChooser(self, event):
        ret = self.outputChooser.showSaveDialog(self.frame)
        if ret == JFileChooser.APPROVE_OPTION:
            selectedPath = self.outputChooser.selectedFile.path
            if not selectedPath.endswith('.zip'):
                zipPath = selectedPath + '.zip'
                self.outputChooser.setSelectedFile(File(zipPath))
            self.selected_output_file = self.outputChooser.selectedFile
            self.log_msg(
                "Selected '%s' as output." % self.selected_output_file.path)

    def runSASI(self, event):
        try:
            self.validateParameters()
        except Exception as e:
            self.log_msg("ERROR: '%s'" % e)

        # Run task in a separate thread, so that log
        # messages will be shown as task progresses.
        def run_task():
            self.tmp_dir = tempfile.mkdtemp(prefix="sasi_runner.")
            self.db_file = os.path.join(self.tmp_dir, "sasi_runner.db")

            self.progressBar.setValue(0)
            self.progressBar.setIndeterminate(True)

            def get_connection():
                engine = create_engine('h2+zxjdbc:////%s' % self.db_file)
                con = engine.connect()
                return con

            try:
                # Set result fields.
                result_fields = []
                for field_id, is_selected in self.selected_result_fields.items():
                    if is_selected: result_fields.append(field_id)

                task = RunSasiTask(
                    input_path=self.selected_input_file.path,
                    output_file=self.selected_output_file.path,
                    logger=self.logger,
                    get_connection=get_connection,
                    config={
                        'result_fields': result_fields,
                        'run_model': {
                            'run': {
                                'batch_size': 'auto',
                            }
                        },
                        'output': {
                            'batch_size': 'auto',
                        },
                    }
                )
                task.call()
            except Exception as e:
                self.logger.exception("Could not complete task")

            self.progressBar.setIndeterminate(False)
            self.progressBar.setValue(100)

            try:
                shutil.rmtree(self.tmp_dir)
            except:
                pass

        Thread(target=run_task).start()

    def validateParameters(self):
        return True
class JythonGui(object):
    def __init__(self, instructionsURI=""):
        self.instructionsURI = instructionsURI

        self.logger = logging.getLogger("sasi_gridder_gui")
        self.logger.addHandler(logging.StreamHandler())

        def log_fn(msg):
            self.log_msg(msg)

        self.logger.addHandler(FnLogHandler(log_fn))
        self.logger.setLevel(logging.DEBUG)

        self.selected_input_file = None
        self.selected_output_file = None

        self.frame = JFrame("SASI Gridder", defaultCloseOperation=WindowConstants.EXIT_ON_CLOSE)
        self.frame.size = (650, 600)

        self.main_panel = JPanel()
        self.main_panel.layout = BoxLayout(self.main_panel, BoxLayout.Y_AXIS)
        self.frame.add(self.main_panel)

        self.top_panel = JPanel(SpringLayout())
        self.top_panel.alignmentX = Component.CENTER_ALIGNMENT
        self.main_panel.add(self.top_panel)

        self.stageCounter = 1

        def getStageLabel(txt):
            label = JLabel("%s. %s" % (self.stageCounter, txt))
            self.stageCounter += 1
            return label

        # Instructions link.
        self.top_panel.add(getStageLabel("Read the instructions:"))
        instructionsButton = JButton(
            ('<HTML><FONT color="#000099">' "<U>open instructions</U></FONT><HTML>"),
            actionPerformed=self.browseInstructions,
        )
        instructionsButton.setHorizontalAlignment(SwingConstants.LEFT)
        instructionsButton.setBorderPainted(False)
        instructionsButton.setOpaque(False)
        instructionsButton.setBackground(Color.WHITE)
        instructionsButton.setToolTipText(self.instructionsURI)
        self.top_panel.add(instructionsButton)

        # Select input elements.
        self.top_panel.add(getStageLabel("Select an input data folder:"))
        self.top_panel.add(JButton("Select input...", actionPerformed=self.openInputChooser))

        # Select output elements.
        self.top_panel.add(getStageLabel("Specify an output file:"))
        self.top_panel.add(JButton("Specify output...", actionPerformed=self.openOutputChooser))

        # Run elements.
        self.top_panel.add(getStageLabel("Run SASI Gridder: (this might take a hwile"))
        self.run_button = JButton("Run...", actionPerformed=self.runSASIGridder)
        self.top_panel.add(self.run_button)

        SpringUtilities.makeCompactGrid(self.top_panel, self.stageCounter - 1, 2, 6, 6, 6, 6)

        # Progress bar.
        self.progressBar = JProgressBar(0, 100)
        self.main_panel.add(self.progressBar)

        # Log panel.
        self.log_panel = JPanel()
        self.log_panel.alignmentX = Component.CENTER_ALIGNMENT
        self.log_panel.setBorder(EmptyBorder(10, 10, 10, 10))
        self.main_panel.add(self.log_panel)
        self.log_panel.setLayout(BorderLayout())
        self.log = JTextArea()
        self.log.editable = False
        self.logScrollPane = JScrollPane(self.log)
        self.logScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS)
        self.log_panel.add(self.logScrollPane, BorderLayout.CENTER)

        # File selectors
        self.inputChooser = JFileChooser()
        self.inputChooser.fileSelectionMode = JFileChooser.FILES_AND_DIRECTORIES
        self.outputChooser = JFileChooser()
        self.outputChooser.fileSelectionMode = JFileChooser.FILES_ONLY
        defaultOutputFile = os.path.join(System.getProperty("user.home"), "gridded_efforts.csv")
        self.outputChooser.setSelectedFile(File(defaultOutputFile))

        self.frame.setLocationRelativeTo(None)
        self.frame.visible = True

    def browseInstructions(self, event):
        """ Open a browser to the instructions page. """
        browseURI(self.instructionsURI)
        return

    def log_msg(self, msg):
        self.log.append(msg + "\n")
        self.log.setCaretPosition(self.log.getDocument().getLength())

    def openInputChooser(self, event):
        ret = self.inputChooser.showOpenDialog(self.frame)
        if ret == JFileChooser.APPROVE_OPTION:
            self.selected_input_file = self.inputChooser.selectedFile
            self.log_msg("Selected '%s' as input." % self.selected_input_file.path)

    def openOutputChooser(self, event):
        ret = self.outputChooser.showSaveDialog(self.frame)
        if ret == JFileChooser.APPROVE_OPTION:
            self.selected_output_file = self.outputChooser.selectedFile
            self.log_msg("Selected '%s' as output." % self.selected_output_file.path)

    def runSASIGridder(self, event):
        try:
            self.validateParameters()
        except Exception as e:
            self.log_msg("ERROR: '%s'" % e)

        # Run task in a separate thread, so that log
        # messages will be shown as task progresses.
        def run_task():

            self.progressBar.setValue(0)
            self.progressBar.setIndeterminate(True)

            try:
                input_dir = self.selected_input_file.path
                output_path = self.selected_output_file.path

                grid_path = os.path.join(input_dir, "grid", "grid.shp")

                stat_areas_path = os.path.join(input_dir, "stat_areas", "stat_areas.shp")

                raw_efforts_path = os.path.join(input_dir, "raw_efforts.csv")

                gear_mappings_path = os.path.join(input_dir, "gear_mappings.csv")

                gear_mappings = {}
                with open(gear_mappings_path, "rb") as f:
                    r = csv.DictReader(f)
                    for mapping in r:
                        gear_mappings[mapping["trip_type"]] = mapping["gear_code"]

                task = SASIGridderTask(
                    grid_path=grid_path,
                    raw_efforts_path=raw_efforts_path,
                    stat_areas_path=stat_areas_path,
                    output_path=output_path,
                    logger=self.logger,
                    gear_mappings=gear_mappings,
                    effort_limit=None,
                )
                task.call()
            except Exception as e:
                self.logger.exception("Could not complete task")

            self.progressBar.setIndeterminate(False)
            self.progressBar.setValue(100)

        Thread(target=run_task).start()

    def validateParameters(self):
        return True
Beispiel #8
0
class BeautifierPanel(JPanel):
    def __init__(self):
        super(BeautifierPanel, self).__init__()
        self.setLayout(BorderLayout())

        self.beautifyTextArea = JTextArea(5, 10)
        self.beautifyTextArea.setLineWrap(True)
        self.beautifyTextArea.setDocument(self.CustomUndoPlainDocument())
        # The undo doesn't work well before replace text. Below is rough fix, so not need to know how undo work for now
        self.beautifyTextArea.setText(" ")
        self.beautifyTextArea.setText("")

        self.undoManager = UndoManager()
        self.beautifyTextArea.getDocument().addUndoableEditListener(
            self.undoManager)
        self.beautifyTextArea.getDocument().addDocumentListener(
            self.BeautifyDocumentListener(self))

        beautifyTextWrapper = JPanel(BorderLayout())
        beautifyScrollPane = JScrollPane(self.beautifyTextArea)
        beautifyTextWrapper.add(beautifyScrollPane, BorderLayout.CENTER)
        self.add(beautifyTextWrapper, BorderLayout.CENTER)

        self.beautifyButton = JButton("Beautify")
        self.beautifyButton.addActionListener(self.beautifyListener)
        self.undoButton = JButton("Undo")
        self.undoButton.addActionListener(self.undoListener)

        formatLabel = JLabel("Format:")
        self.formatsComboBox = JComboBox()
        for f in supportedFormats:
            self.formatsComboBox.addItem(f)

        self.statusLabel = JLabel("Status: Ready")
        preferredDimension = self.statusLabel.getPreferredSize()
        self.statusLabel.setPreferredSize(
            Dimension(preferredDimension.width + 20,
                      preferredDimension.height))
        self.sizeLabel = JLabel("0 B")
        preferredDimension = self.sizeLabel.getPreferredSize()
        self.sizeLabel.setPreferredSize(
            Dimension(preferredDimension.width + 64,
                      preferredDimension.height))
        self.sizeLabel.setHorizontalAlignment(SwingConstants.RIGHT)

        buttonsPanel = JPanel(FlowLayout())
        buttonsPanel.add(formatLabel)
        buttonsPanel.add(self.formatsComboBox)
        buttonsPanel.add(Box.createHorizontalStrut(10))
        buttonsPanel.add(self.beautifyButton)
        buttonsPanel.add(self.undoButton)

        bottomPanel = JPanel(BorderLayout())
        bottomPanel.add(self.statusLabel, BorderLayout.WEST)
        bottomPanel.add(buttonsPanel, BorderLayout.CENTER)
        bottomPanel.add(self.sizeLabel, BorderLayout.EAST)
        self.add(bottomPanel, BorderLayout.SOUTH)

        self.currentBeautifyThread = None

    class CustomUndoPlainDocument(PlainDocument):
        # Code from: https://stackoverflow.com/questions/24433089/jtextarea-settext-undomanager
        compoundEdit = CompoundEdit()

        def fireUndoableEditUpdate(self, e):
            if self.compoundEdit == None:
                super(BeautifierPanel.CustomUndoPlainDocument,
                      self).fireUndoableEditUpdate(e)
            else:
                self.compoundEdit.addEdit(e.getEdit())

        def replace(self, offset, length, text, attrs):
            if length == 0:
                super(BeautifierPanel.CustomUndoPlainDocument,
                      self).replace(offset, length, text, attrs)
            else:
                self.compoundEdit = CompoundEdit()
                super(BeautifierPanel.CustomUndoPlainDocument,
                      self).fireUndoableEditUpdate(
                          UndoableEditEvent(self, self.compoundEdit))
                super(BeautifierPanel.CustomUndoPlainDocument,
                      self).replace(offset, length, text, attrs)
                self.compoundEdit.end()
                self.compoundEdit = None

    def setText(self, text):
        self.beautifyTextArea.setText(text)

    def setRunningState(self):
        self.beautifyButton.setText("Cancel")
        self.undoButton.setEnabled(False)
        self.statusLabel.setText("Status: Running")

    def setReadyState(self):
        self.beautifyButton.setText("Beautify")
        self.undoButton.setEnabled(True)
        self.statusLabel.setText("Status: Ready")

    class BeautifyDocumentListener(DocumentListener):
        def __init__(self, beautifierPanel):
            super(BeautifierPanel.BeautifyDocumentListener, self).__init__()
            self.beautifierPanel = beautifierPanel

        def removeUpdate(self, e):
            self.updateSizeLabel()

        def insertUpdate(self, e):
            self.updateSizeLabel()

        def changedUpdate(self, e):
            pass

        def updateSizeLabel(self):
            length = len(self.beautifierPanel.beautifyTextArea.getText())
            if length >= 1024:
                length = "%.2f KB" % (length / 1024.0)
            else:
                length = "%d B" % length
            self.beautifierPanel.sizeLabel.setText(length)

    def beautifyListener(self, e):
        selectedFormat = self.formatsComboBox.getSelectedItem()
        data = self.beautifyTextArea.getText(
        )  # variable "data" is "unicode" type

        if self.currentBeautifyThread and self.currentBeautifyThread.isAlive():
            # TODO Need a graceful way to shutdown running beautify thread.
            self.currentBeautifyThread.callback = None
            self.currentBeautifyThread = None
            self.setReadyState()
        else:
            self.currentBeautifyThread = None
            self.setRunningState()

            def beautifyCallback(result):
                self.beautifyTextArea.setText(result)
                self.setReadyState()

            self.currentBeautifyThread = BeautifyThread(
                data, selectedFormat, beautifyCallback)
            self.currentBeautifyThread.start()

    def undoListener(self, e):
        if self.undoManager.canUndo():
            self.undoManager.undo()