def __init__(self, master, proc, title, long_description=None, autoclose=True):
        self._proc = proc
        self.stdout = ""
        self.stderr = ""
        self._stdout_thread = None
        self._stderr_thread = None
        self.returncode = None
        self.cancelled = False
        self._autoclose = autoclose
        self._event_queue = collections.deque()

        tk.Toplevel.__init__(self, master)

        self.rowconfigure(0, weight=1)
        self.columnconfigure(0, weight=1)
        main_frame = ttk.Frame(self) # To get styled background
        main_frame.grid(sticky="nsew")

        text_font=tk.font.nametofont("TkFixedFont").copy()
        #text_font["size"] = int(text_font["size"] * 0.9)
        text_font["family"] = "Courier" if running_on_mac_os() else "Courier New"
        text_frame = tktextext.TextFrame(main_frame, read_only=True, horizontal_scrollbar=False,
                                         #vertical_scrollbar=False,
                                         background=get_main_background(),
                                         font=text_font,
                                         wrap="word")
        text_frame.grid(row=0, column=0, sticky=tk.NSEW, padx=15, pady=15)
        self.text = text_frame.text
        self.text["width"] = 60
        self.text["height"] = 12
        if long_description is not None:
            self.text.direct_insert("1.0", long_description + "\n\n")

        self.button = ttk.Button(main_frame, text="Cancel", command=self._close)
        self.button.grid(row=1, column=0, pady=(0,15))

        main_frame.rowconfigure(0, weight=1)
        main_frame.columnconfigure(0, weight=1)


        self.title(title)
        if misc_utils.running_on_mac_os():
            self.configure(background="systemSheetBackground")
        #self.resizable(height=tk.FALSE, width=tk.FALSE)
        self.transient(master)
        self.grab_set() # to make it active and modal
        self.text.focus_set()


        self.bind('<Escape>', self._close_if_done, True) # escape-close only if process has completed
        self.protocol("WM_DELETE_WINDOW", self._close)
        center_window(self, master)

        self._start_listening()
Exemple #2
0
    def handle_vm_message(self, msg):
        debug("ExpressionView.handle_vm_message %s", (msg.state, msg.focus))
        
        if msg.state in ("before_expression", "before_expression_again"):
            # (re)load stuff
            if self._main_range is None or msg.focus.not_smaller_eq_in(self._main_range):
                self._load_expression(msg.filename, msg.focus)
                self._update_position(msg.focus)
                self._update_size()
                
            self._highlight_range(msg.focus, msg.state)
            
        
        elif msg.state == "after_expression":
            debug("EV: after_expression %s", msg)
            
            self.tag_configure('after', background="#BBEDB2", borderwidth=1, relief=tk.FLAT)
            start_mark = self._get_mark_name(msg.focus.lineno, msg.focus.col_offset)
            end_mark = self._get_mark_name(msg.focus.end_lineno, msg.focus.end_col_offset)
            
            if hasattr(msg, "value"):
                debug("EV: replacing expression with value")
                #print("del", start_mark, end_mark)
                self.delete(start_mark, end_mark)
                
                id_str = memory.format_object_id(msg.value.id)
                if self._workbench.get_option("view.values_in_heap"):
                    value_str = id_str
                else:
                    value_str = shorten_repr(msg.value.repr, 100)
                
                #print("ins", start_mark, value_str)
                object_tag = "object_" + str(msg.value.id)
                self.insert(start_mark, value_str, ('value', 'after', object_tag))
                if misc_utils.running_on_mac_os():
                    sequence = "<Command-Button-1>"
                else:
                    sequence = "<Control-Button-1>"
                self.tag_bind(object_tag, sequence,
                              lambda _: self._workbench.event_generate("ObjectSelect", object_id=msg.value.id))
                    
                self._update_size()
                
            else:
                debug("EV: got exc: %s", msg)
                "TODO: make it red"
                
        elif (msg.state == "before_statement_again"
              and self._main_range is not None # TODO: shouldn't need this 
              and self._main_range.is_smaller_eq_in(msg.focus)):
            # we're at final stage of executing parent statement 
            # (eg. assignment after the LHS has been evaluated)
            # don't close yet
            self.tag_configure('after', background="#DCEDF2", borderwidth=1, relief=tk.FLAT)   
        else:
            # hide and clear on non-expression events
            self.clear_debug_view()

        if hasattr(msg, "focus"):
            self._last_focus = msg.focus
Exemple #3
0
def get_busy_cursor():
    if running_on_windows():
        return "wait"
    elif running_on_mac_os():
        return "spinning"
    else:
        return "watch"
Exemple #4
0
    def _cmd_interrupt_with_shortcut(self, event=None):
        if not self._cmd_interrupt_enabled():
            return None

        if not running_on_mac_os():  # on Mac Ctrl+C is not used for Copy.
            # Disable Ctrl+C interrupt in editor and shell, when some text is selected
            # (assuming user intended to copy instead of interrupting)
            widget = get_workbench().focus_get()
            if isinstance(widget, tk.Text):
                if len(widget.tag_ranges("sel")) > 0:
                    # this test is reliable, unlike selection_get below
                    return None
            elif isinstance(widget, (tk.Listbox, ttk.Entry, tk.Entry, tk.Spinbox)):
                try:
                    selection = widget.selection_get()
                    if isinstance(selection, str) and len(selection) > 0:
                        # Assuming user meant to copy, not interrupt
                        # (IDLE seems to follow same logic)

                        # NB! This is not perfect, as in Linux the selection can be in another app
                        # ie. there may be no selection in Thonny actually.
                        # In other words, Ctrl+C interrupt may be dropped without reason
                        # when given inside the widgets listed above.
                        return None
                except Exception:
                    # widget either doesn't have selection_get or it
                    # gave error (can happen without selection on Ubuntu)
                    pass

        self._cmd_interrupt()
        return "break"
Exemple #5
0
    def update_fonts(self):
        editor_font_size = self._guard_font_size(
            self.get_option("view.editor_font_size"))
        editor_font_family = self.get_option("view.editor_font_family")
        io_font_family = self.get_option("view.io_font_family")

        self.get_font("IOFont").configure(family=io_font_family,
                                          size=min(
                                              editor_font_size - 2,
                                              int(editor_font_size * 0.8 + 3)))
        self.get_font("EditorFont").configure(family=editor_font_family,
                                              size=editor_font_size)
        self.get_font("BoldEditorFont").configure(family=editor_font_family,
                                                  size=editor_font_size)
        self.get_font("ItalicEditorFont").configure(family=editor_font_family,
                                                    size=editor_font_size)
        self.get_font("BoldItalicEditorFont").configure(
            family=editor_font_family, size=editor_font_size)

        style = ttk.Style()
        if running_on_mac_os():
            treeview_font_size = int(editor_font_size * 0.7 + 4)
            rowheight = int(treeview_font_size * 1.2 + 4)
        else:
            treeview_font_size = int(editor_font_size * 0.7 + 2)
            rowheight = int(treeview_font_size * 2.0 + 6)

        self.get_font("TreeviewFont").configure(size=treeview_font_size)
        style.configure("Treeview", rowheight=rowheight)

        if self._editor_notebook is not None:
            self._editor_notebook.update_appearance()
Exemple #6
0
    def __init__(self, master, only_user=False):
        self._state = None # possible values: "listing", "fetching", "idle"
        self._process = None
        self._installed_versions = {}
        self._only_user = only_user
        self.current_package_data = None
        
        tk.Toplevel.__init__(self, master)
        
        main_frame = ttk.Frame(self)
        main_frame.grid(sticky=tk.NSEW, ipadx=15, ipady=15)
        self.rowconfigure(0, weight=1)
        self.columnconfigure(0, weight=1)

        self.title(self._get_title())
        if misc_utils.running_on_mac_os():
            self.configure(background="systemSheetBackground")
        self.transient(master)
        self.grab_set() # to make it active
        #self.grab_release() # to allow eg. copy something from the editor 
        
        self._create_widgets(main_frame)
        
        self.search_box.focus_set()
        
        self.bind('<Escape>', self._on_close, True) 
        self.protocol("WM_DELETE_WINDOW", self._on_close)
        self._show_instructions()
        ui_utils.center_window(self, master)
        
        self._start_update_list()
    def __init__(self, master, spin_options, mode="text", **kw):
        super().__init__(master=master, **kw)
        self.frame = ttk.Frame(self, width=50)

        if len(spin_options) == 0:
            raise ValueError("spin_options must be a non empty list")
        self.options = spin_options
        self.option_val = tk.StringVar(self)
        self.option_val.set(self.options[0])
        self.hint_str = tk.StringVar(self)

        self.text = tk.Text(self.frame, height=1, width=50)
        """
        tk.Option used because thonny themes hide the option to change the value of the default list
        """
        if running_on_mac_os():
            self.option_box = tk.OptionMenu(self.frame, self.option_val,
                                            *spin_options)
        else:
            self.option_box = ttk.OptionMenu(self.frame, self.option_val,
                                             *spin_options)

        self.hint_label = ttk.Label(self, textvariable=self.hint_str)

        self.frame.pack(side=tk.TOP, fill=tk.BOTH, expand=True)

        if mode == "text":
            self.text.pack(side=tk.TOP, fill=tk.X, expand=True)
        else:
            self.option_box.pack(side=tk.TOP, fill=tk.X, expand=True)

        self.text.bind("<<Modified>>", self._on_value_change)
        self.option_val.trace("w", self._on_value_change)
Exemple #8
0
def _treeview_settings() -> BasicUiThemeSettings:
    light_blue = "#ADD8E6"
    light_grey = "#D3D3D3"

    if running_on_linux() or running_on_mac_os():
        bg_sel_focus = light_blue
        fg_sel_focus = "black"
        fg_sel_notfocus = "black"
    else:
        bg_sel_focus = "SystemHighlight"
        fg_sel_focus = "SystemHighlightText"
        fg_sel_notfocus = "SystemWindowText"

    return {
        "Treeview": {
            "configure": {"font": "TreeviewFont"},
            "map": {
                "background": [
                    ("selected", "focus", bg_sel_focus),
                    ("selected", "!focus", light_grey),
                ],
                "foreground": [
                    ("selected", "focus", fg_sel_focus),
                    ("selected", "!focus", fg_sel_notfocus),
                ],
            },
            "layout": [
                # get rid of borders
                ("Treeview.treearea", {"sticky": "nswe"})
            ],
        },
        "treearea": {"configure": {"borderwidth": 0}},
    }
Exemple #9
0
    def __init__(self, master):
        super().__init__(master)
        runscript_label = ttk.Label(self,
                                    text="Running current script in terminal:")
        runscript_label.grid(row=0, column=0, sticky="w")

        self.add_checkbox(
            "run.run_in_terminal_python_repl",
            "Present Python REPL after program ends",
            row=1,
            padx=(12, 0),
        )

        self.add_checkbox(
            "run.run_in_terminal_keep_open",
            "Keep terminal window open after Python process ends",
            row=2,
            padx=(12, 0),
        )

        exit_remark = " "
        if running_on_mac_os():
            exit_remark = (
                "NB! Automatic closing needs to be enabled in Terminal's settings\n"
                + "(Profiles → Shell → When the shell exits)")
        remark_label = ttk.Label(self, text=exit_remark)
        remark_label.grid(row=3,
                          column=0,
                          sticky="w",
                          padx=(12, 0),
                          pady=(0, 10))
Exemple #10
0
    def show_file(self,
                  filename,
                  text_range=None,
                  set_focus=True,
                  propose_dialog=True):
        # self.close_single_untitled_unmodified_editor()
        try:
            editor = self.get_editor(filename, True)
        except PermissionError:
            logger.exception("Loading " + filename)
            msg = "Got permission error when trying to load\n" + filename
            if running_on_mac_os() and propose_dialog:
                msg += "\n\nTry opening it with File => Open."

            messagebox.showerror("Permission error", msg, master=self)
            return None

        if editor is None:
            return

        self.select(editor)
        if set_focus:
            editor.focus_set()

        if text_range is not None:
            editor.select_range(text_range)

        return editor
Exemple #11
0
    def _replace(self, focus, value):
        start_mark = self._get_mark_name(focus.lineno, focus.col_offset)
        end_mark = self._get_mark_name(focus.end_lineno, focus.end_col_offset)

        self.delete(start_mark, end_mark)

        id_str = memory.format_object_id(value.id)
        if get_workbench().in_heap_mode():
            value_str = id_str
        else:
            value_str = shorten_repr(value.repr, 100)

        object_tag = "object_" + str(value.id)
        self.insert(start_mark, value_str, ("value", object_tag))
        if misc_utils.running_on_mac_os():
            sequence = "<Command-Button-1>"
        else:
            sequence = "<Control-Button-1>"
        self.tag_bind(
            object_tag,
            sequence,
            lambda _: get_workbench().event_generate(
                "ObjectSelect", object_id=value.id
            ),
        )
Exemple #12
0
def load_plugin(workbench):
    workbench.add_command("about", 
        "Thonny" if running_on_mac_os() else "help",
        "About Thonny",
        lambda: AboutDialog(workbench, workbench.get_version()))

    
Exemple #13
0
def open_with_default_app(path):
    if running_on_windows():
        os.startfile(path)
    elif running_on_mac_os():
        subprocess.run(["open", path])
    else:
        subprocess.run(["xdg-open", path])
Exemple #14
0
def open_path_in_system_file_manager(path):
    if running_on_mac_os():
        # http://stackoverflow.com/a/3520693/261181
        subprocess.Popen(["open", "-R", path])
    elif running_on_linux():
        subprocess.Popen(["xdg-open", path])
    else:
        assert running_on_windows()
        subprocess.Popen(["explorer", path])
Exemple #15
0
    def _set_window_attributes(self):
        if running_on_mac_os():
            try:
                # Must be the first thing to do after creating window
                # https://wiki.tcl-lang.org/page/MacWindowStyle
                self.tk.call("::tk::unsupported::MacWindowStyle", "style",
                             self._w, "help", "noActivates")
                if get_tk_version_info() >= (8, 6, 10) and running_on_mac_os():
                    self.wm_overrideredirect(1)
            except tk.TclError:
                pass
        else:
            self.wm_overrideredirect(1)
        self.wm_transient(get_workbench())

        # From IDLE
        # TODO: self.update_idletasks()  # Need for tk8.6.8 on macOS: #40128.
        self.lift()
Exemple #16
0
def select_sequence(win_version, mac_version, linux_version=None):
    if running_on_windows():
        return win_version
    elif running_on_mac_os():
        return mac_version
    elif running_on_linux() and linux_version:
        return linux_version
    else:
        return win_version
Exemple #17
0
def open_path_in_system_file_manager(path):
    if running_on_mac_os():
        # http://stackoverflow.com/a/3520693/261181
        subprocess.Popen(["open", "-R", path])
    elif running_on_linux():
        subprocess.Popen(["xdg-open", path])
    else:
        assert running_on_windows()
        subprocess.Popen(["explorer", path])
Exemple #18
0
    def __init__(self,
                 master,
                 show_hidden_files=False,
                 last_folder_setting_name=None,
                 breadcrumbs_pady=(5, 7)):
        self._cached_dir_data = {}
        ttk.Frame.__init__(self, master, borderwidth=0, relief="flat")
        self.vert_scrollbar = ttk.Scrollbar(self,
                                            orient=tk.VERTICAL,
                                            style=scrollbar_style("Vertical"))
        self.vert_scrollbar.grid(row=0, column=1, sticky=tk.NSEW, rowspan=3)

        tktextext.fixwordbreaks(tk._default_root)
        self.building_breadcrumbs = False
        self.init_header(row=0, column=0)

        spacer = ttk.Frame(self, height=1)
        spacer.grid(row=1, sticky="nsew")

        self.tree = ttk.Treeview(
            self,
            columns=["#0", "kind", "path"],
            displaycolumns=(0, ),
            yscrollcommand=self.vert_scrollbar.set,
        )
        self.tree["show"] = "headings"
        self.tree.grid(row=2, column=0, sticky=tk.NSEW)
        self.vert_scrollbar["command"] = self.tree.yview
        self.columnconfigure(0, weight=1)
        self.rowconfigure(2, weight=1)

        self.show_hidden_files = show_hidden_files
        self.tree["show"] = ("tree", )

        self.tree.bind("<3>", self.on_secondary_click, True)
        if misc_utils.running_on_mac_os():
            self.tree.bind("<2>", self.on_secondary_click, True)
            self.tree.bind("<Control-1>", self.on_secondary_click, True)
        self.tree.bind('<Double-Button-1>', self.on_double_click, True)
        self.tree.bind("<<TreeviewOpen>>", self.on_open_node)

        wb = get_workbench()
        self.folder_icon = wb.get_image("folder")
        self.python_file_icon = wb.get_image("python-file")
        self.text_file_icon = wb.get_image("text-file")
        self.generic_file_icon = wb.get_image("generic-file")
        self.hard_drive_icon = wb.get_image("hard-drive")

        self.tree.column("#0", width=500, anchor=tk.W)

        # set-up root node
        self.tree.set("", "kind", "root")
        self.menu = tk.Menu(self.tree, tearoff=False)

        self._last_folder_setting_name = last_folder_setting_name
        self.focus_into_saved_folder()
Exemple #19
0
 def __init__(self, master, show_hidden_files=False):
     BaseFileBrowser.__init__(self, master, show_hidden_files, "file.last_browser_folder")
     
     self.menu = tk.Menu(tk._default_root, tearoff=False)
     self.menu.add_command(label="Create new file", command=self.create_new_file)
     
     self.tree.bind('<3>', self.on_secondary_click, True)
     if misc_utils.running_on_mac_os():
         self.tree.bind('<2>', self.on_secondary_click, True)
         self.tree.bind('<Control-1>', self.on_secondary_click, True)
Exemple #20
0
 def __init__(self):
     wb = get_workbench()
     wb.bind_class("EditorCodeViewText", "<1>", self.request_definitions, True)
     wb.bind_class("EditorCodeViewText", "<Any-Motion>", self.on_motion, True)
     wb.bind_class("EditorCodeViewText", "<Any-Leave>", self.remove_underline, True)
     if running_on_mac_os():
         wb.bind_class("EditorCodeViewText", "<Command-KeyRelease>", self.remove_underline, True)
     else:
         wb.bind_class("EditorCodeViewText", "<Control-KeyRelease>", self.remove_underline, True)
     wb.bind("get_definitions_response", self.handle_definitions_response, True)
Exemple #21
0
    def _handle_toplevel_response(self, msg: ToplevelResponse) -> None:
        if msg.get("error"):
            self._insert_text_directly(msg["error"] + "\n",
                                       ("toplevel", "stderr"))
            self._ensure_visible()

        if "user_exception" in msg:
            self._show_user_exception(msg["user_exception"])
            self._ensure_visible()

        welcome_text = msg.get("welcome_text")
        if welcome_text and welcome_text != self._last_welcome_text:
            self._insert_text_directly(welcome_text, ("comment", ))
            self._last_welcome_text = welcome_text

        if "value_info" in msg:
            num_stripped_question_marks = getattr(
                msg, "num_stripped_question_marks", 0)
            if num_stripped_question_marks > 0:
                # show the value in object inspector
                get_workbench().event_generate("ObjectSelect",
                                               object_id=msg["value_info"].id)
            else:
                # show the value in shell
                value_repr = shorten_repr(msg["value_info"].repr, 10000)
                if value_repr != "None":
                    if get_workbench().in_heap_mode():
                        value_repr = memory.format_object_id(
                            msg["value_info"].id)
                    object_tag = "object_" + str(msg["value_info"].id)
                    self._insert_text_directly(
                        value_repr + "\n", ("toplevel", "value", object_tag))
                    if running_on_mac_os():
                        sequence = "<Command-Button-1>"
                    else:
                        sequence = "<Control-Button-1>"
                    self.tag_bind(
                        object_tag,
                        sequence,
                        lambda _: get_workbench().event_generate(
                            "ObjectSelect", object_id=msg["value_info"].id),
                    )

                    self.active_object_tags.add(object_tag)

        self.mark_set("output_end", self.index("end-1c"))
        self._discard_old_content()
        self._update_visible_io(None)
        self._reset_ansi_attributes()
        self._io_cursor_offset = 0
        self._insert_prompt()
        self._try_submit_input(
        )  # Trying to submit leftover code (eg. second magic command)
        self.see("end")
Exemple #22
0
 def _get_interpreters(cls):
     result = set()
     
     if running_on_windows():
         # registry
         result.update(CPythonProxy._get_interpreters_from_windows_registry())
         
         # Common locations
         for dir_ in ["C:\\Python34",
                      "C:\\Python35",
                      "C:\\Program Files\\Python 3.5",
                      "C:\\Program Files (x86)\\Python 3.5",
                      "C:\\Python36",
                      "C:\\Program Files\\Python 3.6",
                      "C:\\Program Files (x86)\\Python 3.6",
                      ]:
             path = os.path.join(dir_, "pythonw.exe")
             if os.path.exists(path):
                 result.add(os.path.realpath(path))  
     
     else:
         # Common unix locations
         for dir_ in ["/bin", "/usr/bin", "/usr/local/bin",
                      os.path.expanduser("~/.local/bin")]:
             for name in ["python3", "python3.4", "python3.5", "python3.6"]:
                 path = os.path.join(dir_, name)
                 if os.path.exists(path):
                     result.add(path)  
     
     if running_on_mac_os():
         for version in ["3.4", "3.5", "3.6"]:
             dir_ = os.path.join("/Library/Frameworks/Python.framework/Versions",
                                 version, "bin")
             path = os.path.join(dir_, "python3")
             
             if os.path.exists(path):
                 result.add(path)
     
     for command in ["pythonw", "python3", "python3.4", "python3.5", "python3.6"]:
         path = which(command)
         if path is not None:
             result.add(path)
     
     current_configuration = get_workbench().get_option("run.backend_configuration")
     backend, configuration_option = parse_configuration(current_configuration)
     if backend == "Python" and configuration_option and os.path.exists(configuration_option):
         result.add(os.path.realpath(configuration_option))
     
     for path in get_workbench().get_option("run.used_interpreters"):
         if os.path.exists(path):
             result.add(os.path.realpath(path))
     
     return sorted(result)
Exemple #23
0
    def _init_fonts(self):
        self.set_default("view.io_font_family",
                         "Courier" if running_on_mac_os() else "Courier New")

        default_editor_family = "Courier New"
        families = tk_font.families()

        for family in ["Consolas", "Ubuntu Mono", "Menlo", "DejaVu Sans Mono"]:
            if family in families:
                default_editor_family = family
                break

        self.set_default("view.editor_font_family", default_editor_family)
        self.set_default("view.editor_font_size",
                         14 if running_on_mac_os() else 11)

        default_font = tk_font.nametofont("TkDefaultFont")

        self._fonts = {
            'IOFont':
            tk_font.Font(family=self.get_option("view.io_font_family")),
            'EditorFont':
            tk_font.Font(family=self.get_option("view.editor_font_family")),
            'BoldEditorFont':
            tk_font.Font(family=self.get_option("view.editor_font_family"),
                         weight="bold"),
            'ItalicEditorFont':
            tk_font.Font(family=self.get_option("view.editor_font_family"),
                         slant="italic"),
            'BoldItalicEditorFont':
            tk_font.Font(family=self.get_option("view.editor_font_family"),
                         weight="bold",
                         slant="italic"),
            'TreeviewFont':
            tk_font.Font(family=default_font.cget("family"),
                         size=default_font.cget("size"))
        }

        self.update_fonts()
Exemple #24
0
    def __init__(self, codeview):
        tk.Toplevel.__init__(self, codeview.winfo_toplevel())
        text = tk.Text(self, **self.get_text_options())
        BaseExpressionBox.__init__(self, codeview, text)
        self.text.grid()

        if running_on_mac_os():
            try:
                # NB! Must be the first thing to do after creation
                # https://wiki.tcl-lang.org/page/MacWindowStyle
                self.tk.call("::tk::unsupported::MacWindowStyle", "style",
                             self._w, "help", "noActivates")
            except TclError:
                pass
        else:
            raise RuntimeError("Should be used only on Mac")

        self.resizable(False, False)
        if get_tk_version_info() >= (8, 6, 10) and running_on_mac_os():
            self.wm_overrideredirect(1)
        self.wm_transient(codeview.winfo_toplevel())
        self.lift()
Exemple #25
0
    def _cmd_interrupt_enabled(self):
        widget = get_workbench().focus_get()
        if not running_on_mac_os(): # on Mac Ctrl+C is not used for Copy
            if hasattr(widget, "selection_get"):
                try:
                    if widget.selection_get() != "":
                        # assuming user meant to copy, not interrupt
                        # (IDLE seems to follow same logic)
                        return False
                except:
                    # selection_get() gives error when calling without selection on Ubuntu
                    pass

        return get_runner().get_state() != "waiting_toplevel_command"
Exemple #26
0
    def __init__(self, master):
        tk.Toplevel.__init__(self, master)

        self.title(_("Configure shell macro"))
        if misc_utils.running_on_mac_os():
            self.configure(background="systemSheetBackground")
        self.transient(master)
        self.grab_set()  # to make it active
        # self.grab_release() # to allow eg. copy something from the editor

        self._create_widgets()

        self.bind("<Escape>", self._on_close, True)
        self.protocol("WM_DELETE_WINDOW", self._on_close)
        self.main_command_text.focus_set()
Exemple #27
0
    def _preview_submission_data(self, event=None):
        temp_path = os.path.join(
            tempfile.mkdtemp(),
            "ThonnyAssistantFeedback_" +
            datetime.datetime.now().isoformat().replace(":", ".")[:19] +
            ".txt",
        )
        data = self._collect_submission_data()
        with open(temp_path, "w", encoding="ascii") as fp:
            fp.write(data)

        if running_on_mac_os():
            subprocess.Popen(["open", "-e", temp_path])
        else:
            webbrowser.open(temp_path)
Exemple #28
0
    def __init__(self, master, show_hidden_files=False):
        BaseFileBrowser.__init__(self, master, show_hidden_files,
                                 "file.last_browser_folder")

        self.menu = tk.Menu(tk._default_root, tearoff=False)
        self.menu.add_command(label="Create new file",
                              command=self.create_new_file)

        self.tree.bind("<3>", self.on_secondary_click, True)
        if misc_utils.running_on_mac_os():
            self.tree.bind("<2>", self.on_secondary_click, True)
            self.tree.bind("<Control-1>", self.on_secondary_click, True)

        self.set_breadcrumbs(
            "C:\\Users\\Aivar\\Documents\\Python\\PyGame\\NikaNaka")
Exemple #29
0
    def __init__(self, master):
        super().__init__(master)

        self._configuration_variable = create_string_var(
            get_workbench().get_option("CustomInterpreter.path"))

        entry_label = ttk.Label(self, text=tr("Python executable"))
        entry_label.grid(row=0, column=1, columnspan=2, sticky=tk.W)

        self._entry = ttk.Combobox(
            self,
            exportselection=False,
            textvariable=self._configuration_variable,
            values=_get_interpreters(),
        )

        self._entry.grid(row=1, column=1, sticky=tk.NSEW)

        self._select_button = ttk.Button(
            self,
            text="...",
            width=3,
            command=self._select_executable,
        )
        self._select_button.grid(row=1, column=2, sticky="e", padx=(10, 0))
        self.columnconfigure(1, weight=1)

        extra_text = tr("NB! Thonny only supports Python 3.5 and later")
        if running_on_mac_os():
            extra_text += "\n\n" + tr(
                "NB! File selection button may not work properly when selecting executables\n"
                +
                "from a virtual environment. In this case choose the 'activate' script instead\n"
                +
                "of the interpreter (or enter the path directly to the box)!")
        extra_label = ttk.Label(self, text=extra_text)
        extra_label.grid(row=2, column=1, columnspan=2, pady=10, sticky="w")

        last_row = ttk.Frame(self)
        last_row.grid(row=100, sticky="swe", column=1, columnspan=2)
        self.rowconfigure(100, weight=1)
        last_row.columnconfigure(1, weight=1)
        new_venv_link = ui_utils.create_action_label(
            last_row,
            "New virtual environment",
            self._create_venv,
        )
        new_venv_link.grid(row=0, column=1, sticky="e", pady=10)
Exemple #30
0
    def _handle_toplevel_result(self, msg):
        self["font"] = get_workbench().get_font("EditorFont")
        self._before_io = True
        if hasattr(msg, "error"):
            self._insert_text_directly(msg.error + "\n", ("toplevel", "error"))

        if hasattr(msg, "welcome_text"):
            configuration = get_workbench().get_option(
                "run.backend_configuration")
            welcome_text = msg.welcome_text
            if hasattr(
                    msg, "executable"
            ) and msg.executable != thonny.running.get_private_venv_executable(
            ):
                welcome_text += " (" + msg.executable + ")"
            if (configuration != self._last_configuration
                    and not (self._last_configuration is None
                             and not configuration)):
                self._insert_text_directly(welcome_text, ("welcome", ))

            self._last_configuration = get_workbench().get_option(
                "run.backend_configuration")

        if hasattr(msg, "value_info"):
            value_repr = shorten_repr(msg.value_info["repr"], 10000)
            if value_repr != "None":
                if get_workbench().in_heap_mode():
                    value_repr = memory.format_object_id(msg.value_info["id"])
                object_tag = "object_" + str(msg.value_info["id"])
                self._insert_text_directly(value_repr + "\n",
                                           ("toplevel", "value", object_tag))
                if running_on_mac_os():
                    sequence = "<Command-Button-1>"
                else:
                    sequence = "<Control-Button-1>"
                self.tag_bind(
                    object_tag, sequence,
                    lambda _: get_workbench().event_generate(
                        "ObjectSelect", object_id=msg.value_info["id"]))

                self.active_object_tags.add(object_tag)

        self.mark_set("output_end", self.index("end-1c"))
        self._insert_prompt()
        self._try_submit_input(
        )  # Trying to submit leftover code (eg. second magic command)
        self.see("end")
Exemple #31
0
    def __init__(self, text_frame, frame_info):
        self._text_frame = text_frame
        self._text = text_frame.text
        self._frame_info = frame_info
        self._frame_id = frame_info.id
        self._filename = frame_info.filename
        self._firstlineno = None
        if running_on_mac_os():
            self._expression_box = ToplevelExpressionBox(text_frame)
        else:
            self._expression_box = PlacedExpressionBox(text_frame)

        self._note_box = ui_utils.NoteBox(text_frame.winfo_toplevel())
        self._next_frame_visualizer = None
        self._prev_frame_visualizer = None
        self._text.set_read_only(True)
        self._line_debug = frame_info.current_statement is None

        self._reconfigure_tags()
Exemple #32
0
    def _cmd_interrupt_enabled(self) -> bool:
        if not self._proxy or not self._proxy.is_functional():
            return False
        # TODO: distinguish command and Ctrl+C shortcut

        widget = get_workbench().focus_get()
        if not running_on_mac_os():  # on Mac Ctrl+C is not used for Copy
            if widget is not None and hasattr(widget, "selection_get"):
                try:
                    selection = widget.selection_get()
                    if isinstance(selection, str) and len(selection) > 0:
                        # assuming user meant to copy, not interrupt
                        # (IDLE seems to follow same logic)
                        return False
                except Exception:
                    # selection_get() gives error when calling without selection on Ubuntu
                    pass

        return self.is_running() or self.is_waiting_toplevel_command()
Exemple #33
0
    def _check_connection(self, port):
        proxy = get_runner().get_backend_proxy()
        if isinstance(proxy, MicroPythonProxy):
            # Most likely it is using the same port
            proxy.disconnect()
            time.sleep(1.5)

        # Maybe another program is connected
        # or the user doesn't have sufficient permissions?
        try:
            conn = SerialConnection(port, 115200, skip_reader=True)
            conn.close()

            return True
        except Exception as e:
            messagebox.showerror("Can't connect",
                                 str(e),
                                 master=None if running_on_mac_os() else self)
            return False
Exemple #34
0
 def __init__(self, master, workbench, show_hidden_files=False): # TODO: refactor universal file browser
     TreeFrame.__init__(self, master, 
                        ["#0", "kind", "path"], 
                        displaycolumns=(0,))
     #print(self.get_toplevel_items())
     self._workbench = workbench
     self.editor_notebook = workbench.get_editor_notebook()
     self.show_hidden_files = show_hidden_files
     self.tree['show'] = ('tree',)
     
     self.hor_scrollbar = ttk.Scrollbar(self, orient=tk.HORIZONTAL)
     self.tree.config(xscrollcommand=self.hor_scrollbar.set)
     self.hor_scrollbar['command'] = self.tree.xview
     self.hor_scrollbar.grid(row=1, column=0, sticky="nsew")
     
     self.folder_icon = tk.PhotoImage(file=misc_utils.get_res_path("folder.gif"))
     self.python_file_icon = tk.PhotoImage(file=misc_utils.get_res_path("python_file.gif"))
     self.text_file_icon = tk.PhotoImage(file=misc_utils.get_res_path("text_file.gif"))
     self.generic_file_icon = tk.PhotoImage(file=misc_utils.get_res_path("generic_file.gif"))
     self.hard_drive_icon = tk.PhotoImage(file=misc_utils.get_res_path("hard_drive2.gif"))
     
     self.tree.column('#0', width=500, anchor=tk.W)
     
     # set-up root node
     self.tree.set("", "kind", "root")
     self.tree.set("", "path", "")
     self.refresh_tree()
     
     
     self.tree.bind("<<TreeviewOpen>>", self.on_open_node)
     
     self.menu = tk.Menu(tk._default_root, tearoff=False)
     self.menu.add_command(label="Create new file", command=self.create_new_file)
     
     self.tree.bind('<3>', self.on_secondary_click)
     if misc_utils.running_on_mac_os():
         self.tree.bind('<2>', self.on_secondary_click)
         self.tree.bind('<Control-1>', self.on_secondary_click)
 
     self.open_initial_folder()
Exemple #35
0
 def _handle_vm_message(self, msg):
     if isinstance(msg, InputRequest):
         self.text_mode = "io"
         self.text["font"] = self._workbench.get_font("IOFont") # otherwise the cursor is of toplevel size
         self.text.focus_set()
         self.text.mark_set("insert", "end")
         self.text.tag_remove("sel", "1.0", tk.END)
         self._try_submit_input() # try to use leftovers from previous request
         self.text.see("end")
         
     elif isinstance(msg, OutputEvent):
         self.text_mode = "io"
         self.text["font"] = self._workbench.get_font("IOFont")
         
         # mark first line of io
         if self._before_io:
             self._insert_text_directly(msg.data[0], ("io", msg.stream_name, "vertically_spaced"))
             self._before_io = False
             self._insert_text_directly(msg.data[1:], ("io", msg.stream_name))
         else:
             self._insert_text_directly(msg.data, ("io", msg.stream_name))
         
         self.text.mark_set("output_end", self.text.index("end-1c"))
         self.text.see("end")
         
     elif isinstance(msg, ToplevelResponse):
         
         self.text_mode = "toplevel"
         self.text["font"] = self._workbench.get_font("EditorFont")
         self._before_io = True
         if hasattr(msg, "error"):
             self._insert_text_directly(msg.error + "\n", ("toplevel", "error"))
             
         if hasattr(msg, "value_info"):
             value_repr = shorten_repr(msg.value_info.repr, 10000)
             if value_repr != "None":
                 if self._workbench.in_heap_mode():
                     value_repr = memory.format_object_id(msg.value_info.id)
                 object_tag = "object_" + str(msg.value_info.id)
                 self._insert_text_directly(value_repr + "\n", ("toplevel",
                                                                "value",
                                                                object_tag))
                 if running_on_mac_os():
                     sequence = "<Command-Button-1>"
                 else:
                     sequence = "<Control-Button-1>"
                 self.text.tag_bind(object_tag, sequence,
                                    lambda _: self._workbench.event_generate(
                                         "ObjectSelect", object_id=msg.value_info.id))
                 
                 self.active_object_tags.add(object_tag)
         
         self.text.mark_set("output_end", self.text.index("end-1c"))
         self._insert_prompt()
         self._try_submit_input()
         self.text.see("end")
         
         # TODO: show cwd if it has changed
         """
         if hasattr(msg, "event") and msg.event == "reset":
             # make current dir visible (again)
             self.submit_magic_command("%cd " + self._workbench.get_runner().get_cwd() + "\n")
         """
         
     else:
         pass
Exemple #36
0
    def __init__(self, master, workbench):
        tk.Toplevel.__init__(self, master, borderwidth=15, takefocus=1)
        self._workbench = workbench
        self.codeview = master; 
        self._init_found_tag_styles();  #sets up the styles used to highlight found strings
        #references to the current set of passive found tags e.g. all words that match the searched term but are not the active string
        self.passive_found_tags = set()
        self.active_found_tag = None    #reference to the currently active (centered) found string

        #if find dialog was used earlier then put the previous search word to the Find entry field
        #TODO - refactor this, there must be a better way
        try:
            #if find dialog was used earlier then this is present
            FindDialog.last_searched_word = FindDialog.last_searched_word
        except:
            FindDialog.last_searched_word = None #if this variable does not exist then this is the first time find dialog has been launched

        #a tuple containing the start and indexes of the last processed string
        #if the last action was find, then the end index is start index + 1
        #if the last action was replace, then the indexes correspond to the start
        #and end of the inserted word
        self.last_processed_indexes = None
        self.last_search_case = None    #case sensitivity value used during the last search
        
        #set up window display
        self.geometry("+%d+%d" % (master.winfo_rootx() + master.winfo_width() // 2,
                                  master.winfo_rooty() + master.winfo_height() // 2 - 150))

        self.title("Find & Replace")
        if misc_utils.running_on_mac_os():
            self.configure(background="systemSheetBackground")
        self.resizable(height=tk.FALSE, width=tk.FALSE)
        self.transient(master) 
        self.grab_set()        
        self.protocol("WM_DELETE_WINDOW", self._ok)
      
        #Find text label
        self.find_label = ttk.Label(self, text="Find:");    #TODO - text to resources package
        self.find_label.grid(column=0, row=0);

        #Find text field
        self.find_entry_var = tk.StringVar()
        self.find_entry = ttk.Entry(self, textvariable=self.find_entry_var);
        self.find_entry.grid(column=1, row=0, columnspan=2, padx=5);
        if FindDialog.last_searched_word is not None:
            self.find_entry.insert(0, FindDialog.last_searched_word)
        self.find_entry.focus_force();

        #Replace text label
        self.replace_label = ttk.Label(self, text="Replace with:");    #TODO - text to resources package
        self.replace_label.grid(column=0, row=1);

        #Replace text field
        self.replace_entry = ttk.Entry(self);
        self.replace_entry.grid(column=1, row=1, columnspan=2, padx=5);

        #Info text label (invisible by default, used to tell user that searched string was not found etc)
        self.infotext_label_var = tk.StringVar();
        self.infotext_label_var.set("");
        self.infotext_label = ttk.Label(self, textvariable=self.infotext_label_var, foreground="red"); #TODO - style to conf
        self.infotext_label.grid(column=0, row=2, columnspan=3,pady=3);

        #Case checkbox
        self.case_var = tk.IntVar()
        self.case_checkbutton = ttk.Checkbutton(self,text="Case sensitive",variable=self.case_var);  #TODO - text to resources
        self.case_checkbutton.grid(column=0, row=3)

        #Direction radiobuttons
        self.direction_var = tk.IntVar()
        self.up_radiobutton = ttk.Radiobutton(self, text="Up", variable=self.direction_var, value=1)
        self.up_radiobutton.grid(column=1, row=3)
        self.down_radiobutton = ttk.Radiobutton(self, text="Down", variable=self.direction_var, value=2)
        self.down_radiobutton.grid(column=2, row=3)
        self.down_radiobutton.invoke()

        #Find button - goes to the next occurrence
        self.find_button = ttk.Button(self, text="Find", command=self._perform_find) #TODO - text to resources
        self.find_button.grid(column=3, row=0, sticky=tk.W + tk.E);
        self.find_button.config(state='disabled') 

        #Replace button - replaces the current occurrence, if it exists
        self.replace_button = ttk.Button(self, text="Replace", command=self._perform_replace) #TODO - text to resources
        self.replace_button.grid(column=3, row=1, sticky=tk.W + tk.E);
        self.replace_button.config(state='disabled')

        #Replace + find button - replaces the current occurence and goes to next
        self.replace_and_find_button = ttk.Button(self, text="Replace+Find", command=self._perform_replace_and_find) #TODO - text to resources
        self.replace_and_find_button.grid(column=3, row=2, sticky=tk.W + tk.E);
        self.replace_and_find_button.config(state='disabled')  
 
        #Replace all button - replaces all occurrences
        self.replace_all_button = ttk.Button(self, text="Replace all", command=self._perform_replace_all) #TODO - text to resources
        self.replace_all_button.grid(column=3, row=3, sticky=tk.W + tk.E);        
        if FindDialog.last_searched_word == None:
            self.replace_all_button.config(state='disabled') 

        #create bindings
        self.bind('<Escape>', self._ok)
        self.find_entry.bind('<Return>', self._perform_find)
        self.find_entry.bind('<Return>', self._perform_find)
        self.find_entry_var.trace('w', self._update_button_statuses)

        self._update_button_statuses()

        self.wait_window()
Exemple #37
0
def load_plugin(workbench):
    if running_on_mac_os():
        _set_up_mac_specific_stuff()
Exemple #38
0
    def __init__(self, master, version):
        tk.Toplevel.__init__(self, master, borderwidth=15)
        
        #self.geometry("200x200")
        # TODO: position in the center of master
        self.geometry("+%d+%d" % (master.winfo_rootx() + master.winfo_width() // 2 - 50,
                                  master.winfo_rooty() + master.winfo_height() // 2 - 150))

        self.title("About Thonny")
        if misc_utils.running_on_mac_os():
            self.configure(background="systemSheetBackground")
        self.resizable(height=tk.FALSE, width=tk.FALSE)
        self.transient(master)
        self.grab_set()
        self.protocol("WM_DELETE_WINDOW", self._ok)
        
        
        #bg_frame = ttk.Frame(self) # gives proper color in aqua
        #bg_frame.grid()
        
        heading_font = font.nametofont("TkHeadingFont").copy()
        heading_font.configure(size=19, weight="bold")
        heading_label = ttk.Label(self, 
                                  text="Thonny " + str(version),
                                  font=heading_font)
        heading_label.grid()
        
        
        url = "http://thonny.cs.ut.ee"
        url_font = font.nametofont("TkDefaultFont").copy()
        url_font.configure(underline=1)
        url_label = ttk.Label(self, text=url,
                              cursor="hand2",
                              foreground="blue",
                              font=url_font,)
        url_label.grid()
        url_label.bind("<Button-1>", lambda _:webbrowser.open(url))
        
        python_version = ".".join(map(str, sys.version_info[:3]))
        if sys.version_info[3] != "final":
            python_version += "-" + sys.version_info[3]
        platform_label = ttk.Label(self, justify=tk.CENTER, 
                                   text=platform.system() + " " 
                                        + platform.release()  
                                        + " " + self.get_os_word_size_guess() + "\n"
                                        + "Python " + python_version 
                                        + " (" + ("64" if sys.maxsize > 2**32 else "32")+ " bit)\n"
                                        + "Tk " + self.tk.call('info', 'patchlevel'))
        platform_label.grid(pady=20)
        
        license_font = font.nametofont("TkDefaultFont").copy()
        license_font.configure(size=7)
        license_label = ttk.Label(self,
                                  text="Coppyright (©) 2014 Aivar Annamaa\n"
                                  + "This program comes with\n"
                                  + "ABSOLUTELY NO WARRANTY!\n"
                                  + "It is free software, and you are welcome to\n"
                                  + "redistribute it under certain conditions, see\n"
                                  + "http://www.gnu.org/licenses/gpl-3.0.txt\n"
                                  + "for details\n",
                                  justify=tk.CENTER, font=license_font)
        license_label.grid()
        
        ok_button = ttk.Button(self, text="OK", command=self._ok)
        ok_button.grid()
        ok_button.focus_set()
        
        self.bind('<Return>', self._ok) 
        self.bind('<Escape>', self._ok) 
        self.wait_window()