Пример #1
0
 def __init__(self, home):
     super().__init__()
     self.home = home
     self.font = Font().load()
     microbit_fs = MicrobitFileList(home)
     local_fs = LocalFileList(home)
     layout = QGridLayout()
     self.setLayout(layout)
     microbit_label = QLabel()
     microbit_label.setText(_('Files on your micro:bit:'))
     local_label = QLabel()
     local_label.setText(_('Files on your computer:'))
     self.microbit_label = microbit_label
     self.local_label = local_label
     self.microbit_fs = microbit_fs
     self.local_fs = local_fs
     self.set_font_size()
     layout.addWidget(microbit_label, 0, 0)
     layout.addWidget(local_label, 0, 1)
     layout.addWidget(microbit_fs, 1, 0)
     layout.addWidget(local_fs, 1, 1)
     self.microbit_fs.disable.connect(self.disable)
     self.microbit_fs.set_message.connect(self.show_message)
     self.local_fs.disable.connect(self.disable)
     self.local_fs.set_message.connect(self.show_message)
Пример #2
0
    def __init__(self, home):
        super().__init__()
        self.home = home
        self.font = Font().load()
        microbit_fs = ArdupyDeviceFileList(home)
        local_fs = LocalFileTree(home)

        @local_fs.open_file.connect
        def on_open_file(file):
            # Bubble the signal up
            self.open_file.emit(file)

        layout = QGridLayout()
        self.setLayout(layout)
        microbit_label = QLabel()
        microbit_label.setText(_("Files on your device:"))
        local_label = QLabel()
        local_label.setText(_("Files on your computer:"))
        self.microbit_label = microbit_label
        self.local_label = local_label
        self.microbit_fs = microbit_fs
        self.local_fs = local_fs
        self.set_font_size()
        layout.addWidget(microbit_label, 0, 0)
        layout.addWidget(local_label, 0, 1)
        layout.addWidget(microbit_fs, 1, 0)
        layout.addWidget(local_fs, 1, 1)
        self.microbit_fs.disable.connect(self.disable)
        self.microbit_fs.set_message.connect(self.show_message)
        self.local_fs.disable.connect(self.disable)
        self.local_fs.enable.connect(self.enable)
        self.local_fs.set_message.connect(self.show_message)
Пример #3
0
 def configure(self):
     """
     Set up the editor component.
     """
     # Font information
     font = Font().load()
     self.setFont(font)
     # Generic editor settings
     self.setUtf8(True)
     self.setAutoIndent(True)
     self.setIndentationsUseTabs(False)
     self.setIndentationWidth(4)
     self.setIndentationGuides(True)
     self.setBackspaceUnindents(True)
     self.setTabWidth(4)
     self.setEdgeColumn(79)
     self.setMarginLineNumbers(0, True)
     self.setMarginWidth(0, 50)
     self.setBraceMatching(QsciScintilla.SloppyBraceMatch)
     self.SendScintilla(QsciScintilla.SCI_SETHSCROLLBAR, 0)
     self.set_theme()
     # Markers and indicators
     self.setMarginSensitivity(0, True)
     self.markerDefine(self.Circle, self.BREAKPOINT_MARKER)
     self.setMarginSensitivity(1, True)
     self.setIndicatorDrawUnder(True)
     for type_ in self.check_indicators:
         self.indicatorDefine(self.SquiggleIndicator,
                              self.check_indicators[type_]['id'])
     for type_ in self.search_indicators:
         self.indicatorDefine(self.StraightBoxIndicator,
                              self.search_indicators[type_]['id'])
     self.indicatorDefine(self.FullBoxIndicator, self.DEBUG_INDICATOR)
     self.setAnnotationDisplay(self.AnnotationBoxed)
     self.selectionChanged.connect(self.selection_change_listener)
Пример #4
0
 def __init__(self, port, theme='day', parent=None):
     super().__init__(parent)
     self.setFont(Font().load())
     self.setAcceptRichText(False)
     self.setReadOnly(False)
     self.setUndoRedoEnabled(False)
     self.setContextMenuPolicy(Qt.CustomContextMenu)
     self.customContextMenuRequested.connect(self.context_menu)
     self.setObjectName('replpane')
     # open the serial port
     self.serial = QSerialPort(self)
     self.serial.setPortName(port)
     if self.serial.open(QIODevice.ReadWrite):
         self.serial.dataTerminalReady = True
         if not self.serial.isDataTerminalReady():
             # Using pyserial as a 'hack' to open the port and set DTR
             # as QtSerial does not seem to work on some Windows :(
             # See issues #281 and #302 for details.
             self.serial.close()
             pyser = serial.Serial(port)  # open serial port w/pyserial
             pyser.dtr = True
             pyser.close()
             self.serial.open(QIODevice.ReadWrite)
         self.serial.setBaudRate(115200)
         self.serial.readyRead.connect(self.on_serial_read)
         # clear the text
         self.clear()
         # Send a Control-C
         self.serial.write(b'\x03')
     else:
         raise IOError("Cannot connect to device on port {}".format(port))
     self.set_theme(theme)
Пример #5
0
    def __init__(self, home):
        super().__init__()
        self.home = home
        self.font = Font().load()
        microbit_fs = MicrobitFileList(home)
        local_fs = LocalFileList(home)

        @local_fs.open_file.connect
        def on_open_file(file):
            # Bubble the signal up
            self.open_file.emit(file)

        layout = QGridLayout()
        self.setLayout(layout)
        microbit_label = QLabel()
        microbit_label.setText(_('Files on your micro:bit:'))
        local_label = QLabel()
        local_label.setText(_('Files on your computer:'))
        self.microbit_label = microbit_label
        self.local_label = local_label
        self.microbit_fs = microbit_fs
        self.local_fs = local_fs
        self.set_font_size()
        layout.addWidget(microbit_label, 0, 0)
        layout.addWidget(local_label, 0, 1)
        layout.addWidget(microbit_fs, 1, 0)
        layout.addWidget(local_fs, 1, 1)
        self.microbit_fs.disable.connect(self.disable)
        self.microbit_fs.set_message.connect(self.show_message)
        self.local_fs.disable.connect(self.disable)
        self.local_fs.set_message.connect(self.show_message)
Пример #6
0
 def __init__(self, serial, theme='day', parent=None):
     super().__init__(parent)
     self.serial = serial
     self.setFont(Font().load())
     self.setAcceptRichText(False)
     self.setReadOnly(False)
     self.setUndoRedoEnabled(False)
     self.setContextMenuPolicy(Qt.CustomContextMenu)
     self.customContextMenuRequested.connect(self.context_menu)
     self.setObjectName('replpane')
     self.set_theme(theme)
Пример #7
0
 def __init__(self, parent=None):
     super().__init__(parent)
     self.setFont(Font().load())
     self.setAcceptRichText(False)
     self.setReadOnly(False)
     self.setUndoRedoEnabled(False)
     self.setContextMenuPolicy(Qt.CustomContextMenu)
     self.customContextMenuRequested.connect(self.context_menu)
     self.setObjectName('PythonRunner')
     self.process = None  # Will eventually reference the running process.
     self.input_history = []  # history of inputs entered in this session.
     self.start_of_current_line = 0  # start position of the input line.
     self.history_position = 0  # current position when navigation history.
Пример #8
0
 def __init__(self, parent=None):
     super().__init__(parent)
     self.setFont(Font().load())
     self.setAcceptRichText(False)
     self.setReadOnly(False)
     self.setUndoRedoEnabled(False)
     self.setContextMenuPolicy(Qt.CustomContextMenu)
     self.customContextMenuRequested.connect(self.context_menu)
     self.running = False  # Flag to show the child process is running.
     self.setObjectName('PythonRunner')
     self.process = None  # Will eventually reference the running process.
     self.input_history = []  # history of inputs entered in this session.
     self.start_of_current_line = 0  # start position of the input line.
     self.history_position = 0  # current position when navigation history.
     self.stdout_buffer = b''  # contains non-decoded bytes from stdout.
     self.reading_stdout = False  # flag showing if already reading stdout.
Пример #9
0
 def configure(self):
     """
     Set up the editor component.
     """
     # Font information
     font = Font().load()
     self.setFont(font)
     # Generic editor settings
     self.setUtf8(True)
     self.setAutoIndent(True)
     self.setIndentationsUseTabs(False)
     self.setIndentationWidth(4)
     self.setIndentationGuides(True)
     self.setBackspaceUnindents(True)
     self.setTabWidth(4)
     self.setEdgeColumn(79)
     self.setMarginLineNumbers(0, True)
     self.setMarginWidth(0, 50)
     self.setBraceMatching(QsciScintilla.SloppyBraceMatch)
     self.SendScintilla(QsciScintilla.SCI_SETHSCROLLBAR, 0)
     self.set_theme()
     # Markers and indicators
     self.setMarginSensitivity(0, True)
     self.markerDefine(self.Circle, self.BREAKPOINT_MARKER)
     self.setMarginSensitivity(1, True)
     # Additional dummy margin to prevent accidental breakpoint toggles when
     # trying to position the edit cursor to the left of the first column,
     # using the mouse and not being 100% accurate. This margin needs to be
     # set with "sensitivity on": otherwise clicking it would select the
     # whole text line, per QsciScintilla's behaviour. It is up to the
     # click handler to ignore clicks on this margin: self.connect_margin.
     self.setMarginWidth(4, 8)
     self.setMarginSensitivity(4, True)
     # Indicators
     self.setIndicatorDrawUnder(True)
     for type_ in self.check_indicators:
         self.indicatorDefine(
             self.SquiggleIndicator, self.check_indicators[type_]["id"]
         )
     for type_ in self.search_indicators:
         self.indicatorDefine(
             self.StraightBoxIndicator, self.search_indicators[type_]["id"]
         )
     self.indicatorDefine(self.FullBoxIndicator, self.DEBUG_INDICATOR)
     self.setAnnotationDisplay(self.AnnotationBoxed)
     self.selectionChanged.connect(self.selection_change_listener)
     self.set_zoom()
Пример #10
0
 def __init__(self, connection, theme="day", parent=None):
     super().__init__(parent)
     self.connection = connection
     self.setFont(Font().load())
     self.setAcceptRichText(False)
     self.setReadOnly(False)
     self.setUndoRedoEnabled(False)
     self.setContextMenuPolicy(Qt.CustomContextMenu)
     self.customContextMenuRequested.connect(self.context_menu)
     # The following variable maintains the position where we know
     # the device cursor is placed. It is initialized to the beginning
     # of the QTextEdit (i.e. equal to the Qt cursor position)
     self.device_cursor_position = self.textCursor().position()
     self.setObjectName("replpane")
     self.set_theme(theme)
     self.unprocessed_input = b""  # used by process_bytes
     self.decoder = codecs.getincrementaldecoder("utf8")("replace")
     self.vt100_regex = re.compile(
         r"\x1B\[(?P<count>[\d]*)(;?[\d]*)*(?P<action>[A-Za-z])"
     )
Пример #11
0
 def __init__(self, port, theme='day', parent=None):
     super().__init__(parent)
     self.setFont(Font().load())
     self.setAcceptRichText(False)
     self.setReadOnly(False)
     self.setUndoRedoEnabled(False)
     self.setContextMenuPolicy(Qt.CustomContextMenu)
     self.customContextMenuRequested.connect(self.context_menu)
     self.setObjectName('replpane')
     # open the serial port
     self.serial = QSerialPort(self)
     self.serial.setPortName(port)
     if self.serial.open(QIODevice.ReadWrite):
         self.serial.setBaudRate(115200)
         self.serial.readyRead.connect(self.on_serial_read)
         # clear the text
         self.clear()
         # Send a Control-C
         self.serial.write(b'\x03')
     else:
         raise IOError("Cannot connect to device on port {}".format(port))
     self.set_theme(theme)
Пример #12
0
class FileSystemPane(QFrame):
    """
    Contains two QListWidgets representing the micro:bit and the user's code
    directory. Users transfer files by dragging and dropping. Highlighted files
    can be selected for deletion.
    """

    set_message = pyqtSignal(str)
    set_warning = pyqtSignal(str)
    list_files = pyqtSignal()
    open_file = pyqtSignal(str)

    def __init__(self, home):
        super().__init__()
        self.home = home
        self.font = Font().load()
        microbit_fs = MicrobitFileList(home)
        local_fs = LocalFileList(home)

        @local_fs.open_file.connect
        def on_open_file(file):
            # Bubble the signal up
            self.open_file.emit(file)

        layout = QGridLayout()
        self.setLayout(layout)
        microbit_label = QLabel()
        microbit_label.setText(_('Files on your micro:bit:'))
        local_label = QLabel()
        local_label.setText(_('Files on your computer:'))
        self.microbit_label = microbit_label
        self.local_label = local_label
        self.microbit_fs = microbit_fs
        self.local_fs = local_fs
        self.set_font_size()
        layout.addWidget(microbit_label, 0, 0)
        layout.addWidget(local_label, 0, 1)
        layout.addWidget(microbit_fs, 1, 0)
        layout.addWidget(local_fs, 1, 1)
        self.microbit_fs.disable.connect(self.disable)
        self.microbit_fs.set_message.connect(self.show_message)
        self.local_fs.disable.connect(self.disable)
        self.local_fs.set_message.connect(self.show_message)

    def disable(self):
        """
        Stops interaction with the list widgets.
        """
        self.microbit_fs.setDisabled(True)
        self.local_fs.setDisabled(True)
        self.microbit_fs.setAcceptDrops(False)
        self.local_fs.setAcceptDrops(False)

    def enable(self):
        """
        Allows interaction with the list widgets.
        """
        self.microbit_fs.setDisabled(False)
        self.local_fs.setDisabled(False)
        self.microbit_fs.setAcceptDrops(True)
        self.local_fs.setAcceptDrops(True)

    def show_message(self, message):
        """
        Emits the set_message signal.
        """
        self.set_message.emit(message)

    def show_warning(self, message):
        """
        Emits the set_warning signal.
        """
        self.set_warning.emit(message)

    def on_ls(self, microbit_files):
        """
        Displays a list of the files on the micro:bit.

        Since listing files is always the final event in any interaction
        between Mu and the micro:bit, this enables the controls again for
        further interactions to take place.
        """
        self.microbit_fs.clear()
        self.local_fs.clear()
        for f in microbit_files:
            self.microbit_fs.addItem(f)
        local_files = [f for f in os.listdir(self.home)
                       if os.path.isfile(os.path.join(self.home, f))]
        local_files.sort()
        for f in local_files:
            self.local_fs.addItem(f)
        self.enable()

    def on_ls_fail(self):
        """
        Fired when listing files fails.
        """
        self.show_warning(_("There was a problem getting the list of files on "
                            "the micro:bit. Please check Mu's logs for "
                            "technical information. Alternatively, try "
                            "unplugging/plugging-in your micro:bit and/or "
                            "restarting Mu."))
        self.disable()

    def on_put_fail(self, filename):
        """
        Fired when the referenced file cannot be copied onto the micro:bit.
        """
        self.show_warning(_("There was a problem copying the file '{}' onto "
                            "the micro:bit. Please check Mu's logs for "
                            "more information.").format(filename))

    def on_delete_fail(self, filename):
        """
        Fired when a deletion on the micro:bit for the given file failed.
        """
        self.show_warning(_("There was a problem deleting '{}' from the "
                            "micro:bit. Please check Mu's logs for "
                            "more information.").format(filename))

    def on_get_fail(self, filename):
        """
        Fired when getting the referenced file on the micro:bit failed.
        """
        self.show_warning(_("There was a problem getting '{}' from the "
                            "micro:bit. Please check Mu's logs for "
                            "more information.").format(filename))

    def set_theme(self, theme):
        pass

    def set_font_size(self, new_size=DEFAULT_FONT_SIZE):
        """
        Sets the font size for all the textual elements in this pane.
        """
        self.font.setPointSize(new_size)
        self.microbit_label.setFont(self.font)
        self.local_label.setFont(self.font)
        self.microbit_fs.setFont(self.font)
        self.local_fs.setFont(self.font)

    def set_zoom(self, size):
        """
        Set the current zoom level given the "t-shirt" size.
        """
        self.set_font_size(PANE_ZOOM_SIZES[size])
Пример #13
0
class SeeedFileSystemPane(QFrame):
    set_message = pyqtSignal(str)
    set_warning = pyqtSignal(str)
    list_files = pyqtSignal()
    open_file = pyqtSignal(str)

    def __init__(self, home):
        super().__init__()
        self.home = home
        self.font = Font().load()
        microbit_fs = ArdupyDeviceFileList(home)
        local_fs = LocalFileTree(home)

        @local_fs.open_file.connect
        def on_open_file(file):
            # Bubble the signal up
            self.open_file.emit(file)

        layout = QGridLayout()
        self.setLayout(layout)
        microbit_label = QLabel()
        microbit_label.setText(_("Files on your device:"))
        local_label = QLabel()
        local_label.setText(_("Files on your computer:"))
        self.microbit_label = microbit_label
        self.local_label = local_label
        self.microbit_fs = microbit_fs
        self.local_fs = local_fs
        self.set_font_size()
        layout.addWidget(microbit_label, 0, 0)
        layout.addWidget(local_label, 0, 1)
        layout.addWidget(microbit_fs, 1, 0)
        layout.addWidget(local_fs, 1, 1)
        self.microbit_fs.disable.connect(self.disable)
        self.microbit_fs.set_message.connect(self.show_message)
        self.local_fs.disable.connect(self.disable)
        self.local_fs.enable.connect(self.enable)
        self.local_fs.set_message.connect(self.show_message)

    def disable(self):
        """
        Stops interaction with the list widgets.
        """
        self.microbit_fs.setDisabled(True)
        self.local_fs.setDisabled(True)
        self.microbit_fs.setAcceptDrops(False)
        self.local_fs.setAcceptDrops(False)

    def enable(self):
        """
        Allows interaction with the list widgets.
        """
        self.microbit_fs.setDisabled(False)
        self.local_fs.setDisabled(False)
        self.microbit_fs.setAcceptDrops(True)
        self.local_fs.setAcceptDrops(True)

    def show_message(self, message):
        """
        Emits the set_message signal.
        """
        self.set_message.emit(message)

    def show_warning(self, message):
        """
        Emits the set_warning signal.
        """
        self.set_warning.emit(message)

    def on_ls(self, microbit_files):
        """
        Displays a list of the files on the seeed board.

        Since listing files is always the final event in any interaction
        between Mu and the seeed board, this enables the controls again for
        further interactions to take place.
        """
        print("SeeedFileSystemPane on_ls")
        print(microbit_files)
        self.microbit_fs.clear()
        for f in microbit_files:
            self.microbit_fs.addItem(f)

        if self.local_fs.need_update_tree:
            self.local_fs.clear()
            self.local_fs.ls()
        else:
            self.local_fs.need_update_tree = True
        self.enable()

    def on_ls_fail(self):
        """
        Fired when listing files fails.
        """
        self.show_warning(
            _("There was a problem gettingthe list of files on "
              "the device. Please check Mu's logs for "
              "technical information. Alternatively, try "
              "unplugging/plugging-in your device and/or "
              "restarting Mu."))
        self.disable()

    def on_put_fail(self, filename):
        """
        Fired when the referenced file cannot be copied onto the device.
        """
        self.show_warning(
            _("There was a problem copying the file '{}' onto "
              "the device. Please check Mu's logs for "
              "more information.").format(filename))

    def on_delete_fail(self, filename):
        """
        Fired when a deletion on the device for the given file failed.
        """
        self.show_warning(
            _("There was a problem deleting '{}' from the "
              "device. Please check Mu's logs for "
              "more information.").format(filename))

    def on_get_fail(self, filename):
        """
        Fired when getting the referenced file on the device failed.
        """
        self.show_warning(
            _("There was a problem getting '{}' from the "
              "device. Please check Mu's logs for "
              "more information.").format(filename))

    def set_theme(self, theme):
        pass

    def set_font_size(self, new_size=DEFAULT_FONT_SIZE):
        """
        Sets the font size for all the textual elements in this pane.
        """
        self.font.setPointSize(new_size)
        self.microbit_label.setFont(self.font)
        self.local_label.setFont(self.font)
        self.microbit_fs.setFont(self.font)
        self.local_fs.setFont(self.font)

    def set_zoom(self, size):
        """
        Set the current zoom level given the "t-shirt" size.
        """
        self.set_font_size(PANE_ZOOM_SIZES[size])
Пример #14
0
class FileSystemPane(QFrame):
    """
    Contains two QListWidgets representing the micro:bit and the user's code
    directory. Users transfer files by dragging and dropping. Highlighted files
    can be selected for deletion.
    """

    set_message = pyqtSignal(str)
    set_warning = pyqtSignal(str)
    list_files = pyqtSignal()
    open_file = pyqtSignal(str)

    def __init__(self, home):
        import ctypes
        from subprocess import check_output

        def find_device():
            """
            Returns a path on the filesystem that represents the plugged in BBC
            micro:bit that is to be flashed. If no micro:bit is found, it returns
            None.

            Works on Linux, OSX and Windows. Will raise a NotImplementedError
            exception if run on any other operating system.
            """
            # Check what sort of operating system we're on.
            if os.name == 'posix':
                # 'posix' means we're on Linux or OSX (Mac).
                # Call the unix "mount" command to list the mounted volumes.
                mount_output = check_output('mount').splitlines()
                mounted_volumes = [x.split()[2] for x in mount_output]
                for volume in mounted_volumes:
                    if volume.endswith(b'MINI') or volume.endswith(
                            b'MICROBIT'):
                        return volume.decode(
                            'utf-8')  # Return a string not bytes.
            elif os.name == 'nt':
                # 'nt' means we're on Windows.

                def get_volume_name(disk_name):
                    """
                    Each disk or external device connected to windows has an attribute
                    called "volume name". This function returns the volume name for
                    the given disk/device.

                    Code from http://stackoverflow.com/a/12056414
                    """
                    vol_name_buf = ctypes.create_unicode_buffer(1024)
                    ctypes.windll.kernel32.GetVolumeInformationW(
                        ctypes.c_wchar_p(disk_name), vol_name_buf,
                        ctypes.sizeof(vol_name_buf), None, None, None, None, 0)
                    return vol_name_buf.value

                #
                # In certain circumstances, volumes are allocated to USB
                # storage devices which cause a Windows popup to raise if their
                # volume contains no media. Wrapping the check in SetErrorMode
                # with SEM_FAILCRITICALERRORS (1) prevents this popup.
                #
                old_mode = ctypes.windll.kernel32.SetErrorMode(1)
                try:
                    for disk in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ':
                        path = '{}:\\'.format(disk)
                        #
                        # Don't bother looking if the drive isn't removable
                        #
                        if ctypes.windll.kernel32.GetDriveTypeW(path) != 2:
                            continue
                        if os.path.exists(path) and \
                                get_volume_name(path) == 'MINI' or get_volume_name(path) == 'MICROBIT':
                            return get_volume_name(path)
                finally:
                    ctypes.windll.kernel32.SetErrorMode(old_mode)
            else:
                # No support for unknown operating systems.
                #raise NotImplementedError('OS "{}" not supported.'.format(os.name))
                return None

        super().__init__()
        self.home = home
        self.font = Font().load()
        microbit_fs = MicrobitFileList(home)
        local_fs = LocalFileList(home)
        self.device_displayName = "micro:bit"
        if find_device().lower().find("mini") > -1:
            microbit_fs = CalliopeMiniFileList(home)
            self.device_displayName = "Calliope mini"

        @local_fs.open_file.connect
        def on_open_file(file):
            # Bubble the signal up
            self.open_file.emit(file)

        layout = QGridLayout()
        self.setLayout(layout)
        microbit_label = QLabel()
        microbit_label.setText(
            _('Files on your {}:'.format(self.device_displayName)))
        local_label = QLabel()
        local_label.setText(_('Files on your computer:'))
        self.microbit_label = microbit_label
        self.local_label = local_label
        self.microbit_fs = microbit_fs
        self.local_fs = local_fs
        self.set_font_size()
        layout.addWidget(microbit_label, 0, 0)
        layout.addWidget(local_label, 0, 1)
        layout.addWidget(microbit_fs, 1, 0)
        layout.addWidget(local_fs, 1, 1)
        self.microbit_fs.disable.connect(self.disable)
        self.microbit_fs.set_message.connect(self.show_message)
        self.local_fs.disable.connect(self.disable)
        self.local_fs.set_message.connect(self.show_message)

    def disable(self):
        """
        Stops interaction with the list widgets.
        """
        self.microbit_fs.setDisabled(True)
        self.local_fs.setDisabled(True)
        self.microbit_fs.setAcceptDrops(False)
        self.local_fs.setAcceptDrops(False)

    def enable(self):
        """
        Allows interaction with the list widgets.
        """
        self.microbit_fs.setDisabled(False)
        self.local_fs.setDisabled(False)
        self.microbit_fs.setAcceptDrops(True)
        self.local_fs.setAcceptDrops(True)

    def show_message(self, message):
        """
        Emits the set_message signal.
        """
        self.set_message.emit(message)

    def show_warning(self, message):
        """
        Emits the set_warning signal.
        """
        self.set_warning.emit(message)

    def on_ls(self, microbit_files):
        """
        Displays a list of the files on the micro:bit.

        Since listing files is always the final event in any interaction
        between Mu and the micro:bit, this enables the controls again for
        further interactions to take place.
        """
        self.microbit_fs.clear()
        self.local_fs.clear()
        for f in microbit_files:
            self.microbit_fs.addItem(f)
        local_files = [
            f for f in os.listdir(self.home)
            if os.path.isfile(os.path.join(self.home, f))
        ]
        local_files.sort()
        for f in local_files:
            self.local_fs.addItem(f)
        self.enable()

    def on_ls_fail(self):
        """
        Fired when listing files fails.
        """
        self.show_warning(
            _("There was a problem getting the list of files on "
              "the micro:bit. Please check Mu's logs for "
              "technical information. Alternatively, try "
              "unplugging/plugging-in your micro:bit and/or "
              "restarting Mu."))
        self.disable()

    def on_put_fail(self, filename):
        """
        Fired when the referenced file cannot be copied onto the micro:bit.
        """
        self.show_warning(
            _("There was a problem copying the file '{}' onto "
              "the micro:bit. Please check Mu's logs for "
              "more information.").format(filename))

    def on_delete_fail(self, filename):
        """
        Fired when a deletion on the micro:bit for the given file failed.
        """
        self.show_warning(
            _("There was a problem deleting '{}' from the "
              "micro:bit. Please check Mu's logs for "
              "more information.").format(filename))

    def on_get_fail(self, filename):
        """
        Fired when getting the referenced file on the micro:bit failed.
        """
        self.show_warning(
            _("There was a problem getting '{}' from the "
              "micro:bit. Please check Mu's logs for "
              "more information.").format(filename))

    def set_theme(self, theme):
        pass

    def set_font_size(self, new_size=DEFAULT_FONT_SIZE):
        """
        Sets the font size for all the textual elements in this pane.
        """
        self.font.setPointSize(new_size)
        self.microbit_label.setFont(self.font)
        self.local_label.setFont(self.font)
        self.microbit_fs.setFont(self.font)
        self.local_fs.setFont(self.font)

    def zoomIn(self, delta=2):
        """
        Zoom in (increase) the size of the font by delta amount difference in
        point size upto 34 points.
        """
        old_size = self.font.pointSize()
        new_size = min(old_size + delta, 34)
        self.set_font_size(new_size)

    def zoomOut(self, delta=2):
        """
        Zoom out (decrease) the size of the font by delta amount difference in
        point size down to 4 points.
        """
        old_size = self.font.pointSize()
        new_size = max(old_size - delta, 4)
        self.set_font_size(new_size)
Пример #15
0
class FileSystemPane(QFrame):
    """
    Contains two QListWidgets representing the micro:bit and the user's code
    directory. Users transfer files by dragging and dropping. Highlighted files
    can be selected for deletion.
    """

    set_message = pyqtSignal(str)
    set_warning = pyqtSignal(str)
    list_files = pyqtSignal()

    def __init__(self, home):
        super().__init__()
        self.home = home
        self.font = Font().load()
        microbit_fs = MicrobitFileList(home)
        local_fs = LocalFileList(home)
        layout = QGridLayout()
        self.setLayout(layout)
        microbit_label = QLabel()
        microbit_label.setText(_('Files on your micro:bit:'))
        local_label = QLabel()
        local_label.setText(_('Files on your computer:'))
        self.microbit_label = microbit_label
        self.local_label = local_label
        self.microbit_fs = microbit_fs
        self.local_fs = local_fs
        self.set_font_size()
        layout.addWidget(microbit_label, 0, 0)
        layout.addWidget(local_label, 0, 1)
        layout.addWidget(microbit_fs, 1, 0)
        layout.addWidget(local_fs, 1, 1)
        self.microbit_fs.disable.connect(self.disable)
        self.microbit_fs.set_message.connect(self.show_message)
        self.local_fs.disable.connect(self.disable)
        self.local_fs.set_message.connect(self.show_message)

    def disable(self):
        """
        Stops interaction with the list widgets.
        """
        self.microbit_fs.setDisabled(True)
        self.local_fs.setDisabled(True)
        self.microbit_fs.setAcceptDrops(False)
        self.local_fs.setAcceptDrops(False)

    def enable(self):
        """
        Allows interaction with the list widgets.
        """
        self.microbit_fs.setDisabled(False)
        self.local_fs.setDisabled(False)
        self.microbit_fs.setAcceptDrops(True)
        self.local_fs.setAcceptDrops(True)

    def show_message(self, message):
        """
        Emits the set_message signal.
        """
        self.set_message.emit(message)

    def show_warning(self, message):
        """
        Emits the set_warning signal.
        """
        self.set_warning.emit(message)

    def on_ls(self, microbit_files):
        """
        Displays a list of the files on the micro:bit.

        Since listing files is always the final event in any interaction
        between Mu and the micro:bit, this enables the controls again for
        further interactions to take place.
        """
        self.microbit_fs.clear()
        self.local_fs.clear()
        for f in microbit_files:
            self.microbit_fs.addItem(f)
        local_files = [
            f for f in os.listdir(self.home)
            if os.path.isfile(os.path.join(self.home, f))
        ]
        local_files.sort()
        for f in local_files:
            self.local_fs.addItem(f)
        self.enable()

    def on_ls_fail(self):
        """
        Fired when listing files fails.
        """
        self.show_warning(
            _("There was a problem getting the list of files on "
              "the micro:bit. Please check Mu's logs for "
              "technical information. Alternatively, try "
              "unplugging/plugging-in your micro:bit and/or "
              "restarting Mu."))
        self.disable()

    def on_put_fail(self, filename):
        """
        Fired when the referenced file cannot be copied onto the micro:bit.
        """
        self.show_warning(
            _("There was a problem copying the file '{}' onto "
              "the micro:bit. Please check Mu's logs for "
              "more information.").format(filename))

    def on_delete_fail(self, filename):
        """
        Fired when a deletion on the micro:bit for the given file failed.
        """
        self.show_warning(
            _("There was a problem deleting '{}' from the "
              "micro:bit. Please check Mu's logs for "
              "more information.").format(filename))

    def on_get_fail(self, filename):
        """
        Fired when getting the referenced file on the micro:bit failed.
        """
        self.show_warning(
            _("There was a problem getting '{}' from the "
              "micro:bit. Please check Mu's logs for "
              "more information.").format(filename))

    def set_theme(self, theme):
        """
        Sets the theme / look for the FileSystemPane.
        """
        if theme == 'day':
            self.setStyleSheet(DAY_STYLE)
        elif theme == 'night':
            self.setStyleSheet(NIGHT_STYLE)
        else:
            self.setStyleSheet(CONTRAST_STYLE)

    def set_font_size(self, new_size=DEFAULT_FONT_SIZE):
        """
        Sets the font size for all the textual elements in this pane.
        """
        self.font.setPointSize(new_size)
        self.microbit_label.setFont(self.font)
        self.local_label.setFont(self.font)
        self.microbit_fs.setFont(self.font)
        self.local_fs.setFont(self.font)

    def zoomIn(self, delta=2):
        """
        Zoom in (increase) the size of the font by delta amount difference in
        point size upto 34 points.
        """
        old_size = self.font.pointSize()
        new_size = min(old_size + delta, 34)
        self.set_font_size(new_size)

    def zoomOut(self, delta=2):
        """
        Zoom out (decrease) the size of the font by delta amount difference in
        point size down to 4 points.
        """
        old_size = self.font.pointSize()
        new_size = max(old_size - delta, 4)
        self.set_font_size(new_size)
Пример #16
0
 def __init__(self, parent=None):
     super().__init__(parent)
     self.setFont(Font().load())
     self.input_buffer = []
Пример #17
0
class FileSystemPane(QFrame):
    """
    Contains two QListWidgets representing the micro:bit and the user's code
    directory. Users transfer files by dragging and dropping. Highlighted files
    can be selected for deletion.
    """
    def __init__(self, home):
        super().__init__()
        self.home = home
        self.font = Font().load()
        microbit_fs = MicrobitFileList(home)
        local_fs = LocalFileList(home)
        layout = QGridLayout()
        self.setLayout(layout)
        microbit_label = QLabel()
        microbit_label.setText(_('Files on your micro:bit:'))
        local_label = QLabel()
        local_label.setText(_('Files on your computer:'))
        self.microbit_label = microbit_label
        self.local_label = local_label
        self.microbit_fs = microbit_fs
        self.local_fs = local_fs
        self.set_font_size()
        layout.addWidget(microbit_label, 0, 0)
        layout.addWidget(local_label, 0, 1)
        layout.addWidget(microbit_fs, 1, 0)
        layout.addWidget(local_fs, 1, 1)
        self.ls()

    def ls(self):
        """
        Gets a list of the files on the micro:bit.

        Naive implementation for simplicity's sake.
        """
        self.microbit_fs.clear()
        self.local_fs.clear()
        microbit_files = microfs.ls(microfs.get_serial())
        for f in microbit_files:
            self.microbit_fs.addItem(f)
        local_files = [
            f for f in os.listdir(self.home)
            if os.path.isfile(os.path.join(self.home, f))
        ]
        local_files.sort()
        for f in local_files:
            self.local_fs.addItem(f)

    def set_theme(self, theme):
        """
        Sets the theme / look for the FileSystemPane.
        """
        if theme == 'day':
            self.setStyleSheet(DAY_STYLE)
        elif theme == 'night':
            self.setStyleSheet(NIGHT_STYLE)
        else:
            self.setStyleSheet(CONTRAST_STYLE)

    def set_font_size(self, new_size=DEFAULT_FONT_SIZE):
        """
        Sets the font size for all the textual elements in this pane.
        """
        self.font.setPointSize(new_size)
        self.microbit_label.setFont(self.font)
        self.local_label.setFont(self.font)
        self.microbit_fs.setFont(self.font)
        self.local_fs.setFont(self.font)

    def zoomIn(self, delta=2):
        """
        Zoom in (increase) the size of the font by delta amount difference in
        point size upto 34 points.
        """
        old_size = self.font.pointSize()
        new_size = min(old_size + delta, 34)
        self.set_font_size(new_size)

    def zoomOut(self, delta=2):
        """
        Zoom out (decrease) the size of the font by delta amount difference in
        point size down to 4 points.
        """
        old_size = self.font.pointSize()
        new_size = max(old_size - delta, 4)
        self.set_font_size(new_size)
Пример #18
0
    def __init__(self, home):
        import ctypes
        from subprocess import check_output

        def find_device():
            """
            Returns a path on the filesystem that represents the plugged in BBC
            micro:bit that is to be flashed. If no micro:bit is found, it returns
            None.

            Works on Linux, OSX and Windows. Will raise a NotImplementedError
            exception if run on any other operating system.
            """
            # Check what sort of operating system we're on.
            if os.name == 'posix':
                # 'posix' means we're on Linux or OSX (Mac).
                # Call the unix "mount" command to list the mounted volumes.
                mount_output = check_output('mount').splitlines()
                mounted_volumes = [x.split()[2] for x in mount_output]
                for volume in mounted_volumes:
                    if volume.endswith(b'MINI') or volume.endswith(
                            b'MICROBIT'):
                        return volume.decode(
                            'utf-8')  # Return a string not bytes.
            elif os.name == 'nt':
                # 'nt' means we're on Windows.

                def get_volume_name(disk_name):
                    """
                    Each disk or external device connected to windows has an attribute
                    called "volume name". This function returns the volume name for
                    the given disk/device.

                    Code from http://stackoverflow.com/a/12056414
                    """
                    vol_name_buf = ctypes.create_unicode_buffer(1024)
                    ctypes.windll.kernel32.GetVolumeInformationW(
                        ctypes.c_wchar_p(disk_name), vol_name_buf,
                        ctypes.sizeof(vol_name_buf), None, None, None, None, 0)
                    return vol_name_buf.value

                #
                # In certain circumstances, volumes are allocated to USB
                # storage devices which cause a Windows popup to raise if their
                # volume contains no media. Wrapping the check in SetErrorMode
                # with SEM_FAILCRITICALERRORS (1) prevents this popup.
                #
                old_mode = ctypes.windll.kernel32.SetErrorMode(1)
                try:
                    for disk in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ':
                        path = '{}:\\'.format(disk)
                        #
                        # Don't bother looking if the drive isn't removable
                        #
                        if ctypes.windll.kernel32.GetDriveTypeW(path) != 2:
                            continue
                        if os.path.exists(path) and \
                                get_volume_name(path) == 'MINI' or get_volume_name(path) == 'MICROBIT':
                            return get_volume_name(path)
                finally:
                    ctypes.windll.kernel32.SetErrorMode(old_mode)
            else:
                # No support for unknown operating systems.
                #raise NotImplementedError('OS "{}" not supported.'.format(os.name))
                return None

        super().__init__()
        self.home = home
        self.font = Font().load()
        microbit_fs = MicrobitFileList(home)
        local_fs = LocalFileList(home)
        self.device_displayName = "micro:bit"
        if find_device().lower().find("mini") > -1:
            microbit_fs = CalliopeMiniFileList(home)
            self.device_displayName = "Calliope mini"

        @local_fs.open_file.connect
        def on_open_file(file):
            # Bubble the signal up
            self.open_file.emit(file)

        layout = QGridLayout()
        self.setLayout(layout)
        microbit_label = QLabel()
        microbit_label.setText(
            _('Files on your {}:'.format(self.device_displayName)))
        local_label = QLabel()
        local_label.setText(_('Files on your computer:'))
        self.microbit_label = microbit_label
        self.local_label = local_label
        self.microbit_fs = microbit_fs
        self.local_fs = local_fs
        self.set_font_size()
        layout.addWidget(microbit_label, 0, 0)
        layout.addWidget(local_label, 0, 1)
        layout.addWidget(microbit_fs, 1, 0)
        layout.addWidget(local_fs, 1, 1)
        self.microbit_fs.disable.connect(self.disable)
        self.microbit_fs.set_message.connect(self.show_message)
        self.local_fs.disable.connect(self.disable)
        self.local_fs.set_message.connect(self.show_message)