Ejemplo n.º 1
0
    def __init__(self, parent, env, path=""):
        StyledTextCtrl.__init__(self, parent, env)
        wx.FileDropTarget.__init__(self)
        self.SetDropTarget(self)

        self.path = path
        self.file_encoding = "utf-8"
        self.modified_externally = False
        self.static_title = None

        self.sig_title_changed = Signal(self)
        self.sig_status_changed = Signal(self)

        self.SetTabIndents(True)
        self.SetBackSpaceUnIndents(True)
        self.SetViewWhiteSpace(wx.stc.STC_WS_VISIBLEALWAYS)
        self.SetWhitespaceForeground(True, "#dddddd")
        self.SetEdgeMode(wx.stc.STC_EDGE_LINE)
        self.SetEdgeColumn(80)
        self.SetEdgeColour("#dddddd")

        self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
        self.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown)
        self.Bind(wx.stc.EVT_STC_SAVEPOINTLEFT, self.OnSavePointLeft)
        self.Bind(wx.stc.EVT_STC_SAVEPOINTREACHED, self.OnSavePointReached)
        self.Bind(wx.stc.EVT_STC_UPDATEUI, self.OnStcUpdateUI)
Ejemplo n.º 2
0
    def __init__(self, parent, env, url="", show_browser_ui=True):
        wx.Panel.__init__(self, parent)

        self.env = env
        self.show_browser_ui = show_browser_ui
        self.sig_title_changed = Signal()
        self.sig_status_changed = Signal()

        import wx.html2 as webview
        self.wv = webview.WebView.New(self, url=url)

        sizer = wx.BoxSizer(wx.VERTICAL)

        if show_browser_ui:
            btnSizer = wx.BoxSizer(wx.HORIZONTAL)

            btn = wx.BitmapButton(self, bitmap=resources.load_bitmap("icons/back.png"))
            self.Bind(wx.EVT_BUTTON, self.OnBack, btn)
            self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI_Back, btn)
            btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

            btn = wx.BitmapButton(self, bitmap=resources.load_bitmap("icons/forward.png"))
            self.Bind(wx.EVT_BUTTON, self.OnForward, btn)
            self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI_Forward, btn)
            btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

            btn = wx.BitmapButton(self, bitmap=resources.load_bitmap("icons/stop.png"))
            self.Bind(wx.EVT_BUTTON, self.OnStop, btn)
            self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI_Stop, btn)
            btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

            btn = wx.BitmapButton(self, bitmap=resources.load_bitmap("icons/refresh.png"))
            self.Bind(wx.EVT_BUTTON, self.OnRefresh, btn)
            self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI_Refresh, btn)
            btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

            self.location = wx.ComboBox(self, value=url, style=wx.CB_DROPDOWN|wx.TE_PROCESS_ENTER)
            self.Bind(wx.EVT_COMBOBOX, self.OnLocationSelect, self.location)
            self.location.Bind(wx.EVT_TEXT_ENTER, self.OnLocationEnter)
            btnSizer.Add(self.location, 1, wx.ALIGN_CENTRE_VERTICAL|wx.ALL, 2)

            sizer.Add(btnSizer, 0, wx.EXPAND)

        sizer.Add(self.wv, 1, wx.EXPAND)
        self.SetSizer(sizer)

        self.Bind(webview.EVT_WEBVIEW_NAVIGATING, self.OnWebViewNavigating, self.wv)
        self.Bind(webview.EVT_WEBVIEW_LOADED, self.OnWebViewLoaded, self.wv)
        self.Bind(webview.EVT_WEBVIEW_TITLE_CHANGED, self.OnWebViewTitleChanged, self.wv)
Ejemplo n.º 3
0
    def __init__(self, parent, filter=None, show_root=False):
        style = wx.TR_DEFAULT_STYLE | wx.TR_EDIT_LABELS | wx.BORDER_NONE
        if not show_root:
            style |= wx.TR_HIDE_ROOT

        wx.TreeCtrl.__init__(self, parent, style=style)
        wx.FileDropTarget.__init__(self)

        self.SetDropTarget(self)
        self.SetDoubleBuffered(True)

        old_font = self.GetFont()
        self.font = wx.Font(old_font.PointSize, old_font.Family, old_font.Style, old_font.Weight, faceName=old_font.FaceName)
        self.SetFont(self.font)

        self.filter = filter or DirTreeFilter()
        self.cq = CoroutineQueue()
        self.cm = CoroutineManager()
        self.select_later_parent = None
        self.select_later_name = None
        self.select_later_time = 0
        self.expanding_all = False
        self.drop_item = None
        self.sig_update_tree = Signal(self)
        self.sig_update_tree.bind(self.UpdateFromFSMonitor)
        self.monitor = FSMonitor()
        self.monitor_thread = DirTreeMonitor(self, self.monitor)

        self.imglist = wx.ImageList(16, 16)
        self.imglist.Add(load_bitmap("icons/folder.png"))
        self.imglist.Add(load_bitmap("icons/folder_denied.png"))
        self.imglist.Add(load_bitmap("icons/file.png"))
        self.SetImageList(self.imglist)

        self.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.OnItemExpanding)
        self.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.OnItemCollapsed)
        self.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.OnItemRightClicked)
        self.Bind(wx.EVT_TREE_BEGIN_LABEL_EDIT, self.OnItemBeginLabelEdit)
        self.Bind(wx.EVT_TREE_END_LABEL_EDIT, self.OnItemEndLabelEdit)
        self.Bind(wx.EVT_TREE_BEGIN_DRAG, self.OnBeginDrag)
        self.Bind(wx.EVT_MENU, self.OnItemRename, id=ID_DIRTREE_RENAME)
        self.Bind(wx.EVT_MENU, self.OnItemDelete, id=ID_DIRTREE_DELETE)
        self.Bind(wx.EVT_MENU, self.OnNewFolder, id=ID_DIRTREE_NEW_FOLDER)
        self.Bind(wx.EVT_MENU, self.OnExpandAll, id=ID_DIRTREE_EXPAND_ALL)
        self.Bind(wx.EVT_MENU, self.OnCollapseAll, id=ID_DIRTREE_COLLAPSE_ALL)
Ejemplo n.º 4
0
    def __init__(self, parent, env):
        wx.Panel.__init__(self, parent, -1)
        self.env = env

        self.current = ""
        
        sizer = wx.BoxSizer(wx.VERTICAL)
        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
        self.wv = webview.WebView.New(self)
        self.Bind(webview.EVT_WEB_VIEW_NAVIGATING, self.OnWebViewNavigating, self.wv)
        self.Bind(webview.EVT_WEB_VIEW_LOADED, self.OnWebViewLoaded, self.wv)
        self.Bind(webview.EVT_WEB_VIEW_TITLE_CHANGED, self.OnWebViewTitleChanged, self.wv)
        
        btn = wx.Button(self, -1, "<--", style=wx.BU_EXACTFIT)
        self.Bind(wx.EVT_BUTTON, self.OnPrevPageButton, btn)
        btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)
        self.Bind(wx.EVT_UPDATE_UI, self.OnCheckCanGoBack, btn)

        btn = wx.Button(self, -1, "-->", style=wx.BU_EXACTFIT)
        self.Bind(wx.EVT_BUTTON, self.OnNextPageButton, btn)
        btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)
        self.Bind(wx.EVT_UPDATE_UI, self.OnCheckCanGoForward, btn)

        btn = wx.Button(self, -1, "Stop", style=wx.BU_EXACTFIT)
        self.Bind(wx.EVT_BUTTON, self.OnStopButton, btn)
        btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        btn = wx.Button(self, -1, "Refresh", style=wx.BU_EXACTFIT)
        self.Bind(wx.EVT_BUTTON, self.OnRefreshPageButton, btn)
        btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        self.location = wx.ComboBox(
            self, -1, "", style=wx.CB_DROPDOWN|wx.TE_PROCESS_ENTER)
        self.Bind(wx.EVT_COMBOBOX, self.OnLocationSelect, self.location)
        self.location.Bind(wx.EVT_TEXT_ENTER, self.OnLocationEnter)
        btnSizer.Add(self.location, 1, wx.EXPAND|wx.ALL, 2)

        sizer.Add(btnSizer, 0, wx.EXPAND)
        sizer.Add(self.wv, 1, wx.EXPAND)
        self.SetSizer(sizer)
        
        self.sig_title_changed = Signal()
        self.sig_status_changed = Signal()
Ejemplo n.º 5
0
class Preview(wx.Panel):
    def __init__(self, parent, env, url="", show_browser_ui=True):
        wx.Panel.__init__(self, parent)

        self.env = env
        self.show_browser_ui = show_browser_ui
        self.sig_title_changed = Signal()
        self.sig_status_changed = Signal()

        import wx.html2 as webview
        self.wv = webview.WebView.New(self, url=url)

        sizer = wx.BoxSizer(wx.VERTICAL)

        if show_browser_ui:
            btnSizer = wx.BoxSizer(wx.HORIZONTAL)

            btn = wx.BitmapButton(self, bitmap=resources.load_bitmap("icons/back.png"))
            self.Bind(wx.EVT_BUTTON, self.OnBack, btn)
            self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI_Back, btn)
            btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

            btn = wx.BitmapButton(self, bitmap=resources.load_bitmap("icons/forward.png"))
            self.Bind(wx.EVT_BUTTON, self.OnForward, btn)
            self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI_Forward, btn)
            btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

            btn = wx.BitmapButton(self, bitmap=resources.load_bitmap("icons/stop.png"))
            self.Bind(wx.EVT_BUTTON, self.OnStop, btn)
            self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI_Stop, btn)
            btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

            btn = wx.BitmapButton(self, bitmap=resources.load_bitmap("icons/refresh.png"))
            self.Bind(wx.EVT_BUTTON, self.OnRefresh, btn)
            self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI_Refresh, btn)
            btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

            self.location = wx.ComboBox(self, value=url, style=wx.CB_DROPDOWN|wx.TE_PROCESS_ENTER)
            self.Bind(wx.EVT_COMBOBOX, self.OnLocationSelect, self.location)
            self.location.Bind(wx.EVT_TEXT_ENTER, self.OnLocationEnter)
            btnSizer.Add(self.location, 1, wx.ALIGN_CENTRE_VERTICAL|wx.ALL, 2)

            sizer.Add(btnSizer, 0, wx.EXPAND)

        sizer.Add(self.wv, 1, wx.EXPAND)
        self.SetSizer(sizer)

        self.Bind(webview.EVT_WEBVIEW_NAVIGATING, self.OnWebViewNavigating, self.wv)
        self.Bind(webview.EVT_WEBVIEW_LOADED, self.OnWebViewLoaded, self.wv)
        self.Bind(webview.EVT_WEBVIEW_TITLE_CHANGED, self.OnWebViewTitleChanged, self.wv)

    @property
    def url(self):
        return self.wv.GetCurrentURL()

    @url.setter
    def url(self, url):
        self.wv.LoadURL(url)

    @property
    def path(self):
        url = self.url
        if url.startswith("file://"):
            if wx.Platform == "__WXMSW__":
                return url[len("file:///"):].replace("/", "\\")
            else:
                return url[len("file://"):]
        else:
            return ""

    @path.setter
    def path(self, path):
        oldpath = self.path
        if oldpath:
            self.env.remove_monitor_path(oldpath)
        self.env.add_monitor_path(path)
        self.wv.LoadURL("file://" + path)

    @property
    def modified(self):
        return False

    @property
    def title(self):
        return (self.wv.GetCurrentTitle()
                or self.path
                or self.url
                or ("Loading..." if self.wv.IsBusy() else "..."))

    @property
    def status_text(self):
        return self.wv.GetCurrentTitle()

    @property
    def status_text_path(self):
        return self.path or self.url or ""

    @property
    def status_text_syntax(self):
        return ""

    @coroutine
    def TryClose(self):
        yield True

    def SavePerspective(self):
        p = dict(view_type="preview")
        path = self.path
        if path:
            p["path"] = path
        else:
            p["url"] = self.url
        return p

    @coroutine
    def LoadPerspective(self, p):
        if "path" in p:
            self.path = p["path"]
        elif "url" in p:
            self.url = p["url"]
        self.wv.ClearHistory()
        yield

    @coroutine
    def OnModifiedExternally(self):
        self.wv.Reload()
        yield

    @coroutine
    def OnUnloadedExternally(self):
        yield

    def OnWebViewNavigating(self, evt):
        pass # to stop it navigating:   evt.Veto()

    def OnWebViewTitleChanged(self, evt):
        self.sig_title_changed.signal(self)
        self.sig_status_changed.signal(self)

    def OnWebViewLoaded(self, evt):
        if self.show_browser_ui:
            self.location.SetValue(self.path or self.url)
        self.sig_title_changed.signal(self)
        self.sig_status_changed.signal(self)

    def OnLocationSelect(self, evt):
        url = self.location.GetStringSelection()
        self.log.write("OnLocationSelect: %s\n" % url)
        self.wv.LoadURL(url)

    def OnLocationEnter(self, evt):
        url = self.location.GetValue()
        self.location.Append(url)
        self.wv.LoadURL(url)

    def OnOpenButton(self, evt):
        url = dialogs.get_text_input(self, "Open Location", "Enter a full URL or local path", self.url)
        if url:
            self.wv.LoadURL(url)

    def OnBack(self, evt):
        self.wv.GoBack()

    def OnForward(self, evt):
        self.wv.GoForward()

    def OnStop(self, evt):
        self.wv.Stop()

    def OnRefresh(self, evt):
        self.wv.Reload()

    def OnUpdateUI_Back(self, evt):
        evt.Enable(self.wv.CanGoBack())

    def OnUpdateUI_Forward(self, evt):
        evt.Enable(self.wv.CanGoForward())

    def OnUpdateUI_Stop(self, evt):
        evt.Enable(self.wv.IsBusy())

    def OnUpdateUI_Refresh(self, evt):
        evt.Enable(not self.wv.IsBusy())
Ejemplo n.º 6
0
class Editor(StyledTextCtrl, wx.FileDropTarget):
    def __init__(self, parent, env, path=""):
        StyledTextCtrl.__init__(self, parent, env)
        wx.FileDropTarget.__init__(self)
        self.SetDropTarget(self)

        self.path = path
        self.file_encoding = "utf-8"
        self.modified_externally = False
        self.static_title = None

        self.sig_title_changed = Signal(self)
        self.sig_status_changed = Signal(self)

        self.SetTabIndents(True)
        self.SetBackSpaceUnIndents(True)
        self.SetViewWhiteSpace(wx.stc.STC_WS_VISIBLEALWAYS)
        self.SetWhitespaceForeground(True, "#dddddd")
        self.SetEdgeMode(wx.stc.STC_EDGE_LINE)
        self.SetEdgeColumn(80)
        self.SetEdgeColour("#dddddd")

        self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
        self.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown)
        self.Bind(wx.stc.EVT_STC_SAVEPOINTLEFT, self.OnSavePointLeft)
        self.Bind(wx.stc.EVT_STC_SAVEPOINTREACHED, self.OnSavePointReached)
        self.Bind(wx.stc.EVT_STC_UPDATEUI, self.OnStcUpdateUI)

    @property
    def name(self):
        return os.path.basename(self.path)

    @property
    def modified(self):
        return self.GetModify()

    @property
    def title(self):
        if self.static_title is not None:
            return self.static_title
        path = os.path.basename(self.path) or "Untitled"
        return "* " + path if self.modified else path

    @property
    def status_text(self):
        return "Line %d, Column %d" % (
            self.GetCurrentLine() + 1, self.GetColumn(self.GetCurrentPos()))

    @property
    def status_text_path(self):
        return self.static_title or self.path or "Untitled"

    @property
    def status_text_syntax(self):
        return "Syntax: " + self.syntax.description

    @property
    def dialog_parent(self):
        return wx.GetTopLevelParent(self)

    def GetModify(self):
        return (not self.GetReadOnly()) and (
                self.modified_externally or super(Editor, self).GetModify())

    def SetModified(self):
        self.modified_externally = True
        self.sig_title_changed.signal(self)

    @coroutine
    def TryClose(self):
        if self.modified:
            result = dialogs.ask_save_changes(self.dialog_parent, self.path)
            if result == wx.ID_YES:
                try:
                    save_result = (yield self.Save())
                    if save_result:
                        self.env.remove_monitor_path(self.path)
                    yield save_result
                except Exception:
                    yield False
            else:
                yield result == wx.ID_NO
        else:
            if self.path:
                self.env.remove_monitor_path(self.path)
            yield True

    def SetStatic(self, title, text):
        self.static_title = title
        self.path = ""
        self.SetText(text)
        self.SetSavePoint()
        self.EmptyUndoBuffer()
        self.SetReadOnly(True)
        self.sig_title_changed.signal(self)
        self.sig_status_changed.signal(self)

    @coroutine
    def LoadFile(self, path):
        self.SetReadOnly(True)
        self.Disable()

        old_path = self.path
        self.path = path
        self.sig_title_changed.signal(self)

        try:
            text = (yield async_call(read_file, path, "r"))
            text, self.file_encoding = decode_text(text)
            text = clean_text(text)

            self.modified_externally = False
            self.SetReadOnly(False)
            self.SetSyntaxFromFilename(path)
            self.SetText(text)
            self.SetSavePoint()

            if old_path:
                self.env.remove_monitor_path(old_path)
            self.env.add_monitor_path(path)
        except:
            self.path = old_path
            self.sig_title_changed.signal(self)
            self.sig_status_changed.signal(self)
            raise
        finally:
            self.Enable()
            self.SetReadOnly(False)

    @coroutine
    def TryLoadFile(self, path):
        try:
            yield self.LoadFile(path)
            self.EmptyUndoBuffer()
            yield True
        except Exception as e:
            dialogs.error(self.dialog_parent, "Error opening file:\n\n%s" % e)
            yield False

    @coroutine
    def Reload(self):
        line_num = self.GetFirstVisibleLine()
        yield self.LoadFile(self.path)
        self.ScrollToLine(line_num)

    @coroutine
    def WriteFile(self, path):
        def do_write_file(path, text):
            mkpath(os.path.dirname(path))
            atomic_write_file(path, text)

        text, self.file_encoding = encode_text(self.GetText(), self.file_encoding)
        text = clean_text(text)
        with self.env.updating_path(path):
            yield async_call(do_write_file, path, text)
        self.modified_externally = False
        self.SetSavePoint()

    def SetPath(self, path):
        if self.path:
            self.env.remove_monitor_path(path)
        self.path = path
        self.static_title = None
        self.SetSyntaxFromFilename(self.path)
        self.env.add_monitor_path(self.path)
        self.env.add_recent_file(self.path)
        self.sig_title_changed.signal(self)
        self.sig_status_changed.signal(self)

    def HasOpenFile(self):
        return bool(self.path)

    @coroutine
    def SaveAsInSameTab(self):
        path = self.env.get_file_to_save(path=os.path.dirname(self.path))
        if path:
            path = os.path.realpath(path)
            try:
                yield self.WriteFile(path)
            except Exception as e:
                dialogs.error(self.dialog_parent, "Error saving file '%s'\n\n%s" % (path, e))
                raise
            else:
                self.SetPath(path)
                yield True
        yield False

    @coroutine
    def SaveAsInNewTab(self):
        path = self.env.get_file_to_save(path=os.path.dirname(self.path))
        if path:
            path = os.path.realpath(path)
            editor = self.env.new_editor(path)
            editor.SetText(self.GetText())
            try:
                yield editor.WriteFile(path)
            except Exception as e:
                dialogs.error(self.dialog_parent, "Error saving file '%s'\n\n%s" % (path, e))
                raise
            else:
                editor.SetPath(path)

    def SaveAs(self):
        if self.path:
            return self.SaveAsInNewTab()
        else:
            return self.SaveAsInSameTab()

    @coroutine
    def Save(self):
        if self.path:
            try:
                yield self.WriteFile(self.path)
                self.env.add_monitor_path(self.path)
                yield True
            except Exception as e:
                dialogs.error(self.dialog_parent, "Error saving file '%s'\n\n%s" % (self.path, e))
                raise
        else:
            yield (yield self.SaveAsInSameTab())

    def OnReturnKeyDown(self, evt):
        start, end = self.GetSelection()
        if start == end:
            indent = self.GetLineIndentation(self.GetCurrentLine())
            pos = self.GetCurrentPos()
            if self.GetUseTabs():
                indent //= self.GetTabWidth()
                self.InsertText(pos, "\n" + "\t" * indent)
            else:
                self.InsertText(pos, "\n" + " " * indent)
            self.GotoPos(pos + indent + 1)
        else:
            evt.Skip()

    def OnKeyDown(self, evt):
        key = evt.GetKeyCode()
        mod = evt.GetModifiers()
        if mod == wx.MOD_NONE:
            if key in (wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER):
                self.OnReturnKeyDown(evt)
            else:
                evt.Skip()
        else:
            evt.Skip()

    def OnRightDown(self, evt):
        start, end = self.GetSelection()
        if start == end:
            pos = self.PositionFromPoint(evt.GetPosition())
            self.SetSelection(pos, pos)
            self.SetCurrentPos(pos)
        evt.Skip()

    def OnSavePointLeft(self, evt):
        self.sig_title_changed.signal(self)

    def OnSavePointReached(self, evt):
        self.sig_title_changed.signal(self)

    def OnStcUpdateUI(self, evt):
        self.sig_status_changed.signal(self)
        evt.Skip()

    def OnDropFiles(self, x, y, filenames):
        for filename in filenames:
            self.env.open_file(filename)
        return True

    @coroutine
    def OnModifiedExternally(self):
        if dialogs.ask_reload(self.dialog_parent, os.path.basename(self.path)):
            yield self.Reload()
        else:
            self.SetModified()

    @coroutine
    def OnUnloadedExternally(self):
        if os.path.exists(self.path):
            if dialogs.ask_reload(self.dialog_parent, os.path.basename(self.path)):
                yield self.Reload()
            else:
                self.SetModified()
        else:
            if dialogs.ask_unload(self.dialog_parent, os.path.basename(self.path)):
                self.env.close_view(self)
            else:
                self.SetModified()

    def GetDyanmicEditMenuItems(self):
        items = []
        if self.path:
            items.extend([
                MenuItem(ID.COPY_FILE_PATH, "Copy File Path"),
                MenuItem(ID.OPEN_CONTAINING_FOLDER, "Open Containing Folder"),
                MenuItem(ID.OPEN_IN_WEB_VIEW, "Preview in Web View"),
                MenuSeparator,
            ])
        selected = self.GetSelectedFirstLine()
        if selected:
            selected = shorten_text(selected, 40)
            items.append(MenuItem(ID.WEB_SEARCH, "Web Search for %s" % repr(selected)[1:]))
        return items

    def CopyFilePath(self):
        if self.path:
            set_clipboard_text(self.path)

    def OpenContainingFolder(self):
        if self.path:
            self.env.shell_open(os.path.dirname(self.path))

    def OpenPreview(self):
        if self.path:
            self.env.open_preview(self.path)

    def WebSearch(self):
        selected = self.GetSelectedFirstLine()
        if selected:
            url = "https://www.google.com/search?" + urlencode([("q", selected)])
            self.env.open_web_view(url)

    def GetSelectionWriter(self):
        if not self.GetReadOnly():
            return EditorSelectionWriter(self)

    def GetAllTextWriter(self):
        if not self.GetReadOnly():
            return EditorAllTextWriter(self)

    def SavePerspective(self):
        p = {
            "line"      : self.GetFirstVisibleLine(),
            "selection" : self.GetSelection(),
            "view_type" : "editor",
        }
        if self.path:
            p["path"] = self.path
        else:
            p["text"] = self.GetText()
            if self.static_title is not None:
                p["static_title"] = self.static_title
        return p

    @coroutine
    def LoadPerspective(self, p):
        if "text" in p:
            self.modified_externally = False
            static_title = p.get("static_title")
            if static_title is None:
                self.SetSavePoint()
                self.SetText(p["text"])
            else:
                self.SetStatic(static_title, p["text"])

        elif "path" in p:
            yield self.LoadFile(p["path"])
            self.EmptyUndoBuffer()

        self.ScrollToLine(p.get("line", 0))
        self.SetSelection(*p.get("selection", (0, 0)))
Ejemplo n.º 7
0
class Preview(wx.Panel):
    def __init__(self, parent, env):
        wx.Panel.__init__(self, parent, -1)
        self.env = env

        self.current = ""
        
        sizer = wx.BoxSizer(wx.VERTICAL)
        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
        self.wv = webview.WebView.New(self)
        self.Bind(webview.EVT_WEB_VIEW_NAVIGATING, self.OnWebViewNavigating, self.wv)
        self.Bind(webview.EVT_WEB_VIEW_LOADED, self.OnWebViewLoaded, self.wv)
        self.Bind(webview.EVT_WEB_VIEW_TITLE_CHANGED, self.OnWebViewTitleChanged, self.wv)
        
        btn = wx.Button(self, -1, "<--", style=wx.BU_EXACTFIT)
        self.Bind(wx.EVT_BUTTON, self.OnPrevPageButton, btn)
        btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)
        self.Bind(wx.EVT_UPDATE_UI, self.OnCheckCanGoBack, btn)

        btn = wx.Button(self, -1, "-->", style=wx.BU_EXACTFIT)
        self.Bind(wx.EVT_BUTTON, self.OnNextPageButton, btn)
        btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)
        self.Bind(wx.EVT_UPDATE_UI, self.OnCheckCanGoForward, btn)

        btn = wx.Button(self, -1, "Stop", style=wx.BU_EXACTFIT)
        self.Bind(wx.EVT_BUTTON, self.OnStopButton, btn)
        btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        btn = wx.Button(self, -1, "Refresh", style=wx.BU_EXACTFIT)
        self.Bind(wx.EVT_BUTTON, self.OnRefreshPageButton, btn)
        btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)

        self.location = wx.ComboBox(
            self, -1, "", style=wx.CB_DROPDOWN|wx.TE_PROCESS_ENTER)
        self.Bind(wx.EVT_COMBOBOX, self.OnLocationSelect, self.location)
        self.location.Bind(wx.EVT_TEXT_ENTER, self.OnLocationEnter)
        btnSizer.Add(self.location, 1, wx.EXPAND|wx.ALL, 2)

        sizer.Add(btnSizer, 0, wx.EXPAND)
        sizer.Add(self.wv, 1, wx.EXPAND)
        self.SetSizer(sizer)
        
        self.sig_title_changed = Signal()
        self.sig_status_changed = Signal()
        
    @coroutine
    def TryClose(self):
        yield True

    def SavePerspective(self):
        return dict(
            view_type="preview",
            path = self.path,
        )
        
    @coroutine
    def LoadPerspective(self, p):
        path = p.get("path", "")
        os.stat(path)  # check it exists
        self.path = path
        yield        
        
    @property
    def path(self):
        return self.current and self.current[len('file://'):]
        
    @property 
    def modified(self):
        return False
    
    @path.setter
    def path(self, p):
        oldpath = self.path
        if oldpath:
            self.env.remove_monitor_path(oldpath)
        self.env.add_monitor_path(p)
        self.wv.LoadURL('file://' + p)
        
    @coroutine
    def OnModifiedExternally(self):
        self.wv.Reload()
        yield
        
    @coroutine
    def OnUnloadedExternally(self):
        yield
        
    @property
    def title(self):
        return self.wv.GetCurrentTitle()

    @property
    def status_text(self):
        return self.title
        
    @property
    def status_text_path(self):
        return self.title

    def OnWebViewNavigating(self, evt):
        pass # to stop it navigating:   evt.Veto()
        
    def OnWebViewTitleChanged(self, evt):
        self.sig_title_changed.signal(self)

    def OnWebViewLoaded(self, evt):
        self.current = evt.GetURL()
        self.location.SetValue(self.current)
        self.sig_title_changed.signal(self)
        
    def OnLocationSelect(self, evt):
        url = self.location.GetStringSelection()
        self.log.write('OnLocationSelect: %s\n' % url)
        self.wv.LoadURL(url)

    def OnLocationEnter(self, evt):
        url = self.location.GetValue()
        self.location.Append(url)
        self.wv.LoadURL(url)

    def OnOpenButton(self, event):
        dlg = wx.TextEntryDialog(self, "Open Location",
                                "Enter a full URL or local path",
                                self.current, wx.OK|wx.CANCEL)
        dlg.CentreOnParent()

        if dlg.ShowModal() == wx.ID_OK:
            self.current = dlg.GetValue()
            self.wv.LoadURL(self.current)

        dlg.Destroy()

    def OnPrevPageButton(self, event):
        self.wv.GoBack()

    def OnNextPageButton(self, event):
        self.wv.GoForward()

    def OnCheckCanGoBack(self, event):
        event.Enable(self.wv.CanGoBack())
        
    def OnCheckCanGoForward(self, event):
        event.Enable(self.wv.CanGoForward())

    def OnStopButton(self, evt):
        self.wv.Stop()

    def OnRefreshPageButton(self, evt):
        self.wv.Reload()
Ejemplo n.º 8
0
class DirTreeCtrl(wx.TreeCtrl, wx.FileDropTarget):
    def __init__(self, parent, filter=None, show_root=False):
        style = wx.TR_DEFAULT_STYLE | wx.TR_EDIT_LABELS | wx.BORDER_NONE
        if not show_root:
            style |= wx.TR_HIDE_ROOT

        wx.TreeCtrl.__init__(self, parent, style=style)
        wx.FileDropTarget.__init__(self)

        self.SetDropTarget(self)
        self.SetDoubleBuffered(True)

        old_font = self.GetFont()
        self.font = wx.Font(old_font.PointSize, old_font.Family, old_font.Style, old_font.Weight, faceName=old_font.FaceName)
        self.SetFont(self.font)

        self.filter = filter or DirTreeFilter()
        self.cq = CoroutineQueue()
        self.cm = CoroutineManager()
        self.select_later_parent = None
        self.select_later_name = None
        self.select_later_time = 0
        self.expanding_all = False
        self.drop_item = None
        self.sig_update_tree = Signal(self)
        self.sig_update_tree.bind(self.UpdateFromFSMonitor)
        self.monitor = FSMonitor()
        self.monitor_thread = DirTreeMonitor(self, self.monitor)

        self.imglist = wx.ImageList(16, 16)
        self.imglist.Add(load_bitmap("icons/folder.png"))
        self.imglist.Add(load_bitmap("icons/folder_denied.png"))
        self.imglist.Add(load_bitmap("icons/file.png"))
        self.SetImageList(self.imglist)

        self.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.OnItemExpanding)
        self.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.OnItemCollapsed)
        self.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.OnItemRightClicked)
        self.Bind(wx.EVT_TREE_BEGIN_LABEL_EDIT, self.OnItemBeginLabelEdit)
        self.Bind(wx.EVT_TREE_END_LABEL_EDIT, self.OnItemEndLabelEdit)
        self.Bind(wx.EVT_TREE_BEGIN_DRAG, self.OnBeginDrag)
        self.Bind(wx.EVT_MENU, self.OnItemRename, id=ID_DIRTREE_RENAME)
        self.Bind(wx.EVT_MENU, self.OnItemDelete, id=ID_DIRTREE_DELETE)
        self.Bind(wx.EVT_MENU, self.OnNewFolder, id=ID_DIRTREE_NEW_FOLDER)
        self.Bind(wx.EVT_MENU, self.OnExpandAll, id=ID_DIRTREE_EXPAND_ALL)
        self.Bind(wx.EVT_MENU, self.OnCollapseAll, id=ID_DIRTREE_COLLAPSE_ALL)

    def Destroy(self):
        self.cm.cancel()
        self.monitor.close()
        wx.TreeCtrl.Destroy(self)

    def SelectLater(self, parent, name, timeout=1):
        self.select_later_parent = parent
        self.select_later_name = name
        self.select_later_time = time.time() + timeout

    def TrySelectLater(self, item, name):
        if name == self.select_later_name \
        and self.GetItemParent(item) == self.select_later_parent:
            if time.time() < self.select_later_time:
                self.SelectItem(item)
            self.select_later_name = None
            self.select_later_parent = None
            self.select_later_time = 0

    @managed("cm")
    @coroutine
    def UpdateFromFSMonitor(self):
        for evt in self.monitor_thread.get_events():
            if evt.action in add_events:
                item = (yield evt.user.add(evt.name, self, self.monitor, self.filter))
                if item:
                    self.TrySelectLater(item, evt.name)
            elif evt.action in remove_events:
                evt.user.remove(evt.name, self, self.monitor)

    def OnItemExpanding(self, evt):
        node = self.GetEventNode(evt)
        if node.type == 'd' and not node.populated:
            self.ExpandNode(node)

    def OnItemCollapsed(self, evt):
        node = self.GetEventNode(evt)
        if node.type == 'd':
            self.CollapseNode(node)

    def GetNodeMenu(self, node):
        return context_menu

    def OnItemRightClicked(self, evt):
        self.SelectItem(evt.GetItem())
        node = self.GetEventNode(evt)
        menu = self.GetNodeMenu(node)
        if menu:
            self.PopupMenu(menu.Create())

    def OnItemBeginLabelEdit(self, evt):
        node = self.GetEventNode(evt)
        if not (node and node.path):
            evt.Veto()

    def OnItemEndLabelEdit(self, evt):
        if not evt.IsEditCancelled():
            evt.Veto()
            node = self.GetEventNode(evt)
            self.RenameNode(node, evt.GetLabel())

    def OnBeginDrag(self, evt):
        node = self.GetEventNode(evt)
        if node:
            data = wx.FileDataObject()
            data.AddFile(node.path)
            dropsrc = wx.DropSource(self)
            dropsrc.SetData(data)
            dropsrc.DoDragDrop()

    def OnDragOver(self, x, y, default):
        self.OnLeave()
        item, flags = self.HitTest((x, y))
        if item and (flags & wx.TREE_HITTEST_ONITEMLABEL):
            self.drop_item = item
            self.SetItemDropHighlight(item, True)
            return wx.DragCopy
        return wx.DragNone

    def OnLeave(self):
        if self.drop_item:
            self.SetItemDropHighlight(self.drop_item, False)
            self.drop_item = None

    def OnDropFiles(self, x, y, filenames):
        self.OnLeave()
        item, flags = self.HitTest((x, y))
        if item and (flags & wx.TREE_HITTEST_ONITEMLABEL):            
            while item:
                node = self.GetPyData(item)
                if node.type == 'd':
                    for filename in filenames:
                        filename = os.path.realpath(filename)
                        if filename != node.path:
                            fileutil.shell_move_or_copy(filename, node.path, parent=self)
                    break
                item = self.GetItemParent(item)

    def OnItemRename(self, evt):
        node = self.GetSelectedNode()
        if node and node.path:
            self.EditLabel(node.item)

    def OnItemDelete(self, evt):
        node = self.GetSelectedNode()
        if node:
            next_item = self.GetNextSibling(node.item)
            fileutil.shell_remove(node.path, parent=self)

    def OnNewFolder(self, evt):
        node = self.GetSelectedNode()
        if node:
            if node.type != 'd':
                node = self.GetPyData(self.GetItemParent(node.item))
            name = dialogs.get_text_input(self,
                "New Folder",
                "Please enter new folder name:")
            if name:
                self.NewFolder(node, name)

    @managed("cm")
    @coroutine
    def OnExpandAll(self, evt):
        del evt
        if self.expanding_all:
            return
        if not dialogs.yes_no(self,
                "Expanding all folders may take a long time. Continue?",
                icon_style=wx.ICON_WARNING):
            return
        self.expanding_all = True
        try:
            for item in iter_tree_breadth_first(self, self.GetRootItem()):
                if not self.expanding_all:
                    return
                node = self.GetPyData(item)
                if node.type == 'd':
                    if not node.populated:
                        try:
                            yield self.ExpandNode(node)
                        except Exception:
                            pass
                    else:
                        self.Expand(item)
        finally:
            self.expanding_all = False

    def OnCollapseAll(self, evt):
        self.expanding_all = False
        self.CollapseAll()

    def SetItemNode(self, item, node):
        self.SetPyData(item, node)
        node.item = item
        return node

    def GetEventNode(self, evt):
        item = evt.GetItem()
        if item.IsOk():
            return self.GetPyData(item)

    def GetSelectedNode(self):
        item = self.GetSelection()
        if item.IsOk():
            return self.GetPyData(item)

    def GetSelectedPath(self):
        node = self.GetSelectedNode()
        return node.path if node else ""

    def IsExpanded(self, item):
        return self.GetRootItem() == item or wx.TreeCtrl.IsExpanded(self, item)

    def Expand(self, item):
        if self.GetRootItem() != item:
            wx.TreeCtrl.Expand(self, item)

    @managed("cm")
    @coroutine
    def PopulateNode(self, node):
        if not node.populated:
            f = node.expand(self, self.monitor, self.filter)
            if isinstance(f, Future):
                yield f

    @managed("cm")
    @coroutine
    def ExpandNode(self, node):
        if not node.populated:
            try:
                yield self.PopulateNode(node)
            except OSError:
                return
        if node.populated:
            self.Expand(node.item)

    def CollapseNode(self, node):
        node.collapse(self, self.monitor)

    @managed("cm")
    @coroutine
    def RenameNode(self, node, name):
        newpath = os.path.join(os.path.dirname(node.path), name)
        if newpath != node.path:
            try:
                if (yield async_call(os.path.exists, newpath)):
                    if not dialogs.ask_overwrite(self, newpath):
                        return
                yield async_call(fileutil.rename, node.path, newpath)
                self.SelectLater(self.GetItemParent(node.item), name)
            except OSError as e:
                dialogs.error(self, str(e))

    @managed("cm")
    @coroutine
    def NewFolder(self, node, name):
        path = os.path.join(node.path, name)
        try:
            yield async_call(os.mkdir, path)
            if self.IsExpanded(node.item):
                self.SelectLater(node.item, name)
        except OSError as e:
            dialogs.error(self, str(e))

    @managed("cm")
    @queued_coroutine("cq")
    def _InitialExpand(self, rootnode, toplevel):
        yield self.ExpandNode(rootnode)
        if isinstance(toplevel[0], SimpleNode):
            yield self.ExpandNode(toplevel[0])

    def SetTopLevel(self, toplevel=None):
        self.cm.cancel()
        self.cq.cancel()
        self.monitor_thread.clear()
        self.DeleteAllItems()
        toplevel = toplevel or make_top_level()
        if len(toplevel) == 1:
            rootitem = self.AddRoot(toplevel[0].label)
            rootnode = toplevel[0]
        else:
            rootitem = self.AddRoot("")
            rootnode = SimpleNode("", toplevel)
        self.SetItemNode(rootitem, rootnode)
        return self._InitialExpand(rootnode, toplevel)

    def _FindExpandedPaths(self, item, path, expanded):
        if self.IsExpanded(item):
            node = self.GetPyData(item)
            if node.type == 'd':
                subpath = os.path.join(path, os.path.basename(node.path)) if path else node.path
                len_expanded = len(expanded)
                for child_item in iter_tree_children(self, item):
                    self._FindExpandedPaths(child_item, subpath, expanded)
                if len(expanded) == len_expanded:
                    expanded.append(subpath)
        return expanded

    def FindExpandedPaths(self):
        expanded = []
        for item in iter_tree_children(self, self.GetRootItem()):
            self._FindExpandedPaths(item, "", expanded)
        return expanded

    @managed("cm")
    @coroutine
    def _ExpandPaths(self, item, paths):
        expanded = [path[0] for path in paths if path]
        sub_paths = [path[1:] for path in paths if len(path) > 1]
        yield self.ExpandNode(self.GetPyData(item))
        for child_item in iter_tree_children(self, item):
            node = self.GetPyData(child_item)
            name = os.path.basename(node.path) or node.path.strip(os.path.sep)
            if name in expanded:
                yield self._ExpandPaths(child_item, sub_paths)

    def ExpandPaths(self, paths):
        rootpath = self.GetPyData(self.GetRootItem()).path
        paths = [split_path(path, rootpath) for path in paths]
        return self._ExpandPaths(self.GetRootItem(), paths)

    def ExpandPath(self, path):
        return self.ExpandPaths([path])

    def _SelectExpandedPath(self, item, path):
        node = self.GetPyData(item)
        if node.path == path:
            self.SelectItem(node.item)
        elif node.type == 'd':
            for child_item in iter_tree_children(self, item):
                self._SelectExpandedPath(child_item, path)

    @managed("cm")
    @coroutine
    def _SelectPath(self, path):
        yield self.ExpandPath(os.path.dirname(path))
        self._SelectExpandedPath(self.GetRootItem(), path)

    @managed("cm")
    @coroutine
    def _SelectExpandPath(self, path):
        yield self.ExpandPath(path)
        self._SelectExpandedPath(self.GetRootItem(), path)

    @managed("cm")
    @queued_coroutine("cq")
    def SelectPath(self, path):
        yield self._SelectPath(os.path.normpath(path))

    @managed("cm")
    @queued_coroutine("cq")
    def SelectExpandPath(self, path):
        yield self._SelectExpandPath(os.path.normpath(path))

    def SavePerspective(self):
        p = {}
        expanded = self.FindExpandedPaths()
        if expanded:
            p["expanded"] = expanded
        selected = self.GetSelectedPath()
        if selected:
            p["selected"] = selected
        return p

    @managed("cm")
    @queued_coroutine("cq")
    def LoadPerspective(self, p):
        expanded = p.get("expanded", ())
        if expanded:
            yield self.ExpandPaths(expanded)
        if "selected" in p:
            yield self._SelectPath(p["selected"])