瀏覽代碼

mv legacy code to branch with-legacy.

oldj 8 年之前
父節點
當前提交
272f419f02
共有 100 個文件被更改,包括 0 次插入10193 次删除
  1. 0 646
      legacy/v1/SwitchHosts.py
  2. 0 754
      legacy/v1/libs/ToasterBox.py
  3. 0 0
      legacy/v1/libs/__init__.py
  4. 0 137
      legacy/v1/libs/cls_Hosts.py
  5. 0 230
      legacy/v1/libs/common_operations.py
  6. 0 74
      legacy/v1/libs/highLight.py
  7. 0 21
      legacy/v1/libs/icons.py
  8. 0 9
      legacy/v1/libs/nix_notify.py
  9. 0 330
      legacy/v1/libs/ui.py
  10. 0 110
      legacy/v1/xrc/main.xrc
  11. 0 27
      legacy/v1/xrc/option_frame.xrc
  12. 0 122
      legacy/v2/README.md
  13. 二進制
      legacy/v2/screenshots/1.png
  14. 二進制
      legacy/v2/screenshots/2.png
  15. 二進制
      legacy/v2/screenshots/3.png
  16. 二進制
      legacy/v2/screenshots/4.png
  17. 二進制
      legacy/v2/screenshots/5.png
  18. 二進制
      legacy/v2/screenshots/6.png
  19. 二進制
      legacy/v2/screenshots/7.png
  20. 0 129
      legacy/v2/src/SwitchHosts.py
  21. 二進制
      legacy/v2/src/img/logo.icns
  22. 二進制
      legacy/v2/src/img/logo.ico
  23. 二進制
      legacy/v2/src/img/logo.png
  24. 0 53
      legacy/v2/src/libs/BackThreads.py
  25. 0 271
      legacy/v2/src/libs/Hosts.py
  26. 0 112
      legacy/v2/src/libs/HostsCtrl.py
  27. 0 1262
      legacy/v2/src/libs/MainFrame.py
  28. 0 123
      legacy/v2/src/libs/TaskbarIcon.py
  29. 0 754
      legacy/v2/src/libs/ToasterBox.py
  30. 0 8
      legacy/v2/src/libs/VERSION.py
  31. 0 6
      legacy/v2/src/libs/__init__.py
  32. 0 214
      legacy/v2/src/libs/common_operations.py
  33. 0 21
      legacy/v2/src/libs/icons.py
  34. 0 18
      legacy/v2/src/libs/lang.py
  35. 0 482
      legacy/v2/src/libs/ui.py
  36. 0 34
      legacy/v2/src/setup.py
  37. 二進制
      legacy/v2/ui/img/accept.png
  38. 二進制
      legacy/v2/ui/img/add.png
  39. 二進制
      legacy/v2/ui/img/asterisk_yellow.png
  40. 二進制
      legacy/v2/ui/img/delete.png
  41. 二進制
      legacy/v2/ui/img/disk.png
  42. 二進制
      legacy/v2/ui/img/door.png
  43. 二進制
      legacy/v2/ui/img/icon_0.ico
  44. 二進制
      legacy/v2/ui/img/icon_0.png
  45. 二進制
      legacy/v2/ui/img/icon_1.png
  46. 二進制
      legacy/v2/ui/img/icon_2.png
  47. 二進制
      legacy/v2/ui/img/icon_3.png
  48. 二進制
      legacy/v2/ui/img/icon_4.png
  49. 二進制
      legacy/v2/ui/img/icon_5.png
  50. 二進制
      legacy/v2/ui/img/icon_6.png
  51. 0 19
      legacy/v2/ui/img/mkicon.py
  52. 0 23
      legacy/v2/ui/img/mkicon2.py
  53. 二進制
      legacy/v2/ui/img/pencil.png
  54. 0 848
      legacy/v2/ui/main.fbp
  55. 0 13
      legacy/v3.0/app/config.js
  56. 0 39
      legacy/v3.0/app/css/iconfont/iconfont.css
  57. 二進制
      legacy/v3.0/app/css/iconfont/iconfont.eot
  58. 0 111
      legacy/v3.0/app/css/iconfont/iconfont.svg
  59. 二進制
      legacy/v3.0/app/css/iconfont/iconfont.ttf
  60. 二進制
      legacy/v3.0/app/css/iconfont/iconfont.woff
  61. 0 240
      legacy/v3.0/app/css/style.css
  62. 0 0
      legacy/v3.0/app/css/style.css.map
  63. 0 266
      legacy/v3.0/app/css/style.styl
  64. 0 32
      legacy/v3.0/app/gulpfile.js
  65. 二進制
      legacy/v3.0/app/images/app.icns
  66. 二進制
      legacy/v3.0/app/images/logo_512.png
  67. 二進制
      legacy/v3.0/app/images/t.png
  68. 0 104
      legacy/v3.0/app/index.html
  69. 0 170
      legacy/v3.0/app/js/cf.js
  70. 0 78
      legacy/v3.0/app/js/chk.js
  71. 0 53
      legacy/v3.0/app/js/cm_hl.js
  72. 0 101
      legacy/v3.0/app/js/dnd.js
  73. 0 58
      legacy/v3.0/app/js/lang.js
  74. 0 199
      legacy/v3.0/app/js/menu.js
  75. 0 323
      legacy/v3.0/app/js/sh.js
  76. 0 29
      legacy/v3.0/app/js/tray.js
  77. 0 78
      legacy/v3.0/app/main.js
  78. 0 21
      legacy/v3.0/app/package.json
  79. 0 2
      legacy/v3.1_macgap/app/SH3/.gitignore
  80. 0 17
      legacy/v3.1_macgap/app/SH3/MacGap/AppDelegate.h
  81. 0 41
      legacy/v3.1_macgap/app/SH3/MacGap/AppDelegate.m
  82. 0 213
      legacy/v3.1_macgap/app/SH3/MacGap/Base.lproj/MainMenu.xib
  83. 0 38
      legacy/v3.1_macgap/app/SH3/MacGap/Base.lproj/MainWindow.xib
  84. 0 19
      legacy/v3.1_macgap/app/SH3/MacGap/Categories/JSON.h
  85. 0 66
      legacy/v3.1_macgap/app/SH3/MacGap/Categories/JSON.m
  86. 0 27
      legacy/v3.1_macgap/app/SH3/MacGap/Categories/NSData+Base64.h
  87. 0 276
      legacy/v3.1_macgap/app/SH3/MacGap/Categories/NSData+Base64.m
  88. 0 42
      legacy/v3.1_macgap/app/SH3/MacGap/Classes/Commands/App.h
  89. 0 185
      legacy/v3.1_macgap/app/SH3/MacGap/Classes/Commands/App.m
  90. 0 17
      legacy/v3.1_macgap/app/SH3/MacGap/Classes/Commands/Clipboard.h
  91. 0 30
      legacy/v3.1_macgap/app/SH3/MacGap/Classes/Commands/Clipboard.m
  92. 0 27
      legacy/v3.1_macgap/app/SH3/MacGap/Classes/Commands/Command.h
  93. 0 58
      legacy/v3.1_macgap/app/SH3/MacGap/Classes/Commands/Command.m
  94. 0 23
      legacy/v3.1_macgap/app/SH3/MacGap/Classes/Commands/Defaults.h
  95. 0 150
      legacy/v3.1_macgap/app/SH3/MacGap/Classes/Commands/Defaults.m
  96. 0 22
      legacy/v3.1_macgap/app/SH3/MacGap/Classes/Commands/Dialog.h
  97. 0 102
      legacy/v3.1_macgap/app/SH3/MacGap/Classes/Commands/Dialog.m
  98. 0 24
      legacy/v3.1_macgap/app/SH3/MacGap/Classes/Commands/Dock.h
  99. 0 38
      legacy/v3.1_macgap/app/SH3/MacGap/Classes/Commands/Dock.m
  100. 0 24
      legacy/v3.1_macgap/app/SH3/MacGap/Classes/Commands/Event.h

+ 0 - 646
legacy/v1/SwitchHosts.py

@@ -1,646 +0,0 @@
-# -*- coding: utf-8 -*-
-
-u"""
-本程序用于快速切换 hosts 文件
-
-@author: oldj
-@blog: http://oldj.net
-@email: [email protected]
-
-"""
-
-import os
-import sys
-import glob
-import wx
-import libs.common_operations as co
-import libs.ui as ui
-from libs.cls_Hosts import Hosts, DEFAULT_HOSTS_FN
-
-VERSION = "0.2.0.1763"
-SELECTED_FLAG = u"√"
-
-class TaskBarIcon(wx.TaskBarIcon):
-    ID_About = wx.NewId()
-    ID_Exit = wx.NewId()
-    ID_MainFrame = wx.NewId()
-
-    def __init__(self, frame):
-        wx.TaskBarIcon.__init__(self)
-        #        super(wx.TaskBarIcon, self).__init__()
-        self.frame = frame
-        self.SetIcon(co.GetMondrianIcon(), "SwitchHosts! %s" % VERSION)
-        self.Bind(wx.EVT_TASKBAR_LEFT_DCLICK, self.OnTaskBarLeftDClick)
-        self.Bind(wx.EVT_MENU, self.frame.OnAbout, id=self.ID_About)
-        self.Bind(wx.EVT_MENU, self.OnExit, id=self.ID_Exit)
-        self.Bind(wx.EVT_MENU, self.OnMainFrame, id=self.ID_MainFrame)
-
-        self.current_hosts = None
-
-        self.font_bold = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
-        self.font_bold.SetWeight(wx.BOLD)
-
-
-    def OnTaskBarLeftDClick(self, event):
-        if self.frame.IsIconized():
-            self.frame.Iconize(False)
-        if not self.frame.IsShown():
-            self.frame.Show(True)
-        self.frame.Raise()
-
-
-    def OnExit(self, event):
-        self.frame.Destroy()
-        self.Destroy()
-        sys.exit()
-
-
-    def OnMainFrame(self, event):
-        u"""显示主面板"""
-        if not self.frame.IsShown():
-            self.frame.Show(True)
-        self.frame.Raise()
-
-    # override
-    def CreatePopupMenu(self):
-        self.hosts = {}
-
-        hosts_list = listLocalHosts()
-        menu = wx.Menu()
-        menu.Append(self.ID_MainFrame, u"SwitchHosts!")
-        menu.AppendSeparator()
-
-        for fn in hosts_list:
-            oh = self.frame.getOHostsFromFn(fn)
-            if oh:
-                self.addHosts(menu, oh)
-
-        menu.AppendSeparator()
-        menu.Append(self.ID_About, "About")
-        menu.Append(self.ID_Exit, "Exit")
-        return menu
-
-
-    def addHosts(self, menu, ohost):
-        u"""在菜单项中添加一个 hosts"""
-
-        title = ohost.getTitle()
-
-        item_id = wx.NewId()
-        mitem = wx.MenuItem(menu, item_id, title, kind=wx.ITEM_RADIO)
-        mitem.SetBitmap(co.GetMondrianBitmap(ohost.icon_idx))
-        menu.AppendItem(mitem)
-
-        menu.Check(item_id, self.current_hosts == ohost.path)
-        if self.current_hosts == ohost.path:
-            mitem.SetFont(self.font_bold)
-        self.hosts[item_id] = title
-
-        self.Bind(wx.EVT_MENU, self.switchHost, id=item_id)
-
-
-    def switchHost(self, event):
-        hosts_id = event.GetId()
-        title = self.hosts[hosts_id]
-
-        oh = self.frame.getOHostsFromTitle(title)
-        if oh:
-            co.switchHost(self, oh.path)
-            self.frame.updateListCtrl()
-
-
-class Frame(ui.Frame):
-
-    ID_RENAME = wx.NewId()
-
-    def __init__(
-        self, parent=None, id=wx.ID_ANY, title="SwitchHosts! %s" % VERSION, pos=wx.DefaultPosition,
-        size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE,
-        sys_hosts_title=None
-    ):
-        ui.Frame.__init__(self, parent, id, title, pos, size, style, cls_TaskBarIcon=TaskBarIcon)
-
-        self.Bind(wx.EVT_CLOSE, self.OnClose)
-        self.init2(sys_hosts_title)
-
-
-    def init2(self, sys_hosts_title):
-
-        self.Bind(wx.EVT_MENU, self.newHosts, id=wx.ID_NEW)
-        self.Bind(wx.EVT_MENU, self.OnExit, id=wx.ID_EXIT)
-        self.Bind(wx.EVT_MENU, self.OnAbout, id=wx.ID_ABOUT)
-        self.Bind(wx.EVT_BUTTON, self.OnHide, id=wx.ID_CLOSE)
-        self.Bind(wx.EVT_BUTTON, self.applyHost, id=wx.ID_APPLY)
-        self.Bind(wx.EVT_TEXT, self.hostsContentChange, id=self.ID_HOSTS_TEXT)
-
-        self.Bind(wx.EVT_BUTTON, self.newHosts, id=wx.ID_ADD)
-        self.Bind(wx.EVT_BUTTON, self.deleteHosts, id=wx.ID_DELETE)
-
-        hosts_cols = (
-            (u"hosts", 130),
-            (u"", 20),
-            )
-        for col, (txt, width) in enumerate(hosts_cols):
-            self.m_list.InsertColumn(col, txt)
-            self.m_list.SetColumnWidth(col, width)
-        self.current_selected_hosts_index = -1
-        self.current_selected_hosts_fn = None
-        self.current_use_hosts_index = -1
-        self.current_max_hosts_index = -1
-        self.latest_stable_version = None
-
-        self.updateHostsList(sys_hosts_title)
-
-        self.hosts_item_menu = wx.Menu()
-        self.hosts_item_menu.Append(wx.ID_APPLY, u"切换到当前hosts")
-#        self.hosts_item_menu.Append(wx.ID_EDIT, u"编辑")
-        self.hosts_item_menu.Append(self.ID_RENAME, u"重命名")
-        self.hosts_item_menu.AppendMenu(-1, u"图标", self.mkSubIconMenu())
-
-        self.hosts_item_menu.AppendSeparator()
-        self.hosts_item_menu.Append(wx.ID_DELETE, u"删除")
-
-        self.m_btn_apply.Disable()
-
-        co.checkLatestStableVersion(self)
-
-        self.Bind(wx.EVT_MENU, self.menuApplyHost, id=wx.ID_APPLY)
-        self.Bind(wx.EVT_MENU, self.deleteHosts, id=wx.ID_DELETE)
-        self.Bind(wx.EVT_MENU, self.renameHosts, id=self.ID_RENAME)
-
-        self.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.OnHostsItemRClick, self.m_tree)
-        self.Bind(wx.EVT_TREE_ITEM_MENU, self.OnHostsItemBeSelected, self.m_tree) # todo selected 方法?
-        self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.applyHost, self.m_tree)
-
-
-    def setLatestStableVersion(self, version):
-
-        self.latest_stable_version = version
-#        print(version)
-
-
-    def mkSubIconMenu(self):
-        u"""生成图标子菜单"""
-
-        menu = wx.Menu()
-
-        def _f(i):
-            return lambda e: self.setHostIcon(e, i)
-
-        icons_length = len(co.ICONS)
-        for i in range(icons_length):
-            item_id = wx.NewId()
-            mitem = wx.MenuItem(menu, item_id, u"图标#%d" % (i + 1))
-            mitem.SetBitmap(co.GetMondrianBitmap(i))
-            menu.AppendItem(mitem)
-
-            self.Bind(wx.EVT_MENU, _f(i), id=item_id)
-
-        return menu
-
-
-    def setHostIcon(self, event=None, i=0):
-
-        index = self.current_selected_hosts_index
-        ohosts = self.hosts_objects[index]
-        ohosts.setIcon(i)
-        self.m_list.SetItemImage(index, ohosts.icon_idx, ohosts.icon_idx)
-
-        ch = self.taskbar_icon.current_hosts
-        if ch == ohosts.path or (not ch and DEFAULT_HOSTS_FN == ohosts.fn):
-            # 如果当前设置图片的 hosts 正是正在使用的 hosts,则
-            
-            self.SetIcon(co.GetMondrianIcon(i))
-            self.taskbar_icon.SetIcon(co.GetMondrianIcon(i), u"当前 hosts 方案:%s" % ohosts.getTitle())
-
-
-    def updateHostsList(self, selected_title=None):
-        u"""更新 hosts 列表"""
-
-        hosts_list = listLocalHosts()
-#        hosts_list.insert(0, co.getSysHostsPath())
-        hosts_list = [list(os.path.split(fn)) + [fn] for fn in hosts_list]
-        self.hosts_lists = hosts_list
-        self.hosts_objects = []
-
-        self.m_list.DeleteAllItems()
-        ch = self.taskbar_icon.current_hosts
-        c_idx = -1
-
-        il = wx.ImageList(16, 16, True)
-        icons_count = len(co.ICONS)
-        for i in xrange(icons_count):
-            il.Add(co.GetMondrianBitmap(i))
-        self.m_list.AssignImageList(il, wx.IMAGE_LIST_SMALL)
-
-        for idx, (folder, fn, fn2) in enumerate(hosts_list):
-
-            icon_idx = idx if idx < icons_count else icons_count - 1
-            ohosts = Hosts(idx, fn2, icon_idx)
-            self.hosts_objects.append(ohosts)
-
-            i, t, t2 = fn.partition(".")
-            if i.isdigit():
-                i = int(i)
-                if i > self.current_max_hosts_index:
-                    self.current_max_hosts_index = i
-
-            c = ""
-            index = self.m_list.InsertStringItem(sys.maxint, ohosts.getTitle())
-
-            # 如果指定了当前选中的 hosts
-            if ohosts.getTitle() == selected_title:
-                ch = self.taskbar_icon.current_hosts = fn2
-                self.SetIcon(co.GetMondrianIcon(ohosts.icon_idx))
-                self.taskbar_icon.SetIcon(co.GetMondrianIcon(ohosts.icon_idx), u"当前 hosts 方案:%s" % ohosts.getTitle())
-                self.m_list.SetItemFont(idx, self.font_bold)
-
-
-            if (ch and ch == fn2) or \
-                (not selected_title and not ch and co.decode(fn) == DEFAULT_HOSTS_FN):
-                c = SELECTED_FLAG
-            if c:
-                c_idx = index
-            self.m_list.SetStringItem(index, 1, c)
-            self.m_list.SetItemImage(index, ohosts.icon_idx, ohosts.icon_idx)
-
-
-        if self.current_selected_hosts_index >= 0:
-            c_idx = self.current_selected_hosts_index
-
-        while c_idx >= len(self.hosts_objects) and c_idx > 0:
-            c_idx -= 1
-
-        ohosts = self.hosts_objects[c_idx]
-
-        self.m_list.Select(c_idx)
-        self.current_selected_hosts_index = c_idx
-        self.current_selected_hosts_fn = self.hosts_objects[c_idx].path
-
-        self.m_textCtrl_content.Value = ohosts.getContent()
-
-
-    def hostsContentChange(self, event):
-
-        c = self.m_textCtrl_content.Value.rstrip()
-        ohosts = self.getOHostsFromFn()
-        old_c = ohosts.getContent()
-        if ohosts and c != old_c:
-            # 内容改变
-#            print ohosts.getTitle()
-#            print("%s, changed!" % self.current_selected_hosts_fn)
-            self.saveCurrentHost(ohosts, c)
-            self.textStyle(old_c)
-        else:
-            # 新切换
-            self.textStyle()
-
-        self.m_btn_apply.Enable()
-
-
-    def menuApplyHost(self, event):
-
-        self.applyHost(event)
-
-
-    def mkNewHostsPath(self):
-
-        global g_local_hosts_dir
-
-        self.current_max_hosts_index += 1
-        return os.path.join(g_local_hosts_dir, "%d.hosts" % self.current_max_hosts_index)
-
-
-    def newHosts_test(self):
-
-        print(123)
-        dlg = ui.Dlg_addHosts(None)
-        if dlg.ShowModal() == wx.ID_OK:
-            print("OK!")
-
-            print(dlg.m_radioBtn_local.Value)
-            print(dlg.m_textCtrl_title.Value)
-            print(dlg.m_textCtrl_url.Value)
-        else:
-            print("Cancel!")
-
-
-
-    def newHosts(self, event=None, default=""):
-        u"""新建一个 hosts"""
-
-        global g_local_hosts_dir
-
-        repeat = False
-        title = default
-
-        self.newHosts_test()
-        return
-
-        dlg = wx.TextEntryDialog(None, u"新建 hosts", u"输入 hosts 名:", title,
-                style=wx.OK | wx.CANCEL
-            )
-        if dlg.ShowModal() == wx.ID_OK:
-            title = dlg.GetValue().strip()
-
-            if title:
-
-                oh = self.getOHostsFromTitle(title)
-                if oh:
-
-                    repeat = True
-                    self.alert(u"命名失败!", u"名为 '%s' 的 hosts 已经存在了!" % title)
-
-                else:
-                    # 保存新文件
-
-                    path = self.mkNewHostsPath()
-                    c = u"# %s" % title
-                    oh = Hosts(path=path)
-                    oh.setTitle(title)
-                    oh.setContent(c)
-                    self.updateHostsList()
-
-        dlg.Destroy()
-
-        if repeat:
-            self.newHosts(event, default=title)
-
-
-    def renameHosts(self, event):
-        u"""重命名一个 hosts"""
-
-        ohosts = self.hosts_objects[self.current_selected_hosts_index]
-        if ohosts.fn == DEFAULT_HOSTS_FN:
-            self.alert(u"不可操作", u"默认 hosts 不可重命名!")
-            return
-
-        old_title = ohosts.getTitle()
-
-        repeat = False
-
-        dlg = wx.TextEntryDialog(None, u"重命名 hosts", u"输入新的 hosts 名:", old_title,
-                style=wx.OK | wx.CANCEL
-            )
-        if dlg.ShowModal() == wx.ID_OK:
-            # 改名
-            new_title = dlg.GetValue().strip()
-
-            if new_title and new_title != old_title:
-
-                oh2 = self.getOHostsFromTitle(new_title)
-
-                if oh2:
-
-                    repeat = True
-                    self.alert(u"重命名失败!", u"'%s' 已存在,请先将它删除!" % new_title)
-
-                else:
-
-                    ohosts.setTitle(new_title)
-
-                    if self.taskbar_icon.current_hosts == ohosts.path:
-                        self.applyHost()
-                    self.updateHostsList()
-
-        dlg.Destroy()
-
-        if repeat:
-            self.renameHosts(event)
-
-
-    def deleteHosts(self, event):
-        u"""删除 hosts"""
-
-        fn = DEFAULT_HOSTS_FN.encode()
-        if self.current_selected_hosts_fn:
-            folder, fn = os.path.split(self.current_selected_hosts_fn)
-#            fn = co.decode(fn)
-        ohosts = self.getOHostsFromFn(fn)
-
-#        print(self.current_selected_hosts_fn, self.taskbar_icon.current_hosts)
-
-        if not self.current_selected_hosts_fn or \
-            self.current_selected_hosts_fn == self.taskbar_icon.current_hosts or \
-            (self.taskbar_icon.current_hosts is None and fn == DEFAULT_HOSTS_FN):
-            self.alert(u"不可删除", u"当前 hosts 正在使用中,不可删除!")
-            return
-
-        dlg = wx.MessageDialog(None, u"确定要删除 hosts '%s'?" % ohosts.getTitle(), u"删除 hosts",
-                wx.YES_NO | wx.ICON_QUESTION
-            )
-        ret_code = dlg.ShowModal()
-        if ret_code == wx.ID_YES:
-            # 删除当前 hosts
-            try:
-                os.remove(ohosts.path)
-            except Exception:
-                pass
-
-            self.updateHostsList()
-
-        dlg.Destroy()
-
-
-    def saveCurrentHost(self, ohosts=None, content=None):
-        u"""保存当前 hosts"""
-
-        c = content or self.m_textCtrl_content.Value.rstrip()
-        ohosts = ohosts or self.getOHostsFromFn()
-        if ohosts:
-            ohosts.setContent(c)
-            ohosts.save()
-
-
-    def applyHost(self, event=None, ohosts=None):
-        u"""应用某个 hosts"""
-
-        # 保存当前 hosts 的内容
-        self.saveCurrentHost()
-
-        # 切换 hosts
-        co.switchHost(self.taskbar_icon, self.current_selected_hosts_fn)
-        self.updateListCtrl()
-
-        self.m_btn_apply.Disable()
-
-
-    def getOHostsFromTitle(self, title):
-
-        for oh in self.hosts_objects:
-            if oh.getTitle() == title:
-                return oh
-
-        return None
-
-
-    def getOHostsFromFn(self, fn=None):
-        u"""从 hosts 的文件名取得它的 id"""
-
-        if not fn:
-            fn = self.current_selected_hosts_fn or DEFAULT_HOSTS_FN.encode()
-
-        fn = co.decode(fn)
-
-        for oh in self.hosts_objects:
-            if oh.fn == fn or oh.dc_path == fn:
-                return oh
-
-        return None
-
-
-    def updateListCtrl(self):
-
-        for idx in range(len(self.hosts_lists)):
-            c = ""
-            font = self.font_normal
-            if self.hosts_lists[idx][2] == self.taskbar_icon.current_hosts:
-                c = SELECTED_FLAG
-                font = self.font_bold
-            self.m_list.SetStringItem(idx, 1, c)
-            self.m_list.SetItemFont(idx, font)
-
-
-
-    def OnHostsItemBeSelected(self, event):
-
-        item = event.GetItem()
-        host_title = self.m_tree.GetItemText(item)
-        idx = event.GetIndex()
-        fn = self.hosts_lists[idx][2]
-        ohosts = self.hosts_objects[idx]
-#        c = open(fn, "rb").read() if os.path.isfile(fn) else ""
-
-        self.current_selected_hosts_index = idx
-        self.current_selected_hosts_fn = fn
-        self.m_textCtrl_content.Value = ohosts.getContent()
-
-        self.m_btn_apply.Enable()
-
-
-    def OnHostsItemRClick(self, event):
-        u""""""
-
-        item = event.GetItem()
-        host_title = self.m_tree.GetItemText(item)
-#        idx = event.GetIndex()
-#        fn = self.hosts_lists[idx][2]
-        fn = self.getOHostsFromTitle(host_title)
-        self.current_selected_hosts_index = idx
-        self.current_selected_hosts_fn = fn
-
-        self.m_list.PopupMenu(self.hosts_item_menu, event.GetPosition())
-
-
-    def OnAbout(self, event):
-
-        dlg = ui.AboutBox(version=VERSION, latest_stable_version=self.latest_stable_version)
-        dlg.ShowModal()
-        dlg.Destroy()
-
-
-
-    def editHost(self, event):
-        u"""编辑一个 hosts 文件"""
-
-        print(1)
-
-
-    def textStyle(self, old_content=None):
-        u"""更新文本区的样式"""
-
-        from libs.highLight import highLight
-
-        self.m_textCtrl_content.SetFont(self.font_mono)
-        highLight(self.m_textCtrl_content, old_content=old_content)
-
-
-    def OnHide(self, event):
-        self.Hide()
-
-
-    def OnIconfiy(self, event):
-        wx.MessageBox("Frame has been iconized!", "Prompt")
-        event.Skip()
-
-    def OnExit(self, event):
-    #        self.taskbar_icon.Destroy()
-    #        self.Destroy()
-    #        event.Skip()
-        self.taskbar_icon.OnExit(event)
-
-    def OnClose(self, event):
-        self.Hide()
-        return False
-
-
-def listLocalHosts():
-    u"""列出指定目录下的 host 文件列表"""
-
-    global g_local_hosts_dir
-
-    fns = [fn for fn in glob.glob(os.path.join(g_local_hosts_dir, "*.hosts")) if\
-           os.path.isfile(fn) and not fn.startswith(".")\
-           and not fn.startswith("_")
-    ]
-
-    return fns
-
-
-def getSysHostsTitle():
-
-    global g_local_hosts_dir
-
-    sys_hosts = co.getSysHostsPath()
-    path = os.path.join(g_local_hosts_dir, DEFAULT_HOSTS_FN)
-
-    ohosts_sys = Hosts(path=sys_hosts)
-    sys_hosts_title = ohosts_sys.getTitle()
-    is_title_valid = False
-
-    fns = listLocalHosts()
-    for fn in fns:
-        fn2 = os.path.split(fn)[1]
-        i, t, t2 = fn2.partition(".")
-        if not i.isdigit():
-            continue
-
-        ohosts = Hosts(path=fn)
-        if ohosts.getTitle() == sys_hosts_title:
-            is_title_valid = True
-            break
-
-    if not is_title_valid:
-        open(path, "wb").write(open(sys_hosts, "rb").read())
-#    else:
-#        if os.path.isfile(path):
-#            os.remove(path)
-
-    return sys_hosts_title if is_title_valid else None
-
-
-def init():
-    global g_local_hosts_dir
-
-    base_dir = os.getcwd()
-    g_local_hosts_dir = os.path.join(base_dir, "hosts")
-    if not os.path.isdir(g_local_hosts_dir):
-        os.makedirs(g_local_hosts_dir)
-
-    return getSysHostsTitle()
-
-
-def main():
-    sys_hosts_title = init()
-    app = wx.App()
-#    app = wx.PySimpleApp()
-    frame = Frame(size=(640, 480), sys_hosts_title=sys_hosts_title)
-    frame.Centre()
-    frame.Show()
-    app.MainLoop()
-
-
-if __name__ == "__main__":
-    main()
-
-

+ 0 - 754
legacy/v1/libs/ToasterBox.py

@@ -1,754 +0,0 @@
-# --------------------------------------------------------------------------- #
-# TOASTERBOX wxPython IMPLEMENTATION
-# Ported And Enhanced From wxWidgets Contribution (Aj Bommarito) By:
-#
-# Andrea Gavana, @ 16 September 2005
-# Latest Revision: 31 Oct 2007, 21.30 CET
-#
-#
-# TODO/Caveats List
-#
-# 1. Any Idea?
-#
-#
-# For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please
-# Write To Me At:
-#
-# [email protected]
-# [email protected]
-#
-# Or, Obviously, To The wxPython Mailing List!!!
-#
-#
-# End Of Comments
-# --------------------------------------------------------------------------- #
-
-
-"""Description:
-
-ToasterBox Is A Cross-Platform Library To Make The Creation Of MSN Style "Toaster"
-Popups Easier. The Syntax Is Really Easy Especially If You Are Familiar With The
-Syntax Of wxPython.
-
-It Has 2 Main Styles:
-
-- TB_SIMPLE:  Using This Style, You Will Be Able To Specify A Background Image For
-             ToasterBox, Text Properties As Text Colour, Font And Label.
-
-- TB_COMPLEX: This Style Will Allow You To Put Almost Any Control Inside A
-             ToasterBox. You Can Add A Panel In Which You Can Put All The Controls
-             You Like.
-
-Both Styles Support The Setting Of ToasterBox Position (On Screen Coordinates),
-Size, The Time After Which The ToasterBox Is Destroyed (Linger), And The Scroll
-Speed Of ToasterBox.
-
-ToasterBox Has Been Tested On The Following Platforms:
-
-Windows (Verified on Windows XP, 2000)
-
-
-Latest Revision: Andrea Gavana @ 31 Oct 2007, 21.30 CET
-
-"""
-
-import textwrap
-import wx
-import sys
-
-from wx.lib.statbmp import GenStaticBitmap as StaticBitmap
-
-# Define Window List, We Use It Globally
-winlist = []
-
-TB_SIMPLE = 1
-TB_COMPLEX = 2
-
-DEFAULT_TB_STYLE = wx.SIMPLE_BORDER | wx.STAY_ON_TOP | wx.FRAME_NO_TASKBAR
-TB_CAPTION = DEFAULT_TB_STYLE | wx.CAPTION | wx.SYSTEM_MENU | wx.CLOSE_BOX | wx.FRAME_TOOL_WINDOW
-
-TB_ONTIME = 1
-TB_ONCLICK = 2
-
-# scroll from up to down
-TB_SCR_TYPE_UD = 1
-# scroll from down to up
-TB_SCR_TYPE_DU = 2
-
-# ------------------------------------------------------------------------------ #
-# Class ToasterBox
-#    Main Class Implementation. It Is Basically A wx.Timer. It Creates And
-#    Displays Popups And Handles The "Stacking".
-# ------------------------------------------------------------------------------ #
-
-class ToasterBox(wx.Timer):
-
-   def __init__(self, parent, tbstyle=TB_SIMPLE, windowstyle=DEFAULT_TB_STYLE,
-                closingstyle=TB_ONTIME, scrollType=TB_SCR_TYPE_DU):
-       """Deafult Class Constructor.
-
-       ToasterBox.__init__(self, tbstyle=TB_SIMPLE, windowstyle=DEFAULT_TB_STYLE)
-
-       Parameters:
-
-       - tbstyle: This Parameter May Have 2 Values:
-         (a) TB_SIMPLE: A Simple ToasterBox, With Background Image And Text
-             Customization Can Be Created;
-         (b) TB_COMPLEX: ToasterBoxes With Different Degree Of Complexity Can
-             Be Created. You Can Add As Many Controls As You Want, Provided
-             That You Call The AddPanel() Method And Pass To It A Dummy Frame
-             And A wx.Panel. See The Demo For Details.
-
-       - windowstyle: This Parameter Influences The Visual Appearance Of ToasterBox:
-         (a) DEFAULT_TB_STYLE: Default Style, No Caption Nor Close Box;
-         (b) TB_CAPTION: ToasterBox Will Have A Caption, With The Possibility To
-             Set A Title For ToasterBox Frame, And A Close Box;
-
-       - closingstyle: Set This Value To TB_ONCLICK If You Want To Be Able To Close
-         ToasterBox By A Mouse Click Anywhere In The ToasterBox Frame.
-
-       """
-
-       self._parent = parent
-       self._sleeptime = 10
-       self._pausetime = 1700
-       self._popuptext = "default"
-       self._popupposition = wx.Point(100,100)
-       self._popuptop = wx.Point(0,0)
-       self._popupsize = wx.Size(150, 170)
-
-       self._backgroundcolour = wx.WHITE
-       self._foregroundcolour = wx.BLACK
-       if sys.platform != "darwin":
-           self._textfont = wx.Font(8, wx.SWISS, wx.NORMAL, wx.NORMAL, False, "Verdana")
-       else:
-           self._textfont = wx.Font(12, wx.SWISS, wx.NORMAL, wx.NORMAL, False, "Monaco")
-
-       self._bitmap = None
-
-       self._tbstyle = tbstyle
-       self._windowstyle = windowstyle
-       self._closingstyle = closingstyle
-
-       self._panel = None
-
-       self._bottomright = wx.Point(wx.GetDisplaySize().GetWidth(),
-                                    wx.GetDisplaySize().GetHeight())
-
-       parent.Bind(wx.EVT_ICONIZE, lambda evt: [w.Hide() for w in winlist])
-
-       self._tb = ToasterBoxWindow(self._parent, self, self._tbstyle, self._windowstyle,
-                                   self._closingstyle, scrollType=scrollType)
-
-
-   def SetPopupPosition(self, pos):
-       """ Sets The ToasterBox Position On Screen. """
-
-       self._popupposition = pos
-
-
-   def SetPopupPositionByInt(self, pos):
-       """ Sets The ToasterBox Position On Screen, At One Of The Screen Corners. """
-
-       self._bottomright = wx.Point(wx.GetDisplaySize().GetWidth(),
-                                    wx.GetDisplaySize().GetHeight())
-
-       # top left
-       if pos == 0:
-           popupposition = wx.Point(0,0)
-       # top right
-       elif pos == 1:
-           popupposition = wx.Point(wx.GetDisplaySize().GetWidth() -
-                                    self._popupsize[0], 0)
-       # bottom left
-       elif pos == 2:
-           popupposition = wxPoint(0, wx.GetDisplaySize().GetHeight() -
-                                   self._popupsize[1])
-       # bottom right
-       elif pos == 3:
-           popupposition = wx.Point(self._bottomright.x - self._popupsize[0],
-                                    self._bottomright.y - self._popupsize[1])
-
-       self._bottomright = wx.Point(popupposition.x + self._popupsize[0],
-                                    popupposition.y + self._popupsize[1])
-
-
-   def SetPopupBackgroundColor(self, colour=None):
-       """ Sets The ToasterBox Background Colour. Use It Only For ToasterBoxes Created
-       With TB_SIMPLE Style. """
-
-       if colour is None:
-           colour = wx.WHITE
-
-       self._backgroundcolour = colour
-
-
-   def SetPopupTextColor(self, colour=None):
-       """ Sets The ToasterBox Foreground Colour. Use It Only For ToasterBoxes Created
-       With TB_SIMPLE Style. """
-
-       if colour is None:
-           colour = wx.BLACK
-
-       self._foregroundcolour = colour
-
-
-   def SetPopupTextFont(self, font=None):
-       """ Sets The ToasterBox Text Font. Use It Only For ToasterBoxes Created With
-       TB_SIMPLE Style. """
-
-       if font is None:
-           if sys.platform != "darwin":
-               font = wx.Font(8, wx.SWISS, wx.NORMAL, wx.NORMAL, False, "Verdana")
-           else:
-               font = wx.Font(12, wx.SWISS, wx.NORMAL, wx.NORMAL, False, "Monaco")
-
-       self._textfont = font
-
-
-   def SetPopupSize(self, size):
-       """ Sets The ToasterBox Size. """
-
-       self._popupsize = size
-
-
-   def SetPopupPauseTime(self, pausetime):
-       """ Sets The Time After Which The ToasterBox Is Destroyed (Linger). """
-
-       self._pausetime = pausetime
-
-
-   def SetPopupBitmap(self, bitmap=None):
-       """ Sets The ToasterBox Background Image. Use It Only For ToasterBoxes
-       Created With TB_SIMPLE Style. """
-
-       if bitmap is not None:
-           bitmap = wx.Bitmap(bitmap, wx.BITMAP_TYPE_BMP)
-
-       self._bitmap = bitmap
-
-
-   def SetPopupScrollSpeed(self, speed):
-       """ Sets The ToasterBox Scroll Speed. The Speed Parameter Is The Pause
-       Time (In ms) For Every Step In The ScrollUp() Method."""
-
-       self._sleeptime = speed
-
-
-   def SetPopupText(self, text):
-       """ Sets The ToasterBox Text. Use It Only For ToasterBoxes Created With
-       TB_SIMPLE Style. """
-
-       self._popuptext = text
-
-
-   def AddPanel(self, panel):
-       """ Adds A Panel To The ToasterBox. Use It Only For ToasterBoxes Created
-       With TB_COMPLEX Style. """
-
-       if not self._tbstyle & TB_COMPLEX:
-           raise "\nERROR: Panel Can Not Be Added When Using TB_SIMPLE ToasterBox Style"
-           return
-
-       self._panel = panel
-
-
-   def Play(self):
-       """ Creates The ToasterBoxWindow, That Does All The Job. """
-
-       # create new window
-       self._tb.SetPopupSize((self._popupsize[0], self._popupsize[1]))
-       self._tb.SetPopupPosition((self._popupposition[0], self._popupposition[1]))
-       self._tb.SetPopupPauseTime(self._pausetime)
-       self._tb.SetPopupScrollSpeed(self._sleeptime)
-
-       if self._tbstyle == TB_SIMPLE:
-           self._tb.SetPopupTextColor(self._foregroundcolour)
-           self._tb.SetPopupBackgroundColor(self._backgroundcolour)
-           self._tb.SetPopupTextFont(self._textfont)
-
-           if self._bitmap is not None:
-               self._tb.SetPopupBitmap(self._bitmap)
-
-           self._tb.SetPopupText(self._popuptext)
-
-       if self._tbstyle == TB_COMPLEX:
-           if self._panel is not None:
-               self._tb.AddPanel(self._panel)
-
-       # clean up the list
-       self.CleanList()
-
-       # check to see if there is already a window displayed
-       # by looking at the linked list
-       if len(winlist) > 0:
-           # there ARE other windows displayed already
-           # reclac where it should display
-           self.MoveAbove(self._tb)
-
-       # shift new window on to the list
-       winlist.append(self._tb)
-
-       if not self._tb.Play():
-           # if we didn't show the window properly, remove it from the list
-           winlist.remove(winlist[-1])
-           # delete the object too
-           self._tb.Destroy()
-           return
-
-
-   def MoveAbove(self, tb):
-       """ If A ToasterBox Already Exists, Move The New One Above. """
-
-       # recalc where to place this popup
-
-       self._tb.SetPopupPosition((self._popupposition[0], self._popupposition[1] -
-                                  self._popupsize[1]*len(winlist)))
-
-
-   def GetToasterBoxWindow(self):
-       """ Returns The ToasterBox Frame. """
-
-       return self._tb
-
-
-   def SetTitle(self, title):
-       """ Sets The ToasterBox Title If It Was Created With TB_CAPTION Window Style. """
-
-       self._tb.SetTitle(title)
-
-
-   def Notify(self):
-       """ It's Time To Hide A ToasterBox! """
-
-       if len(winlist) == 0:
-           return
-
-       # clean the window list
-       self.CleanList()
-
-       # figure out how many blanks we have
-       try:
-           node = winlist[0]
-       except:
-           return
-
-       if not node:
-           return
-
-       # move windows to fill in blank space
-       for i in xrange(node.GetPosition()[1], self._popupposition[1], 4):
-           if i > self._popupposition[1]:
-               i = self._popupposition[1]
-
-           # loop through all the windows
-           for j in xrange(0, len(winlist)):
-               ourNewHeight = i - (j*self._popupsize[1] - 8)
-               tmpTb = winlist[j]
-               # reset where the object THINKS its supposed to be
-               tmpTb.SetPopupPosition((self._popupposition[0], ourNewHeight))
-               # actually move it
-               tmpTb.SetDimensions(self._popupposition[0], ourNewHeight, tmpTb.GetSize().GetWidth(),
-                                   tmpTb.GetSize().GetHeight())
-
-           wx.Usleep(self._sleeptime)
-
-
-   def CleanList(self):
-       """ Clean The Window List. """
-
-       if len(winlist) == 0:
-           return
-
-       node = winlist[0]
-       while node:
-           if not node.IsShown():
-               winlist.remove(node)
-               try:
-                   node = winlist[0]
-               except:
-                   node = 0
-           else:
-               indx = winlist.index(node)
-               try:
-                   node = winlist[indx+1]
-               except:
-                   node = 0
-
-
-# ------------------------------------------------------------------------------ #
-# Class ToasterBoxWindow
-#    This Class Does All The Job, By Handling Background Images, Text Properties
-#    And Panel Adding. Depending On The Style You Choose, ToasterBoxWindow Will
-#    Behave Differently In Order To Handle Widgets Inside It.
-# ------------------------------------------------------------------------------ #
-
-class ToasterBoxWindow(wx.Frame):
-
-   def __init__(self, parent, parent2, tbstyle, windowstyle,
-       closingstyle, scrollType=TB_SCR_TYPE_DU):
-       """Default Class Constructor.
-
-       Used Internally. Do Not Call Directly This Class In Your Application!
-       """
-
-       wx.Frame.__init__(self, parent, wx.ID_ANY, "window", wx.DefaultPosition,
-                         wx.DefaultSize, style=windowstyle | wx.CLIP_CHILDREN)
-
-       self._starttime = wx.GetLocalTime()
-       self._parent2 = parent2
-       self._parent = parent
-       self._sleeptime = 10
-       self._step = 4
-       self._pausetime = 1700
-       self._textcolour = wx.BLACK
-       self._popuptext = "Change Me!"
-       # the size we want the dialog to be
-       framesize = wx.Size(150, 170)
-       self._count = 1
-       self._tbstyle = tbstyle
-       self._windowstyle = windowstyle
-       self._closingstyle = closingstyle
-       self._scrollType = scrollType
-
-
-       if tbstyle == TB_COMPLEX:
-           self.sizer = wx.BoxSizer(wx.VERTICAL)
-       else:
-           self._staticbitmap = None
-
-       if self._windowstyle == TB_CAPTION:
-           self.Bind(wx.EVT_CLOSE, self.OnClose)
-           self.SetTitle("")
-
-       if self._closingstyle & TB_ONCLICK and self._windowstyle != TB_CAPTION:
-           self.Bind(wx.EVT_LEFT_DOWN, self.OnMouseDown)
-
-       self._bottomright = wx.Point(wx.GetDisplaySize().GetWidth(),
-                                    wx.GetDisplaySize().GetHeight())
-
-       self.SetDimensions(self._bottomright.x, self._bottomright.y,
-                          framesize.GetWidth(), framesize.GetHeight())
-
-
-   def OnClose(self, event):
-
-       self.NotifyTimer(None)
-       event.Skip()
-
-
-   def OnMouseDown(self, event):
-
-       self.NotifyTimer(None)
-       event.Skip()
-
-
-   def SetPopupBitmap(self, bitmap):
-       """ Sets The ToasterBox Background Image. Use It Only For ToasterBoxes
-       Created With TB_SIMPLE Style. """
-
-       bitmap = bitmap.ConvertToImage()
-       xsize, ysize = self.GetSize()
-       bitmap = bitmap.Scale(xsize, ysize)
-       bitmap = bitmap.ConvertToBitmap()
-       self._staticbitmap = StaticBitmap(self, -1, bitmap, pos=(0,0))
-
-       if self._closingstyle & TB_ONCLICK and self._windowstyle != TB_CAPTION:
-           self._staticbitmap.Bind(wx.EVT_LEFT_DOWN, self.OnMouseDown)
-
-
-   def SetPopupSize(self, size):
-       """ Sets The ToasterBox Size. """
-
-       self.SetDimensions(self._bottomright.x, self._bottomright.y, size[0], size[1])
-
-
-   def SetPopupPosition(self, pos):
-       """ Sets The ToasterBox Position On Screen. """
-
-       self._bottomright = wx.Point(pos[0] + self.GetSize().GetWidth(),
-                                    pos[1] + self.GetSize().GetHeight())
-       self._dialogtop = pos
-
-
-   def SetPopupPositionByInt(self, pos):
-       """ Sets The ToasterBox Position On Screen, At One Of The Screen Corners. """
-
-       self._bottomright = wx.Point(wx.GetDisplaySize().GetWidth(),
-                                    wx.GetDisplaySize().GetHeight())
-
-       # top left
-       if pos == 0:
-           popupposition = wx.Point(0,0)
-       # top right
-       elif pos == 1:
-           popupposition = wx.Point(wx.GetDisplaySize().GetWidth() -
-                                    self._popupsize[0], 0)
-       # bottom left
-       elif pos == 2:
-           popupposition = wx.Point(0, wx.GetDisplaySize().GetHeight() -
-                                   self._popupsize[1])
-       # bottom right
-       elif pos == 3:
-           popupposition = wx.Point(self._bottomright.x - self._popupsize[0],
-                                    self._bottomright.y - self._popupsize[1])
-
-       self._bottomright = wx.Point(popupposition.x + self._popupsize[0],
-                                    popupposition.y + self._popupsize[1])
-
-       self._dialogtop = popupposition
-
-
-   def SetPopupPauseTime(self, pausetime):
-       """ Sets The Time After Which The ToasterBox Is Destroyed (Linger). """
-
-       self._pausetime = pausetime
-
-
-   def SetPopupScrollSpeed(self, speed):
-       """ Sets The ToasterBox Scroll Speed. The Speed Parameter Is The Pause
-       Time (In ms) For Every Step In The ScrollUp() Method."""
-
-       self._sleeptime = speed
-
-
-   def AddPanel(self, panel):
-       """ Adds A Panel To The ToasterBox. Use It Only For ToasterBoxes Created
-       With TB_COMPLEX Style. """
-
-       if not self._tbstyle & TB_COMPLEX:
-           raise "\nERROR: Panel Can Not Be Added When Using TB_SIMPLE ToasterBox Style"
-           return
-
-       self.sizer.Add(panel, 1, wx.EXPAND)
-       self.sizer.Layout()
-       self.SetSizer(self.sizer)
-
-       if self._closingstyle & TB_ONCLICK and self._windowstyle != TB_CAPTION:
-           panel.Bind(wx.EVT_LEFT_DOWN, self.OnMouseDown)
-
-
-   def SetPopupText(self, text):
-       """ Sets The ToasterBox Text. Use It Only For ToasterBoxes Created With
-       TB_SIMPLE Style. """
-
-       self._popuptext = text
-
-
-   def SetPopupTextFont(self, font):
-       """ Sets The ToasterBox Text Font. Use It Only For ToasterBoxes Created With
-       TB_SIMPLE Style. """
-
-       self._textfont = font
-
-
-   def GetPopupText(self):
-       """ Returns The ToasterBox Text. Use It Only For ToasterBoxes Created With
-       TB_SIMPLE Style. """
-
-       return self._popuptext
-
-
-   def Play(self):
-       """ Creates The ToasterBoxWindow, That Does All The Job. """
-
-       # do some checks to make sure this window is valid
-       if self._bottomright.x < 1 or self._bottomright.y < 1:
-           return False
-
-       if self.GetSize().GetWidth() < 50 or self.GetSize().GetWidth() < 50:
-           # toasterbox launches into a endless loop for some reason
-           # when you try to make the window too small.
-           return False
-
-       self.ScrollUp()
-       timerid = wx.NewId()
-       self.showtime = wx.Timer(self, timerid)
-       self.showtime.Start(self._pausetime)
-       self.Bind(wx.EVT_TIMER, self.NotifyTimer, id=timerid)
-
-       return True
-
-
-   def NotifyTimer(self, event):
-       """ Hides Gradually The ToasterBoxWindow. """
-
-       self.showtime.Stop()
-       del self.showtime
-       self.ScrollDown()
-
-
-   def SetPopupBackgroundColor(self, colour):
-       """ Sets The ToasterBox Background Colour. Use It Only For ToasterBoxes Created
-       With TB_SIMPLE Style. """
-
-       self.SetBackgroundColour(colour)
-
-
-   def SetPopupTextColor(self, colour):
-       """ Sets The ToasterBox Foreground Colour. Use It Only For ToasterBoxes Created
-       With TB_SIMPLE Style. """
-
-       self._textcolour = colour
-
-
-   def ScrollUp(self):
-       """ Scrolls The ToasterBox Up, Which Means Gradually Showing The ToasterBox. """
-
-       self.Show(True)
-
-       # walk the Y value up in a raise motion
-       xpos = self.GetPosition().x
-       ypos = self._bottomright[1]
-       windowsize = 0
-
-       # checking the type of the scroll (from up to down or from down to up)
-       if self._scrollType == TB_SCR_TYPE_UD:
-           start = self._dialogtop[1]
-           stop = ypos
-           step = self._step
-       elif self._scrollType == TB_SCR_TYPE_DU:
-           start = ypos
-           stop = self._dialogtop[1]
-           step = -self._step
-       else:
-           errMsg = ("scrollType not supported (in ToasterBoxWindow.ScrollUp): %s" %
-                 self._scrollType)
-           raise ValueError(errMsg)
-
-       for i in xrange(start, stop, step):
-           if i < self._dialogtop[1]:
-             i = self._dialogtop[1]
-
-           windowsize = windowsize + self._step
-
-           # checking the type of the scroll (from up to down or from down to up)
-           if self._scrollType == TB_SCR_TYPE_UD:
-               dimY = self._dialogtop[1]
-           elif self._scrollType == TB_SCR_TYPE_DU:
-               dimY = i
-           else:
-               errMsg = ("scrollType not supported (in ToasterBoxWindow.ScrollUp): %s" %
-                     self._scrollType)
-               raise ValueError(errMsg)
-
-           self.SetDimensions(self._dialogtop[0], dimY, self.GetSize().GetWidth(),
-                              windowsize)
-
-           if self._tbstyle == TB_SIMPLE:
-               self.DrawText()
-
-           wx.Usleep(self._sleeptime)
-           self.Update()
-           self.Refresh()
-
-       self.Update()
-
-       if self._tbstyle == TB_SIMPLE:
-           self.DrawText()
-
-#       self.SetFocus()
-
-
-   def ScrollDown(self):
-       """ Scrolls The ToasterBox Down, Which Means Gradually Hiding The ToasterBox. """
-
-       # walk down the Y value
-       windowsize = self.GetSize().GetHeight()
-
-       # checking the type of the scroll (from up to down or from down to up)
-       if self._scrollType == TB_SCR_TYPE_UD:
-           start = self._bottomright.y
-           stop = self._dialogtop[1]
-           step = -self._step
-       elif self._scrollType == TB_SCR_TYPE_DU:
-           start = self._dialogtop[1]
-           stop = self._bottomright.y
-           step = self._step
-       else:
-           errMsg = ("scrollType not supported (in ToasterBoxWindow.ScrollUp): %s" %
-                 self._scrollType)
-           raise ValueError(errMsg)
-
-       for i in xrange(start, stop, step):
-           if i > self._bottomright.y:
-               i = self._bottomright.y
-
-           windowsize = windowsize - self._step
-
-           # checking the type of the scroll (from up to down or from down to up)
-           if self._scrollType == TB_SCR_TYPE_UD:
-               dimY = self._dialogtop[1]
-           elif self._scrollType == TB_SCR_TYPE_DU:
-               dimY = i
-           else:
-               errMsg = ("scrollType not supported (in ToasterBoxWindow.ScrollUp): %s" %
-                     self._scrollType)
-               raise ValueError(errMsg)
-
-           self.SetDimensions(self._dialogtop[0], dimY,
-                              self.GetSize().GetWidth(), windowsize)
-
-           wx.Usleep(self._sleeptime)
-           self.Refresh()
-
-       self.Hide()
-       if self._parent2:
-           self._parent2.Notify()
-
-
-   def DrawText(self):
-       if self._staticbitmap is not None:
-           dc = wx.ClientDC(self._staticbitmap)
-       else:
-           dc = wx.ClientDC(self)
-       dc.SetFont(self._textfont)
-
-       if not hasattr(self, "text_coords"):
-           self._getTextCoords(dc)
-
-       dc.DrawTextList(*self.text_coords)
-
-
-   def _getTextCoords(self, dc):
-       """ Draw The User Specified Text Using The wx.DC. Use It Only For ToasterBoxes
-       Created With TB_SIMPLE Style. """
-
-       # border from sides and top to text (in pixels)
-       border = 7
-       # how much space between text lines
-       textPadding = 2
-
-       pText = self.GetPopupText()
-
-       max_len = len(pText)
-
-       tw, th = self._parent2._popupsize
-
-       if self._windowstyle == TB_CAPTION:
-           th = th - 20
-
-       while 1:
-           lines = textwrap.wrap(pText, max_len)
-
-           for line in lines:
-               w, h = dc.GetTextExtent(line)
-               if w > tw - border * 2:
-                   max_len -= 1
-                   break
-           else:
-               break
-
-       fh = 0
-       for line in lines:
-           w, h = dc.GetTextExtent(line)
-           fh += h + textPadding
-       y = (th - fh) / 2; coords = []
-
-       for line in lines:
-           w, h = dc.GetTextExtent(line)
-           x = (tw - w) / 2
-           coords.append((x, y))
-           y += h + textPadding
-
-       self.text_coords = (lines, coords)

+ 0 - 0
legacy/v1/libs/__init__.py


+ 0 - 137
legacy/v1/libs/cls_Hosts.py

@@ -1,137 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import os
-import json
-import chardet
-import urllib2
-
-import common_operations as co
-
-DEFAULT_HOSTS_FN = u"DEFAULT.hosts"
-
-class Hosts(object):
-
-    CONFIG_FLAG = "#@SwitchHost!"
-
-    def __init__(self, index=0, path=None, icon_idx=0):
-
-        self.index = index
-        self.path = path
-        self.dc_path = co.decode(path)
-        self.folder, self.fn = os.path.split(path)
-#        self.fn = co.decode(self.fn)
-#        if os.name == "nt":
-#            self.fn = self.fn.decode("GB18030")
-
-        self.title = None
-        self.icon_idx = icon_idx
-        self.content = ""
-        self.is_selected = False
-
-        self.url = None # 如果是在线hosts方案,则此项不为空
-        self.last_fetch_dt = None # 如果是在线hosts方案,则此项为最后更新时间
-
-        self.read()
-
-
-    @property
-    def is_read_only(self):
-
-        return self.url is not None
-
-
-    def read(self):
-
-        if not self.url:
-            c = open(self.path, "rb").read().strip() if os.path.isfile(self.path) else ""
-
-        else:
-            c = urllib2.urlopen(self.url).read().strip() if co.httpExists(self.url) else ""
-
-#        c = co.decode(c)
-        self.setContent(c, save=False)
-
-
-
-    def getConfig(self, ln):
-        u"""从一行内容中取得配置信息"""
-
-        cfg = None
-        v = ln.partition(self.CONFIG_FLAG)[2].strip()
-        if v:
-            try:
-                cfg = json.loads(v)
-            except Exception:
-                pass
-
-        if cfg:
-            self.title = cfg.get("title", self.title)
-            self.icon_idx = cfg.get("icon_idx", self.icon_idx)
-
-
-    def save(self):
-
-        if not self.path:
-            return
-
-        cfg = {
-            "title": self.title,
-            "icon_idx": self.icon_idx,
-        }
-        if self.url:
-            cfg.update({
-                "url": self.url,
-            })
-        cfg_ln = u"%s %s" % (self.CONFIG_FLAG, json.dumps(cfg).replace("\n", "").replace("\r", ""))
-
-        c = self.content
-        if not repr(c).startswith("u"):
-            c = c.decode("utf-8")
-
-        c = u"%s\n%s" % (cfg_ln, c)
-        open(self.path, "wb").write(c.encode("utf-8"))
-
-
-    def getTitle(self):
-
-        return self.title or self.fn if self.fn != DEFAULT_HOSTS_FN else self.fn
-
-
-    def setTitle(self, title):
-
-        self.title = title
-        self.save()
-
-
-    def setIcon(self, icon_idx):
-
-        self.icon_idx = icon_idx
-        self.save()
-
-
-    def setContent(self, c, save=True):
-
-        self.content = c #co.encode(c)
-
-        # 查看第一行是否为配置内容
-        # 第一行以 #SwitchHost 开头表示为配置信息
-        a = [i.strip() for i in c.split("\n")]
-        if a[0].startswith(self.CONFIG_FLAG):
-            self.getConfig(a[0])
-            self.content = "\n".join(a[1:])
-
-        if save:
-            self.save()
-
-
-    def getContent(self):
-
-        c = self.content
-        if not repr(c).startswith("u"):
-            try:
-                cd = chardet.detect(c)
-                c = c.decode(cd.get("encoding", "utf-8"))
-            except Exception:
-                c = c.decode("utf-8")
-
-        return c

+ 0 - 230
legacy/v1/libs/common_operations.py

@@ -1,230 +0,0 @@
-# -*- coding: utf-8 -*-
-
-u"""
-基本操作
-"""
-
-import os
-import sys
-import traceback
-import wx
-import chardet
-import urllib
-import re
-import threading
-import httplib
-import urlparse
-
-
-if os.name == "posix":
-    if sys.platform != "darwin":
-        # Linux
-        try:
-            import pynotify
-        except ImportError:
-            pynotify = None
-
-    else:
-        # Mac
-        import gntp.notifier
-
-        growl = gntp.notifier.GrowlNotifier(
-            applicationName="SwitchHosts!",
-            notifications=["New Updates", "New Messages"],
-            defaultNotifications=["New Messages"],
-            hostname = "127.0.0.1", # Defaults to localhost
-            # password = "" # Defaults to a blank password
-        )
-        growl.register()
-
-from icons import ICONS, ICONS2, ICONS_ICO
-
-def GetMondrianData(i=0, fn=None):
-    if not fn:
-        idx = i if 0 <= i < len(ICONS) else 0
-        return ICONS_ICO[idx]
-    else:
-        return ICONS2[fn]
-
-
-def GetMondrianBitmap(i=0, fn=None):
-    return wx.BitmapFromImage(GetMondrianImage(i, fn))
-
-
-def GetMondrianImage(i=0, fn=None):
-    import cStringIO
-
-    stream = cStringIO.StringIO(GetMondrianData(i, fn))
-    return wx.ImageFromStream(stream)
-
-
-def GetMondrianIcon(i=0, fn=None):
-    icon = wx.EmptyIcon()
-    icon.CopyFromBitmap(GetMondrianBitmap(i, fn))
-    return icon
-
-
-def macNotify(msg, title):
-
-#    print("mac nofity!")
-
-    growl.notify(
-        noteType="New Messages",
-        title=title,
-        description=msg,
-        sticky=False,
-        priority=1,
-    )
-
-
-def notify(frame, msg="", title=u"消息"):
-
-    if os.name == "posix":
-
-        if sys.platform != "darwin":
-            # linux 系统
-            pynotify.Notification(title, msg).show()
-
-        else:
-            # Mac 系统
-            macNotify(msg, title)
-
-        return
-
-
-    import ToasterBox as TB
-
-    sw, sh = wx.GetDisplaySize()
-    width, height = 210, 50
-    px = sw - 230
-    py = sh - 100
-
-    tb = TB.ToasterBox(frame)
-    tb.SetPopupText(msg)
-    tb.SetPopupSize((width, height))
-    tb.SetPopupPosition((px, py))
-    tb.Play()
-
-    frame.SetFocus()
-
-
-def switchHost(obj, fn):
-    u"""切换 hosts 为 fn 的内容"""
-
-    from cls_Hosts import Hosts
-
-    if not os.path.isfile(fn):
-        wx.MessageBox(u"hosts 文件 '%s' 不存在!" % fn, "Error!")
-
-    ohosts = Hosts(path=fn)
-
-    sys_hosts_fn = getSysHostsPath()
-
-    try:
-        a = open(fn, "rb").read().split("\n")
-        a = [ln.rstrip() for ln in a]
-        if sys_hosts_fn:
-            open(sys_hosts_fn, "wb").write(os.linesep.join(a))
-        else:
-            wx.MessageBox(u"无效的系统 hosts 路径!")
-
-        obj.current_hosts = fn
-        title = ohosts.getTitle()
-
-        obj.SetIcon(GetMondrianIcon(), "Hosts: %s" % title)
-        notify(obj.frame, u"Hosts 已切换为 %s。" % title)
-
-        ohosts = obj.frame.getOHostsFromFn(fn)
-        obj.SetIcon(GetMondrianIcon(ohosts.icon_idx), u"当前 hosts 方案:%s" % ohosts.getTitle())
-        obj.frame.SetIcon(GetMondrianIcon(ohosts.icon_idx))
-        obj.frame.current_use_hosts_index = ohosts.index
-
-
-    except Exception:
-        err_msg = traceback.format_exc()
-        if "Permission denied" in err_msg:
-            err_msg = u"权限不足!"
-        wx.MessageBox(err_msg, u"hosts 未能成功切换!")
-
-
-def getSysHostsPath():
-    u"""取得系统 host 文件的路径"""
-
-    if os.name == "nt":
-        path = "C:\\Windows\\System32\\drivers\\etc\\hosts"
-    else:
-        path = "/etc/hosts"
-
-    return path if os.path.isfile(path) else None
-
-
-def encode(s):
-
-#    print("--")
-#    print(chardet.detect(s))
-    return unicode(s).encode("UTF-8") if s else ""
-
-
-def decode(s):
-
-    if not s:
-        return ""
-
-    cd = {}
-    try:
-        cd = chardet.detect(s)
-    except Exception:
-#        print(traceback.format_exc())
-        pass
-
-    encoding = cd.get("encoding") if cd.get("confidence", 0) > 0.65 else None
-    if not encoding:
-        encoding = "GB18030" if os.name == "nt" else "UTF-8"
-#    print s, cd, encoding, s.decode(encoding)
-
-    return s.decode(encoding)
-
-
-def checkLatestStableVersion(obj):
-
-    def _f(obj):
-        url = "https://github.com/oldj/SwitchHosts/blob/master/README.md"
-        ver = None
-
-        try:
-            c = urllib.urlopen(url).read()
-            v = re.search(r"\bLatest Stable:\s?(?P<version>[\d\.]+)\b", c)
-            if v:
-                ver = v.group("version")
-
-        except Exception:
-            pass
-
-        obj.setLatestStableVersion(ver)
-
-        return ver
-
-    t = threading.Thread(target=_f, args=(obj,))
-    t.setDaemon(True)
-    t.start()
-
-
-def httpExists(url):
-    host, path = urlparse.urlsplit(url)[1:3]
-    found = 0
-    try:
-        connection = httplib.HTTPConnection(host)  ## Make HTTPConnection Object
-        connection.request("HEAD", path)
-        responseOb = connection.getresponse()      ## Grab HTTPResponse Object
-
-        if responseOb.status == 200:
-            found = 1
-        elif responseOb.status == 302:
-            found = httpExists(urlparse.urljoin(url, responseOb.getheader('location', '')))
-        else:
-            print "Status %d %s : %s" % (responseOb.status, responseOb.reason, url)
-    except Exception, e:
-        print e.__class__, e, url
-    return found
-
-

+ 0 - 74
legacy/v1/libs/highLight.py

@@ -1,74 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import wx
-import re
-import sys
-
-
-if sys.platform != "darwin":
-    font_mono = wx.Font(10, wx.ROMAN, wx.NORMAL, wx.NORMAL, faceName="Courier New")
-
-else:
-    # 系统是 Mac OS X
-    font_mono = wx.Font(12, wx.ROMAN, wx.NORMAL, wx.NORMAL, faceName="Monaco")
-
-
-def __highLightOneLine(txtctrl, ln, start_pos, styles):
-
-    ln_content, t, ln_comment = ln.partition("#")
-    end_pos = start_pos + len(ln)
-    txtctrl.SetStyle(start_pos, end_pos, wx.TextAttr(styles["color_normal"], "#ffffff", styles["font_mono"]))
-
-    # 行正文部分
-    re_ip = re.match(r"^(\s*[\da-f\.:]+[\da-f]+)\s+\w", ln_content)
-    if re_ip:
-        s_ip = re_ip.group(1)
-        pos2 = start_pos + len(s_ip)
-        pos = pos2 - len(s_ip.lstrip())
-        txtctrl.SetStyle(pos, pos2, wx.TextAttr(styles["color_ip"], "#ffffff", styles["font_mono"]))
-    elif len(ln_content.strip()) > 0:
-        pos2 = start_pos + len(ln_content)
-        txtctrl.SetStyle(start_pos, pos2, wx.TextAttr(styles["color_error"], "#ffffff", styles["font_mono"]))
-
-    # 行注释部分
-    if t:
-        pos = start_pos + len(ln_content)
-        txtctrl.SetStyle(pos, end_pos, wx.TextAttr(styles["color_comment"], "#ffffff", styles["font_mono"]))
-
-
-def highLight(txtctrl, styles=None, old_content=None):
-
-    default_style = {
-        "color_normal": "#000000",
-        "color_bg": "#ffffff",
-        "color_comment": "#339933",
-        "color_ip": "#0000cc",
-        "color_error": "#ff0000",
-        "font_mono": font_mono,
-    }
-    if styles:
-        default_style.update(styles)
-    styles = default_style
-
-    content = txtctrl.Value.replace("\r", "")
-    lns = content.split("\n")
-    if old_content:
-        old_content = old_content.replace("\r", "")
-        lns_old = old_content.split("\n")
-    else:
-        lns_old = None
-    pos = 0
-
-    for idx, ln in enumerate(lns):
-        ln_old = None
-        if lns_old and idx < len(lns_old):
-            ln_old = lns_old[idx]
-
-        if not ln_old or ln != ln_old:
-            __highLightOneLine(txtctrl, ln, pos, styles)
-
-        pos += len(ln) + 1
-
-
-
-  

File diff suppressed because it is too large
+ 0 - 21
legacy/v1/libs/icons.py


+ 0 - 9
legacy/v1/libs/nix_notify.py

@@ -1,9 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import pynotify
-
-def showNotify(title, msg):
-    pynotify.Notification(title, msg).show()
-
-if __name__ == "__main__":
-    showNotify(u"标题", u"内容")

+ 0 - 330
legacy/v1/libs/ui.py

@@ -1,330 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import os
-import wx, wx.html
-import wx.lib.buttons as buttons
-import common_operations as co
-
-
-class Frame(wx.Frame):
-    ID_HOSTS_TEXT = wx.NewId()
-
-    def __init__(self,
-                 parent=None, id=wx.ID_ANY, title="SwitchHost!", pos=wx.DefaultPosition,
-                 size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE,
-                 cls_TaskBarIcon=None
-    ):
-        wx.Frame.__init__(self, parent, id, title, pos, size, style)
-
-        self.SetIcon(co.GetMondrianIcon())
-        self.taskbar_icon = cls_TaskBarIcon(self)
-        #        self.Bind(wx.EVT_CLOSE, self.OnClose)
-        self.SetSizeHintsSz(wx.DefaultSize, wx.DefaultSize)
-
-        self.m_menubar1 = wx.MenuBar(0)
-        self.m_menu1 = wx.Menu()
-        self.m_menuItem_new = wx.MenuItem(self.m_menu1, wx.ID_NEW, u"新建(&N)", wx.EmptyString, wx.ITEM_NORMAL)
-        self.m_menu1.AppendItem(self.m_menuItem_new)
-        self.m_menu1.AppendSeparator()
-        self.m_menuItem_exit = wx.MenuItem(self.m_menu1, wx.ID_EXIT, u"退出(&X)", wx.EmptyString, wx.ITEM_NORMAL)
-        self.m_menu1.AppendItem(self.m_menuItem_exit)
-
-        self.m_menubar1.Append(self.m_menu1, u"文件(&F)")
-
-        self.m_menu2 = wx.Menu()
-        self.m_menuItem_about = wx.MenuItem(self.m_menu2, wx.ID_ABOUT, u"关于(&A)", wx.EmptyString, wx.ITEM_NORMAL)
-        self.m_menu2.AppendItem(self.m_menuItem_about)
-
-        self.m_menubar1.Append(self.m_menu2, u"帮助(&H)")
-
-        self.SetMenuBar(self.m_menubar1)
-
-        bSizer1 = wx.BoxSizer(wx.VERTICAL)
-
-        self.m_panel1 = wx.Panel(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL)
-        bSizer4 = wx.BoxSizer(wx.HORIZONTAL)
-
-        bSizer5 = wx.BoxSizer(wx.VERTICAL)
-
-        self.m_list = wx.ListCtrl(self.m_panel1, wx.ID_ANY, wx.DefaultPosition, wx.Size(160, 320),
-                                  wx.LC_REPORT)
-        self.m_list.Hide()
-        bSizer5.Add(self.m_list, 0, wx.ALL | wx.EXPAND, 5)
-
-        self.m_tree = wx.TreeCtrl(self.m_panel1, wx.ID_ANY, wx.DefaultPosition, wx.Size(160, 320))
-        self.tree_root = self.m_tree.AddRoot(u"hosts")
-        self.tree_local = self.m_tree.AppendItem(self.tree_root, u"本地方案")
-        self.tree_online = self.m_tree.AppendItem(self.tree_root, u"在线方案")
-        self.m_tree.ExpandAll()
-        bSizer5.Add(self.m_tree, 0, wx.ALL | wx.EXPAND, 5)
-
-        bSizer61 = wx.BoxSizer(wx.HORIZONTAL)
-
-        self.m_btn_add = buttons.GenBitmapTextButton(self.m_panel1, wx.ID_ADD, co.GetMondrianBitmap(fn="add"), u"添加")
-        bSizer61.Add(self.m_btn_add, 0, wx.ALL, 5)
-
-        self.m_btn_del = buttons.GenBitmapTextButton(self.m_panel1, wx.ID_DELETE, co.GetMondrianBitmap(fn="delete"), u"删除")
-        bSizer61.Add(self.m_btn_del, 0, wx.ALL, 5)
-
-        bSizer5.Add(bSizer61, 1, wx.EXPAND, 5)
-
-        bSizer4.Add(bSizer5, 0, wx.EXPAND, 5)
-
-        bSizer6 = wx.BoxSizer(wx.VERTICAL)
-
-        self.m_textCtrl_content = wx.TextCtrl(self.m_panel1, self.ID_HOSTS_TEXT, wx.EmptyString, wx.DefaultPosition,
-                                              wx.DefaultSize,
-                                              wx.TE_MULTILINE|wx.TE_RICH2|wx.TE_PROCESS_TAB|wx.HSCROLL)
-        self.m_textCtrl_content.SetMaxLength(0)
-        bSizer6.Add(self.m_textCtrl_content, 1, wx.ALL | wx.EXPAND, 5)
-
-        bSizer7 = wx.BoxSizer(wx.HORIZONTAL)
-
-        self.m_panel3 = wx.Panel(self.m_panel1, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL)
-        bSizer71 = wx.BoxSizer(wx.HORIZONTAL)
-
-#        self.m_btn_save = buttons.GenBitmapTextButton(self.m_panel3, wx.ID_SAVE, co.GetMondrianBitmap(fn="disk"), u"保存")
-#        bSizer71.Add(self.m_btn_save, 0, wx.ALL, 0)
-
-        self.m_panel3.SetSizer(bSizer71)
-        self.m_panel3.Layout()
-        bSizer71.Fit(self.m_panel3)
-        bSizer7.Add(self.m_panel3, 1, wx.EXPAND | wx.ALL, 5)
-
-        self.m_btn_apply = buttons.GenBitmapTextButton(self.m_panel1, wx.ID_APPLY, co.GetMondrianBitmap(fn="accept"), u"应用")
-        #        self.m_btn_apply = wx.Button(self.m_panel1, wx.ID_APPLY, u"应用", wx.DefaultPosition, wx.DefaultSize, 0)
-        bSizer7.Add(self.m_btn_apply, 0, wx.ALL, 5)
-
-        if cls_TaskBarIcon and os.name == "nt":
-            # ubuntu 10.04 下点击这个图标时会报错,图标的菜单无法正常工作
-            # ubuntu 11.04 下这个图标总是无法显示
-            # 由于跨平台问题,暂时决定只在 windows 下显示快捷的任务栏图标
-            # 参见:http://stackoverflow.com/questions/7144756/wx-taskbaricon-on-ubuntu-11-04
-            self.m_btn_exit = buttons.GenBitmapTextButton(self.m_panel1, wx.ID_CLOSE, co.GetMondrianBitmap(fn="door"), u"隐藏")
-            #            self.m_btn_exit = wx.Button(self.m_panel1, wx.ID_CLOSE, u"隐藏", wx.DefaultPosition, wx.DefaultSize, 0)
-            bSizer7.Add(self.m_btn_exit, 0, wx.ALL, 5)
-
-        bSizer6.Add(bSizer7, 0, wx.EXPAND, 5)
-
-        bSizer4.Add(bSizer6, 1, wx.EXPAND, 5)
-
-        self.m_panel1.SetSizer(bSizer4)
-        self.m_panel1.Layout()
-        bSizer4.Fit(self.m_panel1)
-        bSizer1.Add(self.m_panel1, 1, wx.EXPAND | wx.ALL, 0)
-
-        self.SetSizer(bSizer1)
-        self.Layout()
-
-        self.Centre(wx.BOTH)
-
-        self.font_bold = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
-        self.font_bold.SetWeight(wx.BOLD)
-        self.font_normal = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
-        self.font_normal.SetWeight(wx.NORMAL)
-
-        self.font_mono = wx.Font(10, wx.ROMAN, wx.NORMAL, wx.NORMAL, faceName="Courier New")
-
-
-    def alert(self, title, msg):
-        dlg = wx.MessageDialog(None, msg, title, wx.OK | wx.ICON_WARNING)
-        dlg.ShowModal()
-        dlg.Destroy()
-
-
-
-class AboutHtml(wx.html.HtmlWindow):
-
-    def __init__(self, parent, id=-1, size=(480, 360)):
-
-        wx.html.HtmlWindow.__init__(self, parent, id, size=size)
-        if "gtk2" in wx.PlatformInfo:
-            self.SetStandardFonts()
-
-
-    def OnLinkClicked(self, link):
-
-        wx.LaunchDefaultBrowser(link.GetHref())
-
-
-class AboutBox(wx.Dialog):
-    u"""关于对话框
-
-    参考自:http://wiki.wxpython.org/wxPython%20by%20Example
-    """
-
-    def __init__(self, version=None, latest_stable_version=None):
-
-        wx.Dialog.__init__(self, None, -1, u"关于",
-                style=wx.DEFAULT_DIALOG_STYLE|wx.THICK_FRAME|wx.TAB_TRAVERSAL
-            )
-
-        update_version = u"正在检查新版本..."
-        if latest_stable_version:
-            cv = self.compareVersion(version, latest_stable_version)
-            if cv < 0:
-                update_version = u"更新的稳定版 v%s 已经发布!" % latest_stable_version
-            else:
-                update_version = u"当前版本已是最新版。"
-            
-
-        hwin = AboutHtml(self)
-        hwin.SetPage(u"""
-            <font size="9" color="#44474D"><b>SwitchHost!</b></font><br />
-            <font size="3" color="#44474D">%(version)s</font><br /><br />
-            <font size="3" color="#909090"><i>%(update_version)s</i></font><br />
-            <p>
-                本程序用于在多个 hosts 之间快速切换。
-            </p>
-            <p>
-                源码:<a href="https://github.com/oldj/SwitchHosts">https://github.com/oldj/SwitchHosts</a><br />
-                作者:<a href="http://oldj.net">oldj</a>
-            </p>
-        """ % {
-            "version": version,
-            "update_version": update_version,
-        })
-
-        btn = hwin.FindWindowById(wx.ID_OK)
-        irep = hwin.GetInternalRepresentation()
-        hwin.SetSize((irep.GetWidth() + 25, irep.GetHeight() + 30))
-        self.SetClientSize(hwin.GetSize())
-        self.CenterOnParent(wx.BOTH)
-        self.SetFocus()
-
-
-    def compareVersion(self, v1, v2):
-        u"""比较两个版本的大小
-        版本的格式形如:0.1.5.3456
-
-        如果 v1 > v2,则返回 1
-        如果 v1 = v2,则返回 0
-        如果 v1 < v2,则返回 -1
-        """
-
-        a1 = v1.split(".")
-        a2 = v2.split(".")
-
-        try:
-            a1 = [int(i) for i in a1]
-            a2 = [int(i) for i in a2]
-        except Exception:
-            return 0
-
-        len1 = len(a1)
-        len2 = len(a2)
-        l = min(len1, len2)
-        for i in range(l):
-            if a1[i] > a2[i]:
-                return 1
-            elif a1[i] < a2[i]:
-                return -1
-
-        if len1 > len2:
-            return 1
-        elif len1 < len2:
-            return -1
-        else:
-            return 0
-
-
-class Dlg_addHosts(wx.Dialog):
-
-    def __init__( self, parent ):
-        wx.Dialog.__init__(self, parent, id=wx.ID_ANY, title=wx.EmptyString, pos=wx.DefaultPosition,
-            size=wx.Size(400, 200), style=wx.DEFAULT_DIALOG_STYLE)
-
-        self.SetSizeHintsSz(wx.DefaultSize, wx.DefaultSize)
-
-        bSizer9 = wx.BoxSizer(wx.VERTICAL)
-
-        self.m_panel9 = wx.Panel(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL)
-        bSizer10 = wx.BoxSizer(wx.VERTICAL)
-
-        bSizer231 = wx.BoxSizer(wx.HORIZONTAL)
-
-        self.m_radioBtn_local = wx.RadioButton(self.m_panel9, wx.ID_ANY, u"本地方案", wx.DefaultPosition, wx.DefaultSize, 0)
-        self.m_radioBtn_local.SetValue(True)
-        bSizer231.Add(self.m_radioBtn_local, 0, wx.ALL, 5)
-
-        self.m_radioBtn_online = wx.RadioButton(self.m_panel9, wx.ID_ANY, u"在线方案", wx.DefaultPosition, wx.DefaultSize,
-            0)
-        bSizer231.Add(self.m_radioBtn_online, 0, wx.ALL, 5)
-
-        bSizer10.Add(bSizer231, 1, wx.EXPAND, 5)
-
-        bSizer111 = wx.BoxSizer(wx.HORIZONTAL)
-
-        self.m_staticText21 = wx.StaticText(self.m_panel9, wx.ID_ANY, u"方案名:", wx.DefaultPosition, wx.Size(60, -1), 0)
-        self.m_staticText21.Wrap(-1)
-        bSizer111.Add(self.m_staticText21, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
-
-        self.m_textCtrl_title = wx.TextCtrl(self.m_panel9, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize
-            , 0)
-        self.m_textCtrl_title.SetMaxLength(32)
-        self.m_textCtrl_title.SetToolTipString(u"在这儿输入方案名称。")
-
-        bSizer111.Add(self.m_textCtrl_title, 1, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
-
-        bSizer10.Add(bSizer111, 1, wx.EXPAND, 5)
-
-        bSizer1612 = wx.BoxSizer(wx.HORIZONTAL)
-
-        self.m_staticText512 = wx.StaticText(self.m_panel9, wx.ID_ANY, u"URL:", wx.DefaultPosition, wx.Size(60, -1), 0)
-        self.m_staticText512.Wrap(-1)
-        bSizer1612.Add(self.m_staticText512, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
-
-        self.m_textCtrl_url = wx.TextCtrl(self.m_panel9, wx.ID_ANY, u"http://", wx.DefaultPosition, wx.DefaultSize, 0)
-        self.m_textCtrl_url.SetMaxLength(1024)
-        self.m_textCtrl_url.Enable(False)
-        self.m_textCtrl_url.SetToolTipString(u"在这儿输入方案的url地址,如:\nhttp://192.168.1.100/hosts/sample.hosts 。")
-
-        bSizer1612.Add(self.m_textCtrl_url, 1, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
-
-        bSizer10.Add(bSizer1612, 1, wx.EXPAND, 5)
-
-        self.m_panel9.SetSizer(bSizer10)
-        self.m_panel9.Layout()
-        bSizer10.Fit(self.m_panel9)
-        bSizer9.Add(self.m_panel9, 2, wx.EXPAND | wx.ALL, 5)
-
-        self.m_staticline211 = wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL)
-        bSizer9.Add(self.m_staticline211, 0, wx.EXPAND | wx.ALL, 5)
-
-        m_sdbSizer1 = wx.StdDialogButtonSizer()
-        self.m_sdbSizer1OK = wx.Button(self, wx.ID_OK)
-        m_sdbSizer1.AddButton(self.m_sdbSizer1OK)
-        self.m_sdbSizer1Cancel = wx.Button(self, wx.ID_CANCEL)
-        m_sdbSizer1.AddButton(self.m_sdbSizer1Cancel)
-        m_sdbSizer1.Realize();
-        bSizer9.Add(m_sdbSizer1, 1, wx.EXPAND, 5)
-
-        self.SetSizer(bSizer9)
-        self.Layout()
-
-        self.Centre(wx.BOTH)
-
-        self.__binds()
-
-
-    def __del__( self ):
-        pass
-
-
-    def __binds(self):
-
-        self.Bind(wx.EVT_RADIOBUTTON, self.switchToLocal, self.m_radioBtn_local)
-        self.Bind(wx.EVT_RADIOBUTTON, self.switchToOnline, self.m_radioBtn_online)
-
-
-    def switchToLocal(self, event):
-
-#        print("local!")
-        self.m_textCtrl_url.Enabled = False
-
-
-    def switchToOnline(self, event):
-
-#        print("online!")
-        self.m_textCtrl_url.Enabled = True
-

+ 0 - 110
legacy/v1/xrc/main.xrc

@@ -1,110 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
-<resource xmlns="http://www.wxwindows.org/wxxrc" version="2.3.0.1">
-	<object class="wxFrame" name="MyFrame1">
-		<style>wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL</style>
-		<size>640,480</size>
-		<title></title>
-		<centered>1</centered>
-		<object class="wxMenuBar" name="m_menubar1">
-			<label>MyMenuBar</label>
-			<object class="wxMenu" name="m_menu1">
-				<label>文件(_F)</label>
-				<object class="wxMenuItem" name="m_menuItem_exit">
-					<label>退出(_X)</label>
-					<help></help>
-				</object>
-			</object>
-			<object class="wxMenu" name="m_menu2">
-				<label>帮助(_H)</label>
-				<object class="wxMenuItem" name="m_menuItem_about">
-					<label>关于(_A)</label>
-					<help></help>
-				</object>
-			</object>
-		</object>
-		<object class="wxPanel" name="m_panel1">
-			<style>wxTAB_TRAVERSAL</style>
-			<object class="wxBoxSizer">
-				<orient>wxHORIZONTAL</orient>
-				<object class="sizeritem">
-					<option>0</option>
-					<flag>wxEXPAND</flag>
-					<border>5</border>
-					<object class="wxBoxSizer">
-						<orient>wxVERTICAL</orient>
-						<object class="sizeritem">
-							<option>0</option>
-							<flag>wxALL</flag>
-							<border>5</border>
-							<object class="wxListBox" name="m_listBox2">
-								<size>-1,320</size>
-								<content />
-							</object>
-						</object>
-					</object>
-				</object>
-				<object class="sizeritem">
-					<option>1</option>
-					<flag>wxEXPAND</flag>
-					<border>5</border>
-					<object class="wxBoxSizer">
-						<orient>wxVERTICAL</orient>
-						<object class="sizeritem">
-							<option>1</option>
-							<flag>wxALL|wxEXPAND</flag>
-							<border>5</border>
-							<object class="wxTextCtrl" name="m_textCtrl1">
-								<style>wxTE_MULTILINE</style>
-								<value></value>
-								<maxlength>0</maxlength>
-							</object>
-						</object>
-						<object class="sizeritem">
-							<option>0</option>
-							<flag>wxEXPAND</flag>
-							<border>5</border>
-							<object class="wxBoxSizer">
-								<orient>wxHORIZONTAL</orient>
-								<object class="sizeritem">
-									<option>0</option>
-									<flag>wxALL</flag>
-									<border>5</border>
-									<object class="wxButton" name="m_btn_save">
-										<label>保存</label>
-										<default>0</default>
-									</object>
-								</object>
-								<object class="sizeritem">
-									<option>0</option>
-									<flag>wxALL</flag>
-									<border>5</border>
-									<object class="wxButton" name="m_btn_cancel">
-										<label>取消</label>
-										<default>0</default>
-									</object>
-								</object>
-								<object class="sizeritem">
-									<option>1</option>
-									<flag>wxEXPAND | wxALL</flag>
-									<border>5</border>
-									<object class="wxPanel" name="m_panel3">
-										<style>wxTAB_TRAVERSAL</style>
-									</object>
-								</object>
-								<object class="sizeritem">
-									<option>0</option>
-									<flag>wxALL</flag>
-									<border>5</border>
-									<object class="wxButton" name="m_btn_apply">
-										<label>切换</label>
-										<default>0</default>
-									</object>
-								</object>
-							</object>
-						</object>
-					</object>
-				</object>
-			</object>
-		</object>
-	</object>
-</resource>

+ 0 - 27
legacy/v1/xrc/option_frame.xrc

@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
-<resource xmlns="http://www.wxwindows.org/wxxrc" version="2.3.0.1">
-	<object class="wxFrame" name="MyFrame1">
-		<style>wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL</style>
-		<size>500,300</size>
-		<title></title>
-		<centered>1</centered>
-		<object class="wxBoxSizer">
-			<orient>wxVERTICAL</orient>
-			<object class="sizeritem">
-				<option>1</option>
-				<flag>wxEXPAND | wxALL</flag>
-				<border>5</border>
-				<object class="wxNotebook" name="m_notebook1" />
-			</object>
-			<object class="sizeritem">
-				<option>0</option>
-				<flag>wxALL</flag>
-				<border>5</border>
-				<object class="wxButton" name="m_button5">
-					<label>MyButton</label>
-					<default>0</default>
-				</object>
-			</object>
-		</object>
-	</object>
-</resource>

+ 0 - 122
legacy/v2/README.md

@@ -1,122 +0,0 @@
-#SwitchHosts!
-
- * Author: oldj
- * Email: [email protected]
- * Blog: http://oldj.net/
- * Source: https://github.com/oldj/SwitchHosts
- * Homepage: http://oldj.github.com/SwitchHosts/
- * Latest Stable: 0.2.2.1801
-
-
-这是一个用于快速切换 hosts 文件的小程序,基于 Python 和 wxPython 开发。
-
-
-##功能特性:
-
- * 支持Common Host文件,切换到任意环境都将生效的host --- charlestang
- * 快速切换 hosts
- * 跨平台(基于 wxPython)
- * hosts 文件语法高亮
- * 可为不同的 hosts 方案设置不同的图标
- * 切换 hosts 方案时浮出窗口提示
- * 支持在线 hosts 方案
- * 方案档案可导入/导出
-
-
-##下载地址:
-
-你可以直接下载源码到本地运行或编辑,或者在下面下载可执行版本:
-
- * [SwitchHosts! 下载](http://pan.baidu.com/share/link?shareid=150951&uk=3607385901)
-
-
-##程序截图:
-
-以下为本程序的运行截图。
-
-###Windows
-
-![程序主界面](https://github.com/oldj/SwitchHosts/blob/master/screenshots/7.png?raw=true)
-
-*程序主界面*
-
-
-![系统托盘菜单](https://github.com/oldj/SwitchHosts/blob/master/screenshots/2.png?raw=true)
-
-*系统托盘菜单*
-
-###Mac
-
-![程序主界面](https://github.com/oldj/SwitchHosts/blob/master/screenshots/6.png?raw=true)
-
-*程序主界面*
-
-![系统托盘菜单](https://github.com/oldj/SwitchHosts/blob/master/screenshots/4.png?raw=true)
-
-*系统托盘菜单*
-
-##更新历史:
-
- - 2013-02-06 解决Linux/Mac下没有修改系统hosts文件权限的问题。
- - 2012-12-27 启动时检查是否为单一实例,禁止同时运行多个实例。
- - 2012-11-16 接受 @charlestang 网友的 pull request,同时参考了 @allenm 的修改,实现了 Common Hosts 功能。
- - 2012-11-09 简单优化:Common Hosts 不允许删除,不允许“切换到”,将右键菜单相关条目禁用,允许更换图标颜色。修复新增在线方案时,url 框默认禁用的小 bug。
- - 2012-10-09 增加 hosts 方案拖拽排序功能。
- - 2012-10-05 修复在中文目录下程序无法正常启动的问题。
- - 2012-09-30 初步完成 0.2.0 版。
- - 2011-12-14 允许输入超长的 hosts 方案。
- - 2011-10-09 发布 0.1.6 版,修复若干 bug,增加自动检查最新版本的功能。
- - 2011-09-29 发布 0.1.5 版,新增 hosts 内容语法高亮。
- - 2011-09-28 发布 0.1.4 版,新增“添加”、“删除”按钮;hosts 内容修改后自动保存;修复若干 bug。
- - 2011-09-19 发布 0.1.3 版,修复若干 bug。
- - 2011-09-15 发布 0.1.2 版,添加主面板,可以在主面板上对 hosts 进行增加、删除、编辑、重命名等操作。
- - 2011-09-02 发布 0.1.0 版,完成基本功能。
-
-##开发计划:
-
- - 增加选项配置界面
- - 自动监测当前使用的 hosts,如果有修改马上刷新
- - 可选择是否修改注册表以便让 IE 浏览器在修改 hosts 后马上更新
- - 增加快捷键
- - 备份系统初始 hosts
-
-
-##已知问题
-
- - Hosts 编辑器中输入法有问题。
-
-
-##打包方法
-
-您可以使用 [py2exe](http://www.py2exe.org/)(Windows 平台)或 [pyInstaller](http://www.pyinstaller.org/)(Windows/Linux/Mac 平台)将本项目打包制作成可执行文件。推荐使用 *pyInstaller*,因为它在各大主流系统中都可使用。另外,感谢网友_Yan Jian_的提醒,如果使用 py2exe 打包,则需要先将源码中的 `__file__` 替换为 `.`。
- 
-###使用 pyInstaller 打包
- 
-使用 pyInstaller 打包本程序非常简单,大致需要以下步骤:
-
- - 去 [pyInstaller](http://www.pyinstaller.org/) 官方主页下载最新版本的 pyIntaller,比如目前为 2.0 版
- - 将下载的 pyInstaller 解压,比如解压至 `D:\tools\pyinstaller-2.0` 目录
- - 打开 CMD 终端,转到 pyInstaller 所在目录,输入打包命令
-
-如果你的源码位于目录`D:\studio\SwitchHosts`,则打包命令形如:
- 
-    D:\tools\pyinstaller-2.0> pyinstaller.py -w -F --icon=D:\studio\SwitchHosts\src\img\logo.ico --name=SwitchHosts --out=D:\studio\SwitchHosts\dist D:\studio\SwitchHosts\src\SwitchHosts.py
- 
-执行完成之后,即可在`D:\studio\SwitchHosts\dist`目录下看到打包成功的可执行文件。
- 
-
-###使用 py2app 打包
-
-Mac 下可以使用 py2app 将本程序打包为一个 APP,在终端中进入程序的`src`目录,运行以下命令:
-
-    $rm -rf dist build
-    $python setup.py py2app
-
-如果一切顺利,即可在当前目录下的`dist/`目录下看到打包完成的`SwitchHosts!.app`。
-
-
-##版权及致谢:
-
- 本程序的 Windows 版和 Mac 分别使用了 [ToasterBox](http://xoomer.virgilio.it/infinity77/main/ToasterBox.html) 和 [gntp](https://github.com/kfdm/gntp) 作为浮出提示解决方案,在此对作者的工作表示感谢!
-
- 本程序完全免费,并基于 LGPL 协议开源。

二進制
legacy/v2/screenshots/1.png


二進制
legacy/v2/screenshots/2.png


二進制
legacy/v2/screenshots/3.png


二進制
legacy/v2/screenshots/4.png


二進制
legacy/v2/screenshots/5.png


二進制
legacy/v2/screenshots/6.png


二進制
legacy/v2/screenshots/7.png


+ 0 - 129
legacy/v2/src/SwitchHosts.py

@@ -1,129 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# author: oldj
-# blog: http://oldj.net
-# email: [email protected]
-#
-
-import os
-import time
-import wx
-import libs.common_operations as co
-from libs.MainFrame import MainFrame
-from libs.VERSION import VERSION as sVer
-
-
-class SwitchHostsApp(object):
-    VERSION = sVer
-
-    def __init__(self):
-
-        sys_type = co.getSystemType()
-
-        self.pwd = os.path.abspath(os.path.split(__file__)[0])
-        self.user_home = os.path.expanduser("~")
-        self.restart = False
-        self.taskbar_icon = None
-
-        self.sys_type = sys_type
-        if sys_type != "win":
-            self.working_path = os.path.join(self.user_home, ".SwitchHosts")
-        else:
-            self.working_path = self.pwd
-
-    def run(self):
-
-        # instance_name = None
-
-        while True:
-
-            app = wx.App(False)
-
-            instance_name = "%s-%s" % (app.GetAppName(), wx.GetUserId())
-            instance_checker = wx.SingleInstanceChecker(instance_name, self.working_path)
-            if instance_checker.IsAnotherRunning():
-                dlg = wx.MessageDialog(
-                    None,
-                    u"SwitchHosts! 已经在运行了或上次没有正常退出,要重新打开吗?",
-                    u"SwitchHosts!",
-                    wx.YES_NO | wx.ICON_QUESTION
-                )
-                ret_code = dlg.ShowModal()
-                if ret_code != wx.ID_YES:
-                    dlg.Destroy()
-                    return
-
-                dlg.Destroy()
-
-            frame = MainFrame(
-                mainjob=self,
-                instance_name=instance_name,
-                size=(640, 480),
-                version=self.VERSION,
-                working_path=self.working_path,
-                taskbar_icon=self.taskbar_icon,
-            )
-            self.restart = False
-            self.taskbar_icon = None
-
-            self.app = app
-            self.frame = frame
-            self.bindEvents()
-
-            frame.Centre()
-            frame.Show()
-            app.MainLoop()
-            app.Destroy()
-
-            time.sleep(0.1)
-            if not self.restart:
-                break
-
-    def bindEvents(self):
-        u"""绑定各种事件"""
-
-        # self.app.Bind(wx.EVT_TASKBAR_LEFT_DCLICK, self.OnTaskBarActivate)
-        # self.app.Bind(wx.EVT_MENU, self.OnTaskBarActivate, id=self.TBMENU_RESTORE)
-        # self.app.Bind(wx.EVT_MENU, self.OnTaskBarClose, id=self.TBMENU_CLOSE)
-        self.app.Bind(wx.EVT_ACTIVATE_APP, self.OnActivate)
-
-    def OnTaskBarActivate(self, event):
-        u""""""
-
-        if self.frame.IsIconized():
-            self.frame.Iconize(False)
-        if not self.frame.IsShown():
-            self.frame.Show(True)
-        self.frame.Raise()
-
-    def OnActivate(self, event):
-        u"""
-        Mac 下,程序最小化到 dock 栏后,点击图标默认不会恢复窗口,需要监听事件
-        参见:http://wxpython-users.1045709.n5.nabble.com/OS-X-issue-raising-minimized-frame-td2371601.html
-        """
-
-        if self.sys_type == "mac" and event.GetActive():
-            if self.frame.IsIconized():
-                self.frame.Iconize(False)
-            if not self.frame.IsShown():
-                self.frame.Show(True)
-            self.frame.Raise()
-        event.Skip()
-
-    def OnTaskBarClose(self, event):
-        u""""""
-        wx.CallAfter(self.frame.Close)
-
-    def toRestart(self, taskbar_icon):
-
-        self.restart = True
-        self.taskbar_icon = taskbar_icon
-
-
-def main():
-    sh = SwitchHostsApp()
-    sh.run()
-
-
-if __name__ == "__main__":
-    main()

二進制
legacy/v2/src/img/logo.icns


二進制
legacy/v2/src/img/logo.ico


二進制
legacy/v2/src/img/logo.png


+ 0 - 53
legacy/v2/src/libs/BackThreads.py

@@ -1,53 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# author: oldj
-# blog: http://oldj.net
-# email: [email protected]
-#
-
-import time
-import random
-import threading
-import traceback
-
-class BackThreads(threading.Thread):
-
-    def __init__(self, task_qu, *kw, **kw2):
-
-        super(BackThreads, self).__init__(*kw, **kw2)
-
-        self.task_qu = task_qu
-        self.time_to_quit = threading.Event()
-        self.time_to_quit.clear()
-
-
-    def run(self):
-
-        time.sleep(0.5 + random.random())
-
-        while True:
-            if self.time_to_quit.isSet():
-                break
-
-            if not self.task_qu.empty():
-                try:
-                    tasks = self.task_qu.get(block=False)
-                    if callable(tasks):
-                        tasks = [tasks]
-
-                    if type(tasks) in (list, tuple):
-                        for task in tasks:
-                            if callable(task):
-                                task()
-                except Exception:
-                    print(traceback.format_exc())
-
-            time.sleep(0.1)
-
-
-    def stop(self):
-        self.time_to_quit.set()
-
-
-
-

+ 0 - 271
legacy/v2/src/libs/Hosts.py

@@ -1,271 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# author: oldj
-# blog: http://oldj.net
-# email: [email protected]
-#
-
-import os
-import simplejson as json
-import urllib
-import time
-import datetime
-import common_operations as co
-
-
-class Hosts(object):
-
-    flag = "#@SwitchHosts!"
-    old_flag = "#@SwitchHost!"
-
-    def __init__(self, path, is_origin=False, title=None, url=None, is_common=False):
-
-        self.path = path
-        self.is_origin = is_origin
-        self.is_common = is_common
-        self.url = url
-        self.is_online = True if url else False
-        self.is_loading = False
-        self.last_fetch_dt = None
-        self.last_save_time = None
-        self.__title = title
-        self.__content = None
-        self.tree_item_id = None
-        self.taskbar_id = None
-        self.icon_idx = 0
-
-        self.getContent()
-
-    @property
-    def title(self):
-
-        return self.__title or self.filename or u"未命名"
-
-    @title.setter
-    def title(self, value):
-        self.__title = value
-
-    def getContentFromUrl(self, progress_dlg):
-
-        co.log("fetch '%s'.." % self.url)
-
-        if co.httpExists(self.url):
-
-            if progress_dlg:
-                progress_dlg.Update(10),
-            try:
-                cnt = []
-                up = 10
-                url_o = urllib.urlopen(self.url)
-                while True:
-                    c = url_o.read(1024)
-                    if not c:
-                        break
-                    cnt.append(c)
-                    up += 1
-                    if up < 60:
-                        if progress_dlg:
-                            progress_dlg.Update(up),
-                cnt = "".join(cnt)
-                if progress_dlg:
-                    progress_dlg.Update(60),
-            except Exception:
-                co.debugErr()
-                return ""
-
-            self.last_fetch_dt = datetime.datetime.now()
-
-        else:
-            cnt = u"### URL无法访问! ###".encode("utf-8")
-
-        return cnt
-
-    def getContentOnce(self):
-
-        if self.is_online and not self.last_fetch_dt:
-            self.getContent(force=True)
-
-    def getContent(self, force=False, progress_dlg=None):
-
-        self.is_loading = True
-        c = ""
-        if self.is_online:
-            if force:
-                c = self.getContentFromUrl(progress_dlg)
-
-        elif os.path.isfile(self.path):
-            c = open(self.path, "rb").read().strip()
-
-        if c:
-            c = self.tryToDecode(c)
-            a = c.replace("\r", "").split("\n")
-            if a[0].startswith(self.flag):
-                # 首行是配置信息
-                self.parseConfigs(a[0][len(self.flag):])
-                c = "\n".join(a[1:])
-            elif a[0].startswith(self.old_flag):
-                # 兼容老的格式
-                # 首行是配置信息
-                self.parseConfigs(a[0][len(self.old_flag):])
-                c = "\n".join(a[1:])
-
-        self.content = c
-        self.is_loading = False
-
-    def tryToDecode(self, s):
-
-        try:
-            return co.decode(s)
-        except Exception:
-            return u"### 解码错误!###"
-
-    @property
-    def content(self):
-
-        c = self.__content or ""
-        if c and not c.endswith("\n"):
-            # 自动给 hosts 内容最后一行添加一个换行
-            c = "%s\n" % c
-        return c
-
-    @content.setter
-    def content(self, value):
-        self.__content = value.replace("\r", "")
-
-    def parseConfigs(self, json_str=None):
-
-        try:
-            cfg = json.loads(json_str)
-        except Exception:
-            co.log(json_str)
-            co.debugErr()
-            return
-
-        if type(cfg) != dict:
-            return
-
-        if self.is_origin:
-            pass
-        elif cfg.get("title"):
-            if not self.title or not self.is_online:
-                self.title = cfg["title"]
-
-        if cfg.get("url"):
-            if not self.is_online and not self.is_origin:
-                self.url = cfg["url"]
-                self.is_online = True
-#                self.getContent()
-
-        if cfg.get("icon_idx") is not None:
-            icon_idx = cfg.get("icon_idx")
-            if type(icon_idx) not in (int, long) or \
-                icon_idx < 0 or icon_idx > len(co.ICONS):
-                icon_idx = 0
-
-            self.icon_idx = icon_idx
-
-    @property
-    def filename(self):
-
-        sep = "/" if self.is_online else os.sep
-        fn = self.path.split(sep)[-1]
-
-        return fn
-
-    @property
-    def full_content(self):
-
-        cnt_for_save = [self.configLine()] + self.content.split("\n")
-        return os.linesep.join(cnt_for_save).encode("utf-8")
-
-    def configLine(self):
-        u"""生成配置信息的注释行"""
-
-        return "%s %s" % (self.flag, json.dumps({
-                                "title": self.title,
-                                "url": self.url,
-                                "icon_idx": self.icon_idx,
-                                }))
-
-    def contentWithCommon(self, common=None):
-        u"""返回添加了公共内容的hosts"""
-
-        if not common:
-            return self.full_content
-
-        return os.linesep.join([
-            self.configLine(),
-            common.content,
-            "# %s" % ("-" * 50),
-            self.content
-        ]).encode("utf-8")
-
-    def makeBackupHostsName(self, path):
-
-        return "%s.backup_switchhosts" % path
-
-    def tryToBackupOriginalHosts(self, path, backup_name, sudo_password=None):
-        u"""尝试备份原始 hosts"""
-
-        if os.path.isfile(backup_name) or not os.path.isfile(path):
-            return
-
-        if sudo_password:
-            # 新建备份文件
-            cmd = [
-                "echo '%s' | sudo -S touch %s" % (sudo_password, backup_name),
-                "echo '%s' | sudo -S chmod %s %s" % (sudo_password, 766, backup_name),
-            ]
-            os.popen(";".join(cmd))
-
-        # 尝试保存
-        open(backup_name, "w").write(open(path).read())
-
-    def save(self, path=None, common=None, sudo_password=None):
-
-        from stat import ST_MODE
-        # fn_stat = 744
-
-        if self.last_save_time:
-            time_delta = time.time() - self.last_save_time
-            if time_delta < 0.001:
-                pass
-
-        path = path or self.path
-        path = path.encode(co.getLocalEncoding())
-        fn_stat = None
-        backup_name = None
-
-        if os.path.isfile(path):
-            fn_stat = oct(os.stat(path)[ST_MODE])[-3:]
-            backup_name = self.makeBackupHostsName(path)
-            self.tryToBackupOriginalHosts(path, backup_name, sudo_password)
-
-        if sudo_password:
-            # 先修改系统hosts文件的权限
-            cmd = [
-                "echo '%s' | sudo -S chmod %s %s" % (sudo_password, 766, path),
-                ]
-            os.popen(";".join(cmd))
-
-        try:
-            # 写系统hosts
-            open(path, "w").write(self.contentWithCommon(common))
-
-        finally:
-            if sudo_password and fn_stat and backup_name:
-                # 再将系统hosts文件的权限改回来
-                cmd = [
-                    "echo '%s' | sudo -S chmod %s %s" % (sudo_password, fn_stat, path),
-                    "echo '%s' | sudo -S chmod %s %s" % (sudo_password, fn_stat, backup_name),
-                ]
-                os.popen(";".join(cmd))
-
-        self.last_save_time = time.time()
-
-        return True
-
-    def remove(self):
-
-        if os.path.isfile(self.path):
-            os.remove(self.path)

+ 0 - 112
legacy/v2/src/libs/HostsCtrl.py

@@ -1,112 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# author: oldj
-# blog: http://oldj.net
-# email: [email protected]
-#
-
-import wx
-from wx import stc
-#import keyword
-
-if wx.Platform == '__WXMSW__':
-    faces = {
-        'times': 'Times New Roman',
-        'mono': 'Courier New',
-        'helv': 'Courier New',
-        'other': 'Courier New',
-        'size': 10,
-        'size2': 10,
-        }
-elif wx.Platform == '__WXMAC__':
-    faces = {
-        'times': 'Times New Roman',
-        'mono': 'Monaco',
-        'helv': 'Monaco',
-        'other': 'Monaco',
-        'size': 12,
-        'size2': 12,
-        }
-else:
-    faces = {
-        'times': 'Times',
-        'mono': 'Courier New',
-        'helv': 'Helvetica',
-        'other': 'Courier New',
-        'size': 12,
-        'size2': 12,
-        }
-
-
-class HostsCtrl(stc.StyledTextCtrl):
-
-    def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
-                 size=wx.DefaultSize, style=0):
-
-        stc.StyledTextCtrl.__init__(self, parent, id, pos, size, style)
-
-        self.SetReadOnly(False)
-        self.SetLexer(stc.STC_LEX_CONF)
-#        self.SetKeyWords(0, " ".join(keyword.kwlist))
-
-#        self.SetProperty("fold", "1")
-#        self.SetProperty("tab.timmy.whinge.level", "1")
-
-        self.SetViewWhiteSpace(False)
-        self.SetEdgeColumn(80)
-        self.SetMarginWidth(0, 0)
-        self.SetMarginWidth(1, 5)
-        self.SetMarginWidth(2, 5)
-        self.SetScrollWidth(800)
-
-        # Global default styles for all languages
-        self.StyleSetSpec(stc.STC_STYLE_DEFAULT, "face:%(helv)s,size:%(size)d" % faces)
-        self.StyleClearAll()  # Reset all to be like the default
-
-        # Global default styles for all languages
-        self.StyleSetSpec(stc.STC_STYLE_DEFAULT, "face:%(helv)s,size:%(size)d" % faces)
-        self.StyleSetSpec(stc.STC_STYLE_CONTROLCHAR, "face:%(other)s" % faces)
-        self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT, "fore:#FFFFFF,back:#0000FF,bold")
-        self.StyleSetSpec(stc.STC_STYLE_BRACEBAD, "fore:#000000,back:#FF0000,bold")
-
-        # Default
-        self.StyleSetSpec(stc.STC_P_DEFAULT, "fore:#000000,face:%(helv)s,size:%(size)d" % faces)
-        # Comments
-        self.StyleSetSpec(stc.STC_P_COMMENTLINE, "fore:#007F00,face:%(other)s,size:%(size)d" % faces)
-        # Number
-        self.StyleSetSpec(stc.STC_P_NUMBER, "fore:#007F7F,size:%(size)d" % faces)
-        # String
-        self.StyleSetSpec(stc.STC_P_STRING, "fore:#00007F,face:%(helv)s,size:%(size)d" % faces)
-        # Single quoted string
-        self.StyleSetSpec(stc.STC_P_CHARACTER, "fore:#7F007F,face:%(helv)s,size:%(size)d" % faces)
-        # Keyword
-#        self.StyleSetSpec(stc.STC_P_WORD, "fore:#00007F,bold,size:%(size)d" % faces)
-        # Triple quotes
-#        self.StyleSetSpec(stc.STC_P_TRIPLE, "fore:#7F0000,size:%(size)d" % faces)
-        # Triple double quotes
-#        self.StyleSetSpec(stc.STC_P_TRIPLEDOUBLE, "fore:#7F0000,size:%(size)d" % faces)
-        # Class name definition
-        self.StyleSetSpec(stc.STC_P_CLASSNAME, "fore:#0000FF,bold,underline,size:%(size)d" % faces)
-        # Function or method name definition
-#        self.StyleSetSpec(stc.STC_P_DEFNAME, "fore:#007F7F,bold,size:%(size)d" % faces)
-        # Operators
-#        self.StyleSetSpec(stc.STC_P_OPERATOR, "bold,size:%(size)d" % faces)
-        # Identifiers
-#        self.StyleSetSpec(stc.STC_P_IDENTIFIER, "fore:#000000,face:%(helv)s,size:%(size)d" % faces)
-        # Comment-blocks
-        self.StyleSetSpec(stc.STC_P_COMMENTBLOCK, "fore:#7F7F7F,size:%(size)d" % faces)
-        # End of line where string is not closed
-        self.StyleSetSpec(stc.STC_P_STRINGEOL, "fore:#000000,face:%(mono)s,back:#E0C0E0,eol,size:%(size)d" % faces)
-
-        self.SetCaretForeground("BLUE")
-
-
-    def SetValue(self, value):
-    #        if wx.USE_UNICODE:
-    #            value = value.decode('utf-8')
-
-    #        self.SetReadOnly(False)
-        self.SetText(value)
-
-        #        self.SetReadOnly(True)
-

+ 0 - 1262
legacy/v2/src/libs/MainFrame.py

@@ -1,1262 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# author: oldj
-# blog: http://oldj.net
-# email: [email protected]
-#
-
-import os
-import sys
-import glob
-import simplejson as json
-import wx
-from wx import stc
-import ui
-import urllib
-import re
-import traceback
-import random
-import Queue
-import time
-from Hosts import Hosts
-from TaskbarIcon import TaskBarIcon
-from BackThreads import BackThreads
-import common_operations as co
-import lang
-
-sys_type = co.getSystemType()
-
-if sys_type == "linux":
-    # Linux
-    try:
-        import pynotify
-	pynotify.init("SwitchHosts!")
-    except ImportError:
-        pynotify = None
-elif sys_type == "mac":
-    # Mac
-    import gntp.notifier
-
-    growl = gntp.notifier.GrowlNotifier(
-        applicationName="SwitchHosts!",
-        notifications=["New Updates", "New Messages"],
-        defaultNotifications=["New Messages"],
-        hostname="127.0.0.1",  # Defaults to localhost
-        # password="" # Defaults to a blank password
-    )
-    try:
-        growl.register()
-        has_growl = True
-    except Exception:
-        has_growl = False
-
-
-class MainFrame(ui.Frame):
-
-    def __init__(self, mainjob, instance_name,
-        parent=None, id=wx.ID_ANY, title=None, pos=wx.DefaultPosition,
-        size=wx.DefaultSize,
-        style=wx.DEFAULT_FRAME_STYLE,
-        version=None, working_path=None,
-        taskbar_icon=None,
-    ):
-        u""""""
-
-        self.mainjob = mainjob
-        self.instance_name = instance_name
-        self.version = version
-        self.default_title = "SwitchHosts! %s" % self.version
-        self.sudo_password = ""
-        self.is_running = True
-
-        ui.Frame.__init__(self, parent, id,
-            title or self.default_title, pos, size, style)
-
-        self.taskbar_icon = taskbar_icon or TaskBarIcon(self)
-        if taskbar_icon:
-            self.taskbar_icon.setMainFrame(self)
-
-        self.latest_stable_version = "0"
-        self.__sys_hosts_path = None
-        self.local_encoding = co.getLocalEncoding()
-        self.sys_type = co.getSystemType()
-
-        if working_path:
-            working_path = working_path.decode(self.local_encoding)
-            self.working_path = working_path
-            self.configs_path = os.path.join(self.working_path, "configs.json")
-            self.hosts_path = os.path.join(self.working_path, "hosts")
-            if not os.path.isdir(self.hosts_path):
-                os.makedirs(self.hosts_path)
-
-        self.active_fn = os.path.join(self.working_path, ".active")
-        self.task_qu = Queue.Queue(4096)
-        self.startBackThreads(2)
-        self.makeHostsContextMenu()
-
-        self.init2()
-        self.initBind()
-
-        # self.task_qu.put(self.chkActive)
-
-    def init2(self):
-
-        self.showing_rnd_id = random.random()
-        self.is_switching_text = False
-        self.current_using_hosts = None
-        self.current_showing_hosts = None
-        self.current_tree_hosts = None
-        self.current_dragging_hosts = None
-        self.current_tree_item = None  # 当前选中的树无素
-
-        self.origin_hostses = []
-        self.common_hostses = []
-        self.hostses = []
-        self.fn_common_hosts = "COMMON.hosts"
-
-        self.configs = {}
-        self.loadConfigs()
-
-        common_host_file_path = os.path.join(self.hosts_path, self.fn_common_hosts)
-        if not os.path.isfile(common_host_file_path):
-            common_file = open(common_host_file_path, "w")
-            common_file.write("# common")
-            common_file.close()
-
-        hosts = Hosts(path=common_host_file_path, is_common=True)
-        self.addHosts(hosts)
-
-        self.getSystemHosts()
-        self.scanSavedHosts()
-
-        if not os.path.isdir(self.hosts_path):
-            os.makedirs(self.hosts_path)
-
-    def initBind(self):
-        u"""初始化时绑定事件"""
-
-        self.Bind(wx.EVT_CLOSE, self.OnClose)
-        self.Bind(wx.EVT_MENU, self.OnExit, id=wx.ID_EXIT)
-        self.Bind(wx.EVT_MENU, self.OnAbout, id=wx.ID_ABOUT)
-        self.Bind(wx.EVT_MENU, self.OnHomepage, self.m_menuItem_homepage)
-        self.Bind(wx.EVT_MENU, self.OnFeedback, self.m_menuItem_feedback)
-        self.Bind(wx.EVT_MENU, self.OnChkUpdate, self.m_menuItem_chkUpdate)
-        self.Bind(wx.EVT_MENU, self.OnNew, self.m_menuItem_new)
-        self.Bind(wx.EVT_MENU, self.OnDel, id=wx.ID_DELETE)
-        self.Bind(wx.EVT_MENU, self.OnApply, id=wx.ID_APPLY)
-        self.Bind(wx.EVT_MENU, self.OnEdit, id=wx.ID_EDIT)
-        self.Bind(wx.EVT_MENU, self.OnRefresh, id=wx.ID_REFRESH)
-        self.Bind(wx.EVT_MENU, self.OnExport, self.m_menuItem_export)
-        self.Bind(wx.EVT_MENU, self.OnImport, self.m_menuItem_import)
-        self.Bind(wx.EVT_MENU, self.OnDonate, self.m_menuItem_donate)
-        self.Bind(wx.EVT_BUTTON, self.OnNew, self.m_btn_add)
-        self.Bind(wx.EVT_BUTTON, self.OnApply, id=wx.ID_APPLY)
-        self.Bind(wx.EVT_BUTTON, self.OnDel, id=wx.ID_DELETE)
-        self.Bind(wx.EVT_BUTTON, self.OnRefresh, id=wx.ID_REFRESH)
-        self.Bind(wx.EVT_BUTTON, self.OnEdit, id=wx.ID_EDIT)
-        self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnTreeSelectionChange, self.m_tree)
-        self.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.OnTreeRClick, self.m_tree)
-        self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnTreeActive, self.m_tree)
-        self.Bind(wx.EVT_TREE_END_LABEL_EDIT, self.OnRenameEnd, self.m_tree)
-        self.Bind(wx.EVT_TREE_BEGIN_DRAG, self.OnTreeBeginDrag, self.m_tree)
-        self.Bind(wx.EVT_TREE_END_DRAG, self.OnTreeEndDrag, self.m_tree)
-        self.Bind(stc.EVT_STC_CHANGE, self.OnHostsChange, id=self.ID_HOSTS_TEXT)
-
-    def startBackThreads(self, count=1):
-
-        self.back_threads = []
-        for i in xrange(count):
-            t = BackThreads(task_qu=self.task_qu)
-            t.start()
-            self.back_threads.append(t)
-
-    def stopBackThreads(self):
-
-        for t in self.back_threads:
-            t.stop()
-
-    def makeHostsContextMenu(self):
-
-        self.hosts_item_menu = wx.Menu()
-        self.hosts_item_menu.Append(wx.ID_APPLY, u"切换到当前hosts")
-        self.hosts_item_menu.Append(wx.ID_EDIT, u"编辑")
-        self.hosts_item_menu.AppendMenu(-1, u"图标", self.makeSubIconMenu())
-
-        self.hosts_item_menu.AppendSeparator()
-        self.hosts_item_menu.Append(wx.ID_REFRESH, u"刷新")
-        self.hosts_item_menu.Append(wx.ID_DELETE, u"删除")
-
-    def makeSubIconMenu(self):
-        u"""生成图标子菜单"""
-
-        menu = wx.Menu()
-
-        def _f(i):
-            return lambda e: self.setHostsIcon(e, i)
-
-        icons_length = len(co.ICONS)
-        for i in range(icons_length):
-            item_id = wx.NewId()
-            mitem = wx.MenuItem(menu, item_id, u"图标#%d" % (i + 1))
-            mitem.SetBitmap(co.GetMondrianBitmap(i))
-            menu.AppendItem(mitem)
-
-            self.Bind(wx.EVT_MENU, _f(i), id=item_id)
-
-        return menu
-
-    def setHostsIcon(self, event=None, i=0):
-        u"""图标子菜单,点击动作的响应函数"""
-
-        hosts = self.current_showing_hosts
-        if not hosts:
-            return
-
-        hosts.icon_idx = i
-        self.updateHostsIcon(hosts)
-        hosts.save()
-
-    def scanSavedHosts(self):
-        u"""扫描目前保存的各个hosts"""
-
-        fns = glob.glob(os.path.join(self.hosts_path, "*.hosts"))
-        fns = [os.path.split(fn)[1] for fn in fns]
-        if self.fn_common_hosts in fns:
-            fns.remove(self.fn_common_hosts)
-
-        cfg_hostses = self.configs.get("hostses", [])
-        # 移除不存在的 hosts
-        tmp_hosts = []
-        for fn in cfg_hostses:
-            if fn in fns:
-                tmp_hosts.append(fn)
-        cfg_hostses = tmp_hosts
-
-        # 添加新的 hosts
-        for fn in fns:
-            if fn not in cfg_hostses:
-                cfg_hostses.append(fn)
-        self.configs["hostses"] = cfg_hostses
-        self.saveConfigs()
-
-        for fn in self.configs["hostses"]:
-            path = os.path.join(self.hosts_path, fn)
-            hosts = Hosts(path)
-            if hosts.content:
-                pass
-            self.addHosts(hosts)
-
-    def setHostsDir(self):
-        pass
-
-    @property
-    def sys_hosts_path(self):
-        u"""取得系统 hosts 文件的路径"""
-
-        if not self.__sys_hosts_path:
-
-            if os.name == "nt":
-                systemroot = os.environ.get("SYSTEMROOT", "C:\\Windows")
-                path = "%s\\System32\\drivers\\etc\\hosts" % systemroot
-            else:
-                path = "/etc/hosts"
-
-            self.__sys_hosts_path = path if os.path.isfile(path) else None
-
-        return self.__sys_hosts_path
-
-    def getSystemHosts(self):
-
-        path = self.sys_hosts_path
-        if path:
-            hosts = Hosts(path=path, title=lang.trans("origin_hosts"), is_origin=True)
-            self.origin_hostses = [hosts]
-            self.addHosts(hosts)
-            self.highLightHosts(hosts)
-            self.updateBtnStatus(hosts)
-
-    def showHosts(self, hosts):
-
-        self.showing_rnd_id = random.random()
-
-        content = hosts.content if not hosts.is_loading else "loading..."
-        self.is_switching_text = True
-        self.m_textCtrl_content.SetReadOnly(False)
-        self.m_textCtrl_content.SetValue(content)
-        self.m_textCtrl_content.SetReadOnly(not self.getHostsAttr(hosts, "is_content_edit_able"))
-        self.is_switching_text = False
-
-        if self.current_showing_hosts:
-            self.m_tree.SetItemBackgroundColour(self.current_showing_hosts.tree_item_id, None)
-        self.m_tree.SetItemBackgroundColour(hosts.tree_item_id, "#ccccff")
-
-        self.current_showing_hosts = hosts
-
-    def tryToShowHosts(self, hosts):
-
-        if hosts == self.current_showing_hosts:
-            self.showHosts(hosts)
-
-    def tryToSaveBySudoPassword(self, hosts, common_hosts):
-
-        if not self.sudo_password:
-            # 尝试获取sudo密码
-            pswd = None
-            dlg = wx.PasswordEntryDialog(None, u"请输入sudo密码:", u"需要管理员权限",
-                style=wx.OK|wx.CANCEL
-            )
-            if dlg.ShowModal() == wx.ID_OK:
-                pswd = dlg.GetValue().strip()
-
-            dlg.Destroy()
-
-            if not pswd:
-                return False
-
-            self.sudo_password = pswd
-
-        #尝试通过sudo密码保存
-        try:
-            hosts.save(path=self.sys_hosts_path, common=common_hosts,
-                sudo_password=self.sudo_password)
-            return True
-        except Exception:
-            print(traceback.format_exc())
-
-        return False
-
-    def useHosts(self, hosts):
-
-        if hosts.is_loading:
-            wx.MessageBox(u"当前 hosts 内容正在下载中,请稍后再试...")
-            return
-
-        msg = None
-        is_success = False
-        common_hosts = None
-
-        try:
-            for common_hosts in self.common_hostses:
-                if common_hosts.is_common:
-                    break
-
-            hosts.save(path=self.sys_hosts_path, common=common_hosts)
-            is_success = True
-
-        except Exception:
-
-            err = traceback.format_exc()
-            co.log(err)
-
-            if "Permission denied:" in err:
-                if sys_type in ("linux", "mac") and self.tryToSaveBySudoPassword(
-                    hosts, common_hosts
-                ):
-                    is_success = True
-                else:
-                    msg = u"切换 hosts 失败!\n没有修改 '%s' 的权限!" % self.sys_hosts_path
-
-            else:
-                msg = u"切换 hosts 失败!\n\n%s" % err
-
-            if msg and self.current_showing_hosts:
-                wx.MessageBox(msg, caption=u"出错啦!")
-                return
-
-        if is_success:
-
-            if len(self.origin_hostses) > 0:
-                self.origin_hostses[0].icon_idx = hosts.icon_idx
-            self.notify(msg=u"hosts 已切换为「%s」。" % hosts.title, title=u"hosts 切换成功")
-
-            self.tryToFlushDNS()
-            self.highLightHosts(hosts)
-
-    def tryToFlushDNS(self):
-        u"""尝试更新 DNS 缓存
-        @see http://cnzhx.net/blog/how-to-flush-dns-cache-in-linux-windows-mac/
-        """
-
-        try:
-            if self.sys_type == "mac":
-                cmd = "dscacheutil -flushcache"
-                os.popen(cmd)
-
-            elif self.sys_type == "win":
-                cmd = "ipconfig /flushdns"
-                os.popen(cmd)
-
-            elif self.sys_type == "linux":
-                cmd = "service nscd restart"
-                os.popen(cmd)
-
-        except Exception:
-            pass
-
-    def highLightHosts(self, hosts):
-        u"""将切换的host文件高亮显示"""
-
-        self.m_tree.SelectItem(hosts.tree_item_id)
-
-        if self.current_using_hosts:
-            self.m_tree.SetItemBold(self.current_using_hosts.tree_item_id, bold=False)
-        self.m_tree.SetItemBold(hosts.tree_item_id)
-
-        self.showHosts(hosts)
-        self.current_using_hosts = hosts
-        self.updateIcon()
-
-    def updateIcon(self):
-
-        co.log("update icon")
-        if self.current_using_hosts:
-            if len(self.origin_hostses) > 0:
-                self.updateHostsIcon(self.origin_hostses[0])
-            self.SetIcon(co.GetMondrianIcon(self.current_using_hosts.icon_idx))
-            self.taskbar_icon.updateIcon()
-
-    def addHosts(self, hosts, show_after_add=False):
-
-        if hosts.is_origin:
-            tree = self.m_tree_origin
-            list_hosts = self.origin_hostses
-        elif hosts.is_online:
-            tree = self.m_tree_online
-            list_hosts = self.hostses
-        elif hosts.is_common:
-            tree = self.m_tree_common
-            list_hosts = self.common_hostses
-        else:
-            tree = self.m_tree_local
-            list_hosts = self.hostses
-
-        if hosts.is_origin:
-            hosts.tree_item_id = self.m_tree_origin
-        elif hosts.is_common:
-            hosts.tree_item_id = self.m_tree_common
-            list_hosts.append(hosts)
-        else:
-            list_hosts.append(hosts)
-            hosts.tree_item_id = self.m_tree.AppendItem(tree, hosts.title)
-
-        self.updateHostsIcon(hosts)
-        self.m_tree.Expand(tree)
-
-        if show_after_add:
-            self.m_tree.SelectItem(hosts.tree_item_id)
-
-    def updateHostsIcon(self, hosts):
-
-        icon_idx = hosts.icon_idx
-        if type(icon_idx) not in (int, long) or icon_idx < 0:
-            icon_idx = 0
-        elif icon_idx >= len(self.ico_colors_idx):
-            icon_idx = len(self.ico_colors_idx) - 1
-
-        self.m_tree.SetItemImage(
-            hosts.tree_item_id, self.ico_colors_idx[icon_idx], wx.TreeItemIcon_Normal
-        )
-#        if hosts == self.current_using_hosts:
-#            self.updateIcon()
-
-    def delHosts(self, hosts):
-
-        if not hosts:
-            return False
-
-        if hosts.is_origin:
-            wx.MessageBox(u"初始 hosts 不能删除哦~", caption=u"出错啦!")
-            return False
-
-        if hosts == self.current_using_hosts:
-            wx.MessageBox(u"这个 hosts 方案正在使用,不能删除哦~", caption=u"出错啦!")
-            return False
-
-        dlg = wx.MessageDialog(None, u"确定要删除 hosts '%s'?" % hosts.title, u"删除 hosts",
-            wx.YES_NO | wx.ICON_QUESTION
-        )
-        ret_code = dlg.ShowModal()
-        if ret_code != wx.ID_YES:
-            dlg.Destroy()
-            return False
-
-        dlg.Destroy()
-
-        try:
-            hosts.remove()
-
-        except Exception:
-            err = traceback.format_exc()
-            wx.MessageBox(err, caption=u"出错啦!")
-            return False
-
-        self.m_tree.Delete(hosts.tree_item_id)
-        self.hostses.remove(hosts)
-
-        cfg_hostses = self.configs.get("hostses")
-        if cfg_hostses and hosts.title in cfg_hostses:
-            cfg_hostses.remove(hosts.title)
-
-        return True
-
-    def export(self, path):
-        u"""将当前所有设置以及方案导出为一个文件"""
-
-        data = {
-            "version": self.version,
-            "configs": self.configs,
-        }
-        hosts_files = []
-        for hosts in self.hostses:
-            hosts_files.append({
-                "filename": hosts.filename,
-                "content": hosts.full_content,
-            })
-
-        data["hosts_files"] = hosts_files
-
-        try:
-            self.writeFile(path, json.dumps(data))
-        except Exception:
-            wx.MessageBox(u"导出失败!\n\n%s" % traceback.format_exc(), caption=u"出错啦!")
-            return
-
-        wx.MessageBox(u"导出完成!")
-
-    def importHosts(self, content):
-        u"""导入"""
-
-        try:
-            data = json.loads(content)
-
-        except Exception:
-            wx.MessageBox(u"档案解析出错了!", caption=u"导入失败")
-            return
-
-        if type(data) != dict:
-            wx.MessageBox(u"档案格式有误!", caption=u"导入失败")
-            return
-
-        configs = data.get("configs")
-        hosts_files = data.get("hosts_files")
-        if type(configs) != dict or type(hosts_files) not in (list, tuple):
-            wx.MessageBox(u"档案数据有误!", caption=u"导入失败")
-            return
-
-        # 删除现有 hosts 文件
-        current_files = glob.glob(os.path.join(self.hosts_path, "*.hosts"))
-        for fn in current_files:
-            try:
-                os.remove(fn)
-
-            except Exception:
-                wx.MessageBox(u"删除 '%s' 时失败!\n\n%s" % (fn, traceback.format_exc()),
-                    caption=u"导入失败")
-                return
-
-        # 写入新 hosts 文件
-        for hf in hosts_files:
-            if type(hf) != dict or "filename" not in hf or "content" not in hf:
-                continue
-
-            fn = hf["filename"].strip()
-            if not fn or not fn.lower().endswith(".hosts"):
-                continue
-
-            try:
-                self.writeFile(os.path.join(self.hosts_path, fn), hf["content"].strip().encode("utf-8"))
-
-            except Exception:
-                wx.MessageBox(u"写入 '%s' 时失败!\n\n%s" % (fn, traceback.format_exc()),
-                    caption=u"导入失败")
-                return
-
-        # 更新 configs
-#        self.configs = {}
-        try:
-            self.writeFile(self.configs_path, json.dumps(configs).encode("utf-8"))
-        except Exception:
-            wx.MessageBox(u"写入 '%s' 时失败!\n\n%s" % (self.configs_path, traceback.format_exc()),
-                caption=u"导入失败")
-            return
-
-#        self.clearTree()
-#        self.init2()
-
-        wx.MessageBox(u"导入成功!")
-        self.restart()
-
-    def restart(self):
-        u"""重启主界面程序"""
-
-        self.mainjob.toRestart(None)
-#        self.mainjob.toRestart(self.taskbar_icon)
-        self.stopBackThreads()
-        self.taskbar_icon.Destroy()
-        self.Destroy()
-
-    def clearTree(self):
-
-        for hosts in self.all_hostses:
-            self.m_tree.Delete(hosts.tree_item_id)
-
-    def notify(self, msg="", title=u"消息"):
-
-        def macGrowlNotify(msg, title):
-
-            try:
-                growl.notify(
-                    noteType="New Messages",
-                    title=title,
-                    description=msg,
-                    sticky=False,
-                    priority=1,
-                )
-            except Exception:
-                pass
-
-        if self.sys_type == "mac":
-            # Mac 系统
-            if has_growl:
-                macGrowlNotify(msg, title)
-
-        elif self.sys_type == "linux":
-            # linux 系统
-            pynotify.Notification(title, msg).show()
-
-        else:
-
-            try:
-                import ToasterBox as TB
-            except ImportError:
-                TB = None
-
-            sw, sh = wx.GetDisplaySize()
-            width, height = 210, 50
-            px = sw - 230
-            py = sh - 100
-
-            tb = TB.ToasterBox(self)
-            tb.SetPopupText(msg)
-            tb.SetPopupSize((width, height))
-            tb.SetPopupPosition((px, py))
-            tb.Play()
-
-        self.SetFocus()
-
-    def updateConfigs(self, configs):
-
-        keys = ("hostses",)
-        for k in keys:
-            if k in configs:
-                self.configs[k] = configs[k]
-
-        # 校验配置有效性
-        if type(self.configs.get("hostses")) != list:
-            self.configs["hostses"] = []
-
-    def loadConfigs(self):
-
-        if os.path.isfile(self.configs_path):
-            try:
-                configs = json.loads(open(self.configs_path, "rb").read())
-            except Exception:
-                wx.MessageBox("读取配置信息失败!", caption=u"出错啦!")
-                return
-
-            if type(configs) != dict:
-                wx.MessageBox("配置信息格式有误!", caption=u"出错啦!")
-                return
-
-            self.updateConfigs(configs)
-
-
-        self.saveConfigs()
-
-    def saveConfigs(self):
-        try:
-            self.writeFile(self.configs_path, json.dumps(self.configs))
-        except Exception:
-            wx.MessageBox("保存配置信息失败!\n\n%s" % traceback.format_exc(), caption=u"出错啦!")
-
-    def eachHosts(self, func):
-
-        for hosts in self.hostses:
-            func(hosts)
-
-    @property
-    def all_hostses(self):
-
-        return self.origin_hostses + self.hostses
-
-    @property
-    def local_hostses(self):
-
-        return [hosts for hosts in self.hostses if not hosts.is_online]
-
-    @property
-    def online_hostses(self):
-
-        return [hosts for hosts in self.hostses if hosts.is_online]
-
-    def makeNewHostsFileName(self):
-        u"""生成一个新的 hosts 文件名"""
-
-        fns = glob.glob(os.path.join(self.hosts_path, "*.hosts"))
-        fns = [os.path.split(fn)[1] for fn in fns]
-        for i in xrange(1024):
-            fn = "%d.hosts" % i
-            if fn not in fns:
-                break
-
-        else:
-            return None
-
-        return fn
-
-    def saveHosts(self, hosts):
-
-        try:
-            if hosts.save():
-                co.log("saved.")
-            return True
-
-        except Exception:
-            err = traceback.format_exc()
-
-            if "Permission denied:" in err:
-                msg = u"没有修改 '%s' 的权限!" % hosts.path
-
-            else:
-                msg = u"保存 hosts 失败!\n\n%s" % err
-
-            wx.MessageBox(msg, caption=u"出错啦!")
-
-            return False
-
-    def showDetailEditor(self, hosts=None, default_is_online=False):
-        u"""显示详情编辑窗口"""
-
-        dlg = ui.Dlg_addHosts(self)
-
-        if hosts:
-            # 初始化值
-            dlg.m_radioBtn_local.SetValue(not hosts.is_online)
-            dlg.m_radioBtn_online.SetValue(hosts.is_online)
-            dlg.m_radioBtn_local.Enable(False)
-            dlg.m_radioBtn_online.Enable(False)
-            dlg.m_textCtrl_title.SetValue(hosts.title)
-            if hosts.url:
-                dlg.m_textCtrl_url.SetValue(hosts.url)
-                dlg.m_textCtrl_url.Enable(True)
-
-        else:
-            dlg.m_radioBtn_local.SetValue(not default_is_online)
-            dlg.m_radioBtn_online.SetValue(default_is_online)
-            dlg.m_textCtrl_url.Enabled = default_is_online
-
-        if dlg.ShowModal() != wx.ID_OK:
-            dlg.Destroy()
-            return
-
-        dlg.Destroy()
-
-        is_online = dlg.m_radioBtn_online.GetValue()
-        title = dlg.m_textCtrl_title.GetValue().strip()
-        url = dlg.m_textCtrl_url.GetValue().strip()
-
-        if not title:
-            wx.MessageBox(u"方案名不能为空!", caption=u"出错啦!")
-            return
-
-        for h in self.hostses:
-            if h != hosts and h.title == title:
-                wx.MessageBox(u"已经有名为 '%s' 的方案了!" % title, caption=u"出错啦!")
-                return
-
-        if not hosts:
-            # 新建 hosts
-            fn = self.makeNewHostsFileName()
-            if not fn:
-                wx.MessageBox(u"hosts 文件数超出限制,无法再创建新 hosts 了!", caption=u"出错啦!")
-                return
-
-            path = os.path.join(self.hosts_path, fn)
-
-            hosts = Hosts(path, title=title, url=url if is_online else None)
-            hosts.content = u"# %s" % title
-
-            if hosts.is_online:
-                self.getHostsContent(hosts)
-
-            self.addHosts(hosts, show_after_add=True)
-
-        else:
-            # 修改 hosts
-            hosts.is_online = is_online
-            hosts.title = title
-            hosts.url = url if is_online else None
-            self.updateHostsTitle(hosts)
-
-        self.saveHosts(hosts)
-
-    def getHostsContent(self, hosts):
-
-        hosts.is_loading = True
-
-        def tryToDestroy(obj):
-            # mac 下,progress_dlg 销毁时总是会异常退出...
-            if sys_type != "mac":
-                try:
-                    obj.Destroy()
-                except Exception:
-                    print(traceback.format_exc())
-
-        if hosts.is_online:
-            progress_dlg = wx.ProgressDialog(u"加载中",
-                u"正在加载「%s」...\nURL: %s" % (hosts.title, hosts.url), 100,
-                style=wx.PD_AUTO_HIDE
-            )
-            self.task_qu.put(lambda : [
-                wx.CallAfter(progress_dlg.Update, 10),
-                hosts.getContent(force=True, progress_dlg=progress_dlg),
-                wx.CallAfter(progress_dlg.Update, 80),
-                wx.CallAfter(self.tryToShowHosts, hosts),
-                wx.CallAfter(progress_dlg.Update, 90),
-                wx.CallAfter(self.saveHosts, hosts),
-                wx.CallAfter(progress_dlg.Update, 100),
-#                wx.CallAfter(lambda : progress_dlg.Destroy() and self.SetFocus()),
-                wx.CallAfter(lambda : tryToDestroy(progress_dlg)),
-                wx.CallAfter(self.SetFocus),
-            ])
-
-        else:
-            self.task_qu.put(lambda : [
-                hosts.getContent(force=True),
-                wx.CallAfter(self.tryToShowHosts, hosts),
-                wx.CallAfter(self.saveHosts, hosts),
-            ])
-
-        self.tryToShowHosts(hosts)
-
-    def updateHostsTitle(self, hosts):
-        u"""更新hosts的名称"""
-
-        self.m_tree.SetItemText(hosts.tree_item_id, hosts.title)
-
-    def getHostsFromTreeByEvent(self, event):
-
-        item = event.GetItem()
-        self.current_tree_item = item
-
-        if item in (self.m_tree_online, self.m_tree_local, self.m_tree_root):
-            pass
-
-        elif self.current_using_hosts and item == self.current_using_hosts.tree_item_id:
-            return self.current_using_hosts
-
-        else:
-            for hosts in self.all_hostses:
-                if item == hosts.tree_item_id:
-                    return hosts
-            for hosts in self.common_hostses:
-                if item == hosts.tree_item_id:
-                    return hosts
-
-        return None
-
-    def getLatestStableVersion(self, alert=False):
-
-        url = "https://github.com/oldj/SwitchHosts/blob/master/README.md"
-
-        ver = None
-        try:
-            c = urllib.urlopen(url).read()
-#            wx.CallAfter(progress_dlg.Update, 50)
-            v = re.search(r"\bLatest Stable:\s?(?P<version>[\d\.]+)\b", c)
-            if v:
-                ver = v.group("version")
-                self.latest_stable_version = ver
-                co.log("last_stable_version: %s" % ver)
-
-        except Exception:
-            pass
-
-        if not alert:
-            return
-
-        def _msg():
-            if not ver:
-                wx.MessageBox(u"未能取得最新版本号!", caption=u"出错啦!")
-
-            else:
-                cmpv = co.compareVersion(self.version, self.latest_stable_version)
-                try:
-                    if cmpv >= 0:
-                        wx.MessageBox(u"当前已是最新版本!")
-                    else:
-                        if wx.MessageBox(
-                            u"更新的稳定版 %s 已经发布,现在立刻查看吗?" % self.latest_stable_version,
-                            u"发现新版本!",
-                            wx.YES_NO | wx.ICON_INFORMATION
-                        ) == wx.YES:
-                            self.openHomepage()
-
-                except Exception:
-                    co.debugErr()
-                    pass
-
-        wx.CallAfter(_msg)
-
-    def getHostsAttr(self, hosts, key=None):
-
-        attrs = {
-            "is_refresh_able": hosts and hosts in self.all_hostses or hosts in self.common_hostses,
-            "is_delete_able": hosts and hosts in self.hostses,
-            "is_info_edit_able": hosts and not hosts.is_loading and hosts in self.hostses,
-            "is_content_edit_able": hosts and not hosts.is_loading and
-                (hosts in self.hostses or hosts in self.common_hostses),
-            "is_apply_able": not hosts.is_common and not hosts.is_origin,
-        }
-        for k in attrs:
-            attrs[k] = True if attrs[k] else False
-
-        return attrs.get(key, False) if key else attrs
-
-    def updateBtnStatus(self, hosts):
-
-        hosts_attrs = self.getHostsAttr(hosts)
-
-        # 更新下方按钮状态
-        self.m_btn_refresh.Enable(hosts_attrs["is_refresh_able"])
-        self.m_btn_del.Enable(hosts_attrs["is_delete_able"])
-        self.m_btn_edit_info.Enable(hosts_attrs["is_info_edit_able"])
-        self.m_btn_apply.Enable(hosts_attrs["is_apply_able"])
-
-        # 更新右键菜单项状态
-        self.hosts_item_menu.Enable(wx.ID_EDIT, hosts_attrs["is_info_edit_able"])
-        self.hosts_item_menu.Enable(wx.ID_DELETE, hosts_attrs["is_delete_able"])
-        self.hosts_item_menu.Enable(wx.ID_REFRESH, hosts_attrs["is_refresh_able"])
-        self.hosts_item_menu.Enable(wx.ID_APPLY, hosts_attrs["is_apply_able"])
-
-    def writeFile(self, path, content, mode="w"):
-
-        try:
-            path = path.encode(self.local_encoding)
-        except Exception:
-            co.debugErr()
-
-        open(path, mode).write(content)
-
-    def openHomepage(self):
-        u"""打开项目主页"""
-
-        url= "http://oldj.github.io/SwitchHosts/"
-        wx.LaunchDefaultBrowser(url)
-
-    def OnHomepage(self, event):
-        self.openHomepage()
-
-    def openFeedbackPage(self):
-        u"""打开反馈主页"""
-
-        url = "https://github.com/oldj/SwitchHosts/issues?direction=desc&sort=created&state=open"
-        wx.LaunchDefaultBrowser(url)
-
-    def OnFeedback(self, event):
-        self.openFeedbackPage()
-
-    def OnHostsChange(self, event):
-
-        if self.is_switching_text:
-            return
-
-        self.current_showing_hosts.content = self.m_textCtrl_content.GetText().strip()
-        self.saveHosts(self.current_showing_hosts)
-
-    def OnChkUpdate(self, event):
-
-        self.task_qu.put(lambda : [
-            self.getLatestStableVersion(alert=True),
-        ])
-
-    def OnExit(self, event):
-
-        self.is_running = False
-        self.stopBackThreads()
-        self.taskbar_icon.Destroy()
-        self.Destroy()
-
-        # 退出时删除进程锁文件
-        lock_fn = os.path.join(self.working_path, self.instance_name) \
-            if self.instance_name else None
-        if lock_fn and os.path.isfile(lock_fn):
-            os.remove(lock_fn)
-
-        # sys.exit()
-
-    def OnAbout(self, event):
-
-        dlg = ui.AboutBox(version=self.version, latest_stable_version=self.latest_stable_version)
-        dlg.ShowModal()
-        dlg.Destroy()
-
-    def OnTreeSelectionChange(self, event):
-        u"""当点击左边树状结构的节点的时候触发"""
-
-        hosts = self.getHostsFromTreeByEvent(event)
-
-        if not hosts:
-            return
-        self.current_tree_hosts = hosts
-        self.updateBtnStatus(hosts)
-
-        if not hosts or (hosts not in self.hostses and hosts not in self.origin_hostses and hosts not in self.common_hostses):
-            return event.Veto()
-
-        if hosts and hosts != self.current_showing_hosts:
-            if hosts.is_origin:
-                # 重新读取系统 hosts 值
-                hosts.getContent()
-            self.showHosts(hosts)
-
-    def OnTreeRClick(self, event):
-        u"""在树节点上单击右键,展示右键菜单"""
-
-        hosts = self.getHostsFromTreeByEvent(event)
-        if hosts:
-            self.OnTreeSelectionChange(event)
-
-            self.m_tree.PopupMenu(self.hosts_item_menu, event.GetPoint())
-
-    def OnTreeMenu(self, event):
-        co.log("tree menu...")
-
-    def OnTreeActive(self, event):
-        u"""双击树的节点时候触发"""
-
-        hosts = self.getHostsFromTreeByEvent(event)
-        if hosts:
-            if hosts.is_common or hosts.is_origin:
-                return
-            self.useHosts(hosts)
-
-    def OnApply(self, event):
-        u"""点击切换Hosts时候,触发该函数"""
-
-        if self.current_showing_hosts and self.current_showing_hosts.is_common:
-            return
-        if self.current_showing_hosts:
-            self.useHosts(self.current_showing_hosts)
-
-    def OnDel(self, event):
-
-        if self.delHosts(self.current_tree_hosts):
-            self.current_showing_hosts = None
-
-    def OnNew(self, event):
-
-        is_online = False
-        hosts = self.current_showing_hosts
-        if hosts.is_online or self.current_tree_item == self.m_tree_online:
-            is_online = True
-
-        self.showDetailEditor(default_is_online=is_online)
-
-    def OnEdit(self, event):
-
-        self.showDetailEditor(hosts=self.current_showing_hosts)
-
-    def OnRename(self, event):
-
-        hosts = self.current_showing_hosts
-        if not hosts:
-            return
-
-        if hosts in self.origin_hostses:
-            wx.MessageBox(u"%s不能改名!" % lang.trans("origin_hosts"), caption=u"出错啦!")
-            return
-
-        self.m_tree.EditLabel(hosts.tree_item_id)
-
-    def OnRenameEnd(self, event):
-
-        hosts = self.current_showing_hosts
-        if not hosts:
-            return
-
-        title = event.GetLabel().strip()
-        if title and hosts.title != title:
-            hosts.title = title
-            hosts.save()
-
-        else:
-            event.Veto()
-
-    def OnRefresh(self, event):
-
-        hosts = self.current_showing_hosts
-        self.getHostsContent(hosts)
-
-    def OnExport(self, event):
-
-        if wx.MessageBox(
-            u"您可以将现在的 hosts 档案导出并共享给其他 SwitchHosts! 用户。\n\n" +
-            u"注意,只有“%s”和“%s”中的 hosts 会被导出!" % (
-                lang.trans("local_hosts"), lang.trans("online_hosts")),
-            caption=u"导出档案",
-            style=wx.OK | wx.CANCEL,
-        ) != wx.OK:
-            return
-
-        wildcard = u"SwicthHosts! 档案 (*.swh)|*.swh"
-        dlg = wx.FileDialog(self, u"导出为...", os.getcwd(), "hosts.swh", wildcard, wx.SAVE)
-
-        if dlg.ShowModal() == wx.ID_OK:
-            self.export(dlg.GetPath())
-
-        dlg.Destroy()
-
-    def OnImport(self, event):
-
-        dlg = ui.Dlg_Import(self)
-        if dlg.ShowModal() == wx.ID_OK:
-            path = dlg.m_filePicker.GetPath()
-            url = dlg.m_textCtrl_url.GetValue()
-
-            content = None
-            if dlg.m_notebook.GetSelection() != 1:
-                # 本地
-                if os.path.isfile(path):
-                    content = open(path).read()
-
-                else:
-                    wx.MessageBox(u"%s 不是有效的文件路径!" % path, caption=u"出错啦!")
-
-            else:
-                # 在线
-                if co.httpExists(url):
-                    content = urllib.urlopen(url).read()
-
-                else:
-                    wx.MessageBox(u"URL %s 无法访问!" % url, caption=u"出错啦!")
-
-            if content and wx.MessageBox(u"导入档案会替换现有设置及数据,确定要导入吗?",
-                    caption=u"警告",
-                    style=wx.OK | wx.CANCEL) == wx.OK:
-                self.importHosts(content)
-
-        dlg.Destroy()
-
-    def OnDonate(self, event):
-
-        wx.LaunchDefaultBrowser("https://me.alipay.com/oldj")
-
-    def OnTreeBeginDrag(self, event):
-
-        item = event.GetItem()
-        hosts = self.getHostsFromTreeByEvent(event)
-        if not hosts or hosts.is_origin or hosts.is_common:
-            event.Veto()
-            return
-
-        co.log("drag start..")
-        self.current_dragging_hosts = hosts
-        self.__dragging_item = item
-
-        event.Allow()
-        self.m_tree.Bind(wx.EVT_MOTION, self._drag_OnMotion)
-        self.m_tree.Bind(wx.EVT_LEFT_UP, self._drag_OnMouseLeftUp)
-
-    def _drag_OnMotion(self, event):
-
-        event.Skip()
-
-    def _drag_OnMouseLeftUp(self, event):
-
-        co.log("mouse left up..")
-        self.m_tree.Unbind(wx.EVT_MOTION)
-        self.m_tree.Unbind(wx.EVT_LEFT_UP)
-        event.Skip()
-
-    def OnTreeEndDrag(self, event):
-
-        co.log("drag end..")
-
-        target_item = event.GetItem()
-        target_hosts = self.getHostsFromTreeByEvent(event)
-        source_item = self.__dragging_item
-        source_hosts = self.current_dragging_hosts
-
-        self.__dragging_item = None
-        self.current_dragging_hosts = None
-
-        def getHostsIdx(hosts):
-
-            idx = 0
-            for h in self.hostses:
-                if h == hosts:
-                    break
-
-                if h.is_online == hosts.is_online:
-                    idx += 1
-
-            return idx
-
-
-        is_dragged = False
-
-        if target_hosts and target_hosts != source_hosts and \
-           source_hosts.is_online == target_hosts.is_online:
-            # 拖到目标 hosts 上了
-            parent = self.m_tree.GetItemParent(target_item)
-            added_item_id = self.m_tree.InsertItemBefore(parent, getHostsIdx(target_hosts),
-                    source_hosts.title
-                )
-            source_hosts.tree_item_id = added_item_id
-#            self.updateHostsTitle(source_hosts)
-            self.updateHostsIcon(source_hosts)
-            if source_hosts == self.current_using_hosts:
-                self.highLightHosts(source_hosts)
-            self.hostses.remove(source_hosts)
-            self.hostses.insert(self.hostses.index(target_hosts), source_hosts)
-
-            is_dragged = True
-
-        elif target_item == self.m_tree_local and not source_hosts.is_online:
-            # 拖到本地树上了
-            pass
-
-        elif target_item == self.m_tree_online and source_hosts.is_online:
-            # 拖到在线树上了
-            pass
-
-        if is_dragged:
-            self.updateConfigs({
-                "hostses": [hosts.filename for hosts in self.hostses],
-            })
-            self.saveConfigs()
-            self.m_tree.Delete(source_item)
-            self.m_tree.SelectItem(source_hosts.tree_item_id)
-
-    def OnActiveApp(self, event):
-        """Called when the doc icon is clicked, and ???"""
-        print("---")
-#        self.GetTopWindow().Raise()
-        self.Raise()
-
-    def chkActive(self):
-        u"""循环查看工作目录下是否有 .active 文件,有则激活主窗口"""
-
-        if self.is_running and os.path.isfile(self.active_fn):
-            print("active..")
-            os.remove(self.active_fn)
-#            print(dir(self.mainjob.app))
-            self.Raise()
-            wx.TopLevelWindow.RequestUserAttention(self)
-#            self.mainjob.app.SetTopWindow(self)
-
-        time.sleep(0.5)
-#        wx.CallAfter(self.chkActive)
-        if self.is_running:
-            self.task_qu.put(self.chkActive)

+ 0 - 123
legacy/v2/src/libs/TaskbarIcon.py

@@ -1,123 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# author: oldj
-# blog: http://oldj.net
-# email: [email protected]
-#
-
-import wx
-import common_operations as co
-import lang
-
-class TaskBarIcon(wx.TaskBarIcon):
-
-    ID_About = wx.NewId()
-    ID_Exit = wx.NewId()
-    ID_MainFrame = wx.NewId()
-
-    def __init__(self, main_frame):
-
-        wx.TaskBarIcon.__init__(self)
-        #        super(wx.TaskBarIcon, self).__init__()
-        self.setMainFrame(main_frame)
-        self.Bind(wx.EVT_TASKBAR_LEFT_DCLICK, self.OnTaskBarLeftDClick)
-        self.Bind(wx.EVT_MENU, self.OnExit, id=self.ID_Exit)
-        self.Bind(wx.EVT_MENU, self.OnMainFrame, id=self.ID_MainFrame)
-
-        self.font_bold = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
-        self.font_bold.SetWeight(wx.BOLD)
-
-
-    def setMainFrame(self, main_frame):
-
-        self.main_frame = main_frame
-        self.SetIcon(co.GetMondrianIcon(), self.main_frame.default_title)
-        self.Bind(wx.EVT_MENU, self.main_frame.OnAbout, id=self.ID_About)
-
-
-    def OnTaskBarLeftDClick(self, event):
-
-        if self.main_frame.IsIconized():
-            self.main_frame.Iconize(False)
-        if not self.main_frame.IsShown():
-            self.main_frame.Show(True)
-        self.main_frame.Raise()
-
-
-    def OnExit(self, event):
-
-        self.main_frame.OnExit(event)
-
-
-    def OnMainFrame(self, event):
-        u"""显示主面板"""
-
-        if not self.main_frame.IsShown():
-            self.main_frame.Show(True)
-        self.main_frame.Raise()
-
-    # override
-    def CreatePopupMenu(self):
-
-        menu = wx.Menu()
-        menu.Append(self.ID_MainFrame, u"SwitchHosts!")
-        menu.AppendSeparator()
-
-        local_hostses = self.main_frame.local_hostses
-        online_hostses = self.main_frame.online_hostses
-
-        def addItems(name, hostses):
-            tmp_id = wx.NewId()
-            menu.Append(tmp_id, name)
-            menu.Enable(tmp_id, False)
-
-            for hosts in hostses:
-                if hosts:
-                    self.addHosts(menu, hosts)
-
-        if local_hostses:
-            addItems(u"本地方案", local_hostses)
-        if online_hostses:
-            addItems(u"在线方案", online_hostses)
-
-        menu.AppendSeparator()
-        menu.Append(self.ID_About, "About")
-        menu.Append(self.ID_Exit, "Exit")
-
-        return menu
-
-
-    def addHosts(self, menu, hosts):
-        u"""在菜单项中添加一个 hosts"""
-
-        item_id = wx.NewId()
-        title = hosts.title if not hosts.is_origin else lang.trans("origin_hosts")
-        mitem = wx.MenuItem(menu, item_id, title)
-        mitem.SetBitmap(co.GetMondrianBitmap(hosts.icon_idx))
-
-        is_using = self.main_frame.current_using_hosts == hosts
-        if is_using:
-            mitem.SetFont(self.font_bold)
-#        self.hosts[item_id] = title
-        hosts.taskbar_id = item_id
-	menu.AppendItem(mitem)
-        self.Bind(wx.EVT_MENU, self.switchHosts, id=item_id)
-
-
-
-    def switchHosts(self, event):
-        item_id = event.GetId()
-        for hosts in self.main_frame.all_hostses:
-            if hosts.taskbar_id == item_id:
-                self.main_frame.useHosts(hosts)
-
-                return
-
-
-    def updateIcon(self):
-
-        self.SetIcon(
-            co.GetMondrianIcon(self.main_frame.current_using_hosts.icon_idx),
-            self.main_frame.default_title
-        )
-

+ 0 - 754
legacy/v2/src/libs/ToasterBox.py

@@ -1,754 +0,0 @@
-# --------------------------------------------------------------------------- #
-# TOASTERBOX wxPython IMPLEMENTATION
-# Ported And Enhanced From wxWidgets Contribution (Aj Bommarito) By:
-#
-# Andrea Gavana, @ 16 September 2005
-# Latest Revision: 31 Oct 2007, 21.30 CET
-#
-#
-# TODO/Caveats List
-#
-# 1. Any Idea?
-#
-#
-# For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please
-# Write To Me At:
-#
-# [email protected]
-# [email protected]
-#
-# Or, Obviously, To The wxPython Mailing List!!!
-#
-#
-# End Of Comments
-# --------------------------------------------------------------------------- #
-
-
-"""Description:
-
-ToasterBox Is A Cross-Platform Library To Make The Creation Of MSN Style "Toaster"
-Popups Easier. The Syntax Is Really Easy Especially If You Are Familiar With The
-Syntax Of wxPython.
-
-It Has 2 Main Styles:
-
-- TB_SIMPLE:  Using This Style, You Will Be Able To Specify A Background Image For
-             ToasterBox, Text Properties As Text Colour, Font And Label.
-
-- TB_COMPLEX: This Style Will Allow You To Put Almost Any Control Inside A
-             ToasterBox. You Can Add A Panel In Which You Can Put All The Controls
-             You Like.
-
-Both Styles Support The Setting Of ToasterBox Position (On Screen Coordinates),
-Size, The Time After Which The ToasterBox Is Destroyed (Linger), And The Scroll
-Speed Of ToasterBox.
-
-ToasterBox Has Been Tested On The Following Platforms:
-
-Windows (Verified on Windows XP, 2000)
-
-
-Latest Revision: Andrea Gavana @ 31 Oct 2007, 21.30 CET
-
-"""
-
-import textwrap
-import wx
-import sys
-
-from wx.lib.statbmp import GenStaticBitmap as StaticBitmap
-
-# Define Window List, We Use It Globally
-winlist = []
-
-TB_SIMPLE = 1
-TB_COMPLEX = 2
-
-DEFAULT_TB_STYLE = wx.SIMPLE_BORDER | wx.STAY_ON_TOP | wx.FRAME_NO_TASKBAR
-TB_CAPTION = DEFAULT_TB_STYLE | wx.CAPTION | wx.SYSTEM_MENU | wx.CLOSE_BOX | wx.FRAME_TOOL_WINDOW
-
-TB_ONTIME = 1
-TB_ONCLICK = 2
-
-# scroll from up to down
-TB_SCR_TYPE_UD = 1
-# scroll from down to up
-TB_SCR_TYPE_DU = 2
-
-# ------------------------------------------------------------------------------ #
-# Class ToasterBox
-#    Main Class Implementation. It Is Basically A wx.Timer. It Creates And
-#    Displays Popups And Handles The "Stacking".
-# ------------------------------------------------------------------------------ #
-
-class ToasterBox(wx.Timer):
-
-   def __init__(self, parent, tbstyle=TB_SIMPLE, windowstyle=DEFAULT_TB_STYLE,
-                closingstyle=TB_ONTIME, scrollType=TB_SCR_TYPE_DU):
-       """Deafult Class Constructor.
-
-       ToasterBox.__init__(self, tbstyle=TB_SIMPLE, windowstyle=DEFAULT_TB_STYLE)
-
-       Parameters:
-
-       - tbstyle: This Parameter May Have 2 Values:
-         (a) TB_SIMPLE: A Simple ToasterBox, With Background Image And Text
-             Customization Can Be Created;
-         (b) TB_COMPLEX: ToasterBoxes With Different Degree Of Complexity Can
-             Be Created. You Can Add As Many Controls As You Want, Provided
-             That You Call The AddPanel() Method And Pass To It A Dummy Frame
-             And A wx.Panel. See The Demo For Details.
-
-       - windowstyle: This Parameter Influences The Visual Appearance Of ToasterBox:
-         (a) DEFAULT_TB_STYLE: Default Style, No Caption Nor Close Box;
-         (b) TB_CAPTION: ToasterBox Will Have A Caption, With The Possibility To
-             Set A Title For ToasterBox Frame, And A Close Box;
-
-       - closingstyle: Set This Value To TB_ONCLICK If You Want To Be Able To Close
-         ToasterBox By A Mouse Click Anywhere In The ToasterBox Frame.
-
-       """
-
-       self._parent = parent
-       self._sleeptime = 10
-       self._pausetime = 1700
-       self._popuptext = "default"
-       self._popupposition = wx.Point(100,100)
-       self._popuptop = wx.Point(0,0)
-       self._popupsize = wx.Size(150, 170)
-
-       self._backgroundcolour = wx.WHITE
-       self._foregroundcolour = wx.BLACK
-       if sys.platform != "darwin":
-           self._textfont = wx.Font(8, wx.SWISS, wx.NORMAL, wx.NORMAL, False, "Verdana")
-       else:
-           self._textfont = wx.Font(12, wx.SWISS, wx.NORMAL, wx.NORMAL, False, "Monaco")
-
-       self._bitmap = None
-
-       self._tbstyle = tbstyle
-       self._windowstyle = windowstyle
-       self._closingstyle = closingstyle
-
-       self._panel = None
-
-       self._bottomright = wx.Point(wx.GetDisplaySize().GetWidth(),
-                                    wx.GetDisplaySize().GetHeight())
-
-       parent.Bind(wx.EVT_ICONIZE, lambda evt: [w.Hide() for w in winlist])
-
-       self._tb = ToasterBoxWindow(self._parent, self, self._tbstyle, self._windowstyle,
-                                   self._closingstyle, scrollType=scrollType)
-
-
-   def SetPopupPosition(self, pos):
-       """ Sets The ToasterBox Position On Screen. """
-
-       self._popupposition = pos
-
-
-   def SetPopupPositionByInt(self, pos):
-       """ Sets The ToasterBox Position On Screen, At One Of The Screen Corners. """
-
-       self._bottomright = wx.Point(wx.GetDisplaySize().GetWidth(),
-                                    wx.GetDisplaySize().GetHeight())
-
-       # top left
-       if pos == 0:
-           popupposition = wx.Point(0,0)
-       # top right
-       elif pos == 1:
-           popupposition = wx.Point(wx.GetDisplaySize().GetWidth() -
-                                    self._popupsize[0], 0)
-       # bottom left
-       elif pos == 2:
-           popupposition = wxPoint(0, wx.GetDisplaySize().GetHeight() -
-                                   self._popupsize[1])
-       # bottom right
-       elif pos == 3:
-           popupposition = wx.Point(self._bottomright.x - self._popupsize[0],
-                                    self._bottomright.y - self._popupsize[1])
-
-       self._bottomright = wx.Point(popupposition.x + self._popupsize[0],
-                                    popupposition.y + self._popupsize[1])
-
-
-   def SetPopupBackgroundColor(self, colour=None):
-       """ Sets The ToasterBox Background Colour. Use It Only For ToasterBoxes Created
-       With TB_SIMPLE Style. """
-
-       if colour is None:
-           colour = wx.WHITE
-
-       self._backgroundcolour = colour
-
-
-   def SetPopupTextColor(self, colour=None):
-       """ Sets The ToasterBox Foreground Colour. Use It Only For ToasterBoxes Created
-       With TB_SIMPLE Style. """
-
-       if colour is None:
-           colour = wx.BLACK
-
-       self._foregroundcolour = colour
-
-
-   def SetPopupTextFont(self, font=None):
-       """ Sets The ToasterBox Text Font. Use It Only For ToasterBoxes Created With
-       TB_SIMPLE Style. """
-
-       if font is None:
-           if sys.platform != "darwin":
-               font = wx.Font(8, wx.SWISS, wx.NORMAL, wx.NORMAL, False, "Verdana")
-           else:
-               font = wx.Font(12, wx.SWISS, wx.NORMAL, wx.NORMAL, False, "Monaco")
-
-       self._textfont = font
-
-
-   def SetPopupSize(self, size):
-       """ Sets The ToasterBox Size. """
-
-       self._popupsize = size
-
-
-   def SetPopupPauseTime(self, pausetime):
-       """ Sets The Time After Which The ToasterBox Is Destroyed (Linger). """
-
-       self._pausetime = pausetime
-
-
-   def SetPopupBitmap(self, bitmap=None):
-       """ Sets The ToasterBox Background Image. Use It Only For ToasterBoxes
-       Created With TB_SIMPLE Style. """
-
-       if bitmap is not None:
-           bitmap = wx.Bitmap(bitmap, wx.BITMAP_TYPE_BMP)
-
-       self._bitmap = bitmap
-
-
-   def SetPopupScrollSpeed(self, speed):
-       """ Sets The ToasterBox Scroll Speed. The Speed Parameter Is The Pause
-       Time (In ms) For Every Step In The ScrollUp() Method."""
-
-       self._sleeptime = speed
-
-
-   def SetPopupText(self, text):
-       """ Sets The ToasterBox Text. Use It Only For ToasterBoxes Created With
-       TB_SIMPLE Style. """
-
-       self._popuptext = text
-
-
-   def AddPanel(self, panel):
-       """ Adds A Panel To The ToasterBox. Use It Only For ToasterBoxes Created
-       With TB_COMPLEX Style. """
-
-       if not self._tbstyle & TB_COMPLEX:
-           raise "\nERROR: Panel Can Not Be Added When Using TB_SIMPLE ToasterBox Style"
-           return
-
-       self._panel = panel
-
-
-   def Play(self):
-       """ Creates The ToasterBoxWindow, That Does All The Job. """
-
-       # create new window
-       self._tb.SetPopupSize((self._popupsize[0], self._popupsize[1]))
-       self._tb.SetPopupPosition((self._popupposition[0], self._popupposition[1]))
-       self._tb.SetPopupPauseTime(self._pausetime)
-       self._tb.SetPopupScrollSpeed(self._sleeptime)
-
-       if self._tbstyle == TB_SIMPLE:
-           self._tb.SetPopupTextColor(self._foregroundcolour)
-           self._tb.SetPopupBackgroundColor(self._backgroundcolour)
-           self._tb.SetPopupTextFont(self._textfont)
-
-           if self._bitmap is not None:
-               self._tb.SetPopupBitmap(self._bitmap)
-
-           self._tb.SetPopupText(self._popuptext)
-
-       if self._tbstyle == TB_COMPLEX:
-           if self._panel is not None:
-               self._tb.AddPanel(self._panel)
-
-       # clean up the list
-       self.CleanList()
-
-       # check to see if there is already a window displayed
-       # by looking at the linked list
-       if len(winlist) > 0:
-           # there ARE other windows displayed already
-           # reclac where it should display
-           self.MoveAbove(self._tb)
-
-       # shift new window on to the list
-       winlist.append(self._tb)
-
-       if not self._tb.Play():
-           # if we didn't show the window properly, remove it from the list
-           winlist.remove(winlist[-1])
-           # delete the object too
-           self._tb.Destroy()
-           return
-
-
-   def MoveAbove(self, tb):
-       """ If A ToasterBox Already Exists, Move The New One Above. """
-
-       # recalc where to place this popup
-
-       self._tb.SetPopupPosition((self._popupposition[0], self._popupposition[1] -
-                                  self._popupsize[1]*len(winlist)))
-
-
-   def GetToasterBoxWindow(self):
-       """ Returns The ToasterBox Frame. """
-
-       return self._tb
-
-
-   def SetTitle(self, title):
-       """ Sets The ToasterBox Title If It Was Created With TB_CAPTION Window Style. """
-
-       self._tb.SetTitle(title)
-
-
-   def Notify(self):
-       """ It's Time To Hide A ToasterBox! """
-
-       if len(winlist) == 0:
-           return
-
-       # clean the window list
-       self.CleanList()
-
-       # figure out how many blanks we have
-       try:
-           node = winlist[0]
-       except:
-           return
-
-       if not node:
-           return
-
-       # move windows to fill in blank space
-       for i in xrange(node.GetPosition()[1], self._popupposition[1], 4):
-           if i > self._popupposition[1]:
-               i = self._popupposition[1]
-
-           # loop through all the windows
-           for j in xrange(0, len(winlist)):
-               ourNewHeight = i - (j*self._popupsize[1] - 8)
-               tmpTb = winlist[j]
-               # reset where the object THINKS its supposed to be
-               tmpTb.SetPopupPosition((self._popupposition[0], ourNewHeight))
-               # actually move it
-               tmpTb.SetDimensions(self._popupposition[0], ourNewHeight, tmpTb.GetSize().GetWidth(),
-                                   tmpTb.GetSize().GetHeight())
-
-           wx.Usleep(self._sleeptime)
-
-
-   def CleanList(self):
-       """ Clean The Window List. """
-
-       if len(winlist) == 0:
-           return
-
-       node = winlist[0]
-       while node:
-           if not node.IsShown():
-               winlist.remove(node)
-               try:
-                   node = winlist[0]
-               except:
-                   node = 0
-           else:
-               indx = winlist.index(node)
-               try:
-                   node = winlist[indx+1]
-               except:
-                   node = 0
-
-
-# ------------------------------------------------------------------------------ #
-# Class ToasterBoxWindow
-#    This Class Does All The Job, By Handling Background Images, Text Properties
-#    And Panel Adding. Depending On The Style You Choose, ToasterBoxWindow Will
-#    Behave Differently In Order To Handle Widgets Inside It.
-# ------------------------------------------------------------------------------ #
-
-class ToasterBoxWindow(wx.Frame):
-
-   def __init__(self, parent, parent2, tbstyle, windowstyle,
-       closingstyle, scrollType=TB_SCR_TYPE_DU):
-       """Default Class Constructor.
-
-       Used Internally. Do Not Call Directly This Class In Your Application!
-       """
-
-       wx.Frame.__init__(self, parent, wx.ID_ANY, "window", wx.DefaultPosition,
-                         wx.DefaultSize, style=windowstyle | wx.CLIP_CHILDREN)
-
-       self._starttime = wx.GetLocalTime()
-       self._parent2 = parent2
-       self._parent = parent
-       self._sleeptime = 10
-       self._step = 4
-       self._pausetime = 1700
-       self._textcolour = wx.BLACK
-       self._popuptext = "Change Me!"
-       # the size we want the dialog to be
-       framesize = wx.Size(150, 170)
-       self._count = 1
-       self._tbstyle = tbstyle
-       self._windowstyle = windowstyle
-       self._closingstyle = closingstyle
-       self._scrollType = scrollType
-
-
-       if tbstyle == TB_COMPLEX:
-           self.sizer = wx.BoxSizer(wx.VERTICAL)
-       else:
-           self._staticbitmap = None
-
-       if self._windowstyle == TB_CAPTION:
-           self.Bind(wx.EVT_CLOSE, self.OnClose)
-           self.SetTitle("")
-
-       if self._closingstyle & TB_ONCLICK and self._windowstyle != TB_CAPTION:
-           self.Bind(wx.EVT_LEFT_DOWN, self.OnMouseDown)
-
-       self._bottomright = wx.Point(wx.GetDisplaySize().GetWidth(),
-                                    wx.GetDisplaySize().GetHeight())
-
-       self.SetDimensions(self._bottomright.x, self._bottomright.y,
-                          framesize.GetWidth(), framesize.GetHeight())
-
-
-   def OnClose(self, event):
-
-       self.NotifyTimer(None)
-       event.Skip()
-
-
-   def OnMouseDown(self, event):
-
-       self.NotifyTimer(None)
-       event.Skip()
-
-
-   def SetPopupBitmap(self, bitmap):
-       """ Sets The ToasterBox Background Image. Use It Only For ToasterBoxes
-       Created With TB_SIMPLE Style. """
-
-       bitmap = bitmap.ConvertToImage()
-       xsize, ysize = self.GetSize()
-       bitmap = bitmap.Scale(xsize, ysize)
-       bitmap = bitmap.ConvertToBitmap()
-       self._staticbitmap = StaticBitmap(self, -1, bitmap, pos=(0,0))
-
-       if self._closingstyle & TB_ONCLICK and self._windowstyle != TB_CAPTION:
-           self._staticbitmap.Bind(wx.EVT_LEFT_DOWN, self.OnMouseDown)
-
-
-   def SetPopupSize(self, size):
-       """ Sets The ToasterBox Size. """
-
-       self.SetDimensions(self._bottomright.x, self._bottomright.y, size[0], size[1])
-
-
-   def SetPopupPosition(self, pos):
-       """ Sets The ToasterBox Position On Screen. """
-
-       self._bottomright = wx.Point(pos[0] + self.GetSize().GetWidth(),
-                                    pos[1] + self.GetSize().GetHeight())
-       self._dialogtop = pos
-
-
-   def SetPopupPositionByInt(self, pos):
-       """ Sets The ToasterBox Position On Screen, At One Of The Screen Corners. """
-
-       self._bottomright = wx.Point(wx.GetDisplaySize().GetWidth(),
-                                    wx.GetDisplaySize().GetHeight())
-
-       # top left
-       if pos == 0:
-           popupposition = wx.Point(0,0)
-       # top right
-       elif pos == 1:
-           popupposition = wx.Point(wx.GetDisplaySize().GetWidth() -
-                                    self._popupsize[0], 0)
-       # bottom left
-       elif pos == 2:
-           popupposition = wx.Point(0, wx.GetDisplaySize().GetHeight() -
-                                   self._popupsize[1])
-       # bottom right
-       elif pos == 3:
-           popupposition = wx.Point(self._bottomright.x - self._popupsize[0],
-                                    self._bottomright.y - self._popupsize[1])
-
-       self._bottomright = wx.Point(popupposition.x + self._popupsize[0],
-                                    popupposition.y + self._popupsize[1])
-
-       self._dialogtop = popupposition
-
-
-   def SetPopupPauseTime(self, pausetime):
-       """ Sets The Time After Which The ToasterBox Is Destroyed (Linger). """
-
-       self._pausetime = pausetime
-
-
-   def SetPopupScrollSpeed(self, speed):
-       """ Sets The ToasterBox Scroll Speed. The Speed Parameter Is The Pause
-       Time (In ms) For Every Step In The ScrollUp() Method."""
-
-       self._sleeptime = speed
-
-
-   def AddPanel(self, panel):
-       """ Adds A Panel To The ToasterBox. Use It Only For ToasterBoxes Created
-       With TB_COMPLEX Style. """
-
-       if not self._tbstyle & TB_COMPLEX:
-           raise "\nERROR: Panel Can Not Be Added When Using TB_SIMPLE ToasterBox Style"
-           return
-
-       self.sizer.Add(panel, 1, wx.EXPAND)
-       self.sizer.Layout()
-       self.SetSizer(self.sizer)
-
-       if self._closingstyle & TB_ONCLICK and self._windowstyle != TB_CAPTION:
-           panel.Bind(wx.EVT_LEFT_DOWN, self.OnMouseDown)
-
-
-   def SetPopupText(self, text):
-       """ Sets The ToasterBox Text. Use It Only For ToasterBoxes Created With
-       TB_SIMPLE Style. """
-
-       self._popuptext = text
-
-
-   def SetPopupTextFont(self, font):
-       """ Sets The ToasterBox Text Font. Use It Only For ToasterBoxes Created With
-       TB_SIMPLE Style. """
-
-       self._textfont = font
-
-
-   def GetPopupText(self):
-       """ Returns The ToasterBox Text. Use It Only For ToasterBoxes Created With
-       TB_SIMPLE Style. """
-
-       return self._popuptext
-
-
-   def Play(self):
-       """ Creates The ToasterBoxWindow, That Does All The Job. """
-
-       # do some checks to make sure this window is valid
-       if self._bottomright.x < 1 or self._bottomright.y < 1:
-           return False
-
-       if self.GetSize().GetWidth() < 50 or self.GetSize().GetWidth() < 50:
-           # toasterbox launches into a endless loop for some reason
-           # when you try to make the window too small.
-           return False
-
-       self.ScrollUp()
-       timerid = wx.NewId()
-       self.showtime = wx.Timer(self, timerid)
-       self.showtime.Start(self._pausetime)
-       self.Bind(wx.EVT_TIMER, self.NotifyTimer, id=timerid)
-
-       return True
-
-
-   def NotifyTimer(self, event):
-       """ Hides Gradually The ToasterBoxWindow. """
-
-       self.showtime.Stop()
-       del self.showtime
-       self.ScrollDown()
-
-
-   def SetPopupBackgroundColor(self, colour):
-       """ Sets The ToasterBox Background Colour. Use It Only For ToasterBoxes Created
-       With TB_SIMPLE Style. """
-
-       self.SetBackgroundColour(colour)
-
-
-   def SetPopupTextColor(self, colour):
-       """ Sets The ToasterBox Foreground Colour. Use It Only For ToasterBoxes Created
-       With TB_SIMPLE Style. """
-
-       self._textcolour = colour
-
-
-   def ScrollUp(self):
-       """ Scrolls The ToasterBox Up, Which Means Gradually Showing The ToasterBox. """
-
-       self.Show(True)
-
-       # walk the Y value up in a raise motion
-       xpos = self.GetPosition().x
-       ypos = self._bottomright[1]
-       windowsize = 0
-
-       # checking the type of the scroll (from up to down or from down to up)
-       if self._scrollType == TB_SCR_TYPE_UD:
-           start = self._dialogtop[1]
-           stop = ypos
-           step = self._step
-       elif self._scrollType == TB_SCR_TYPE_DU:
-           start = ypos
-           stop = self._dialogtop[1]
-           step = -self._step
-       else:
-           errMsg = ("scrollType not supported (in ToasterBoxWindow.ScrollUp): %s" %
-                 self._scrollType)
-           raise ValueError(errMsg)
-
-       for i in xrange(start, stop, step):
-           if i < self._dialogtop[1]:
-             i = self._dialogtop[1]
-
-           windowsize = windowsize + self._step
-
-           # checking the type of the scroll (from up to down or from down to up)
-           if self._scrollType == TB_SCR_TYPE_UD:
-               dimY = self._dialogtop[1]
-           elif self._scrollType == TB_SCR_TYPE_DU:
-               dimY = i
-           else:
-               errMsg = ("scrollType not supported (in ToasterBoxWindow.ScrollUp): %s" %
-                     self._scrollType)
-               raise ValueError(errMsg)
-
-           self.SetDimensions(self._dialogtop[0], dimY, self.GetSize().GetWidth(),
-                              windowsize)
-
-           if self._tbstyle == TB_SIMPLE:
-               self.DrawText()
-
-           wx.Usleep(self._sleeptime)
-           self.Update()
-           self.Refresh()
-
-       self.Update()
-
-       if self._tbstyle == TB_SIMPLE:
-           self.DrawText()
-
-#       self.SetFocus()
-
-
-   def ScrollDown(self):
-       """ Scrolls The ToasterBox Down, Which Means Gradually Hiding The ToasterBox. """
-
-       # walk down the Y value
-       windowsize = self.GetSize().GetHeight()
-
-       # checking the type of the scroll (from up to down or from down to up)
-       if self._scrollType == TB_SCR_TYPE_UD:
-           start = self._bottomright.y
-           stop = self._dialogtop[1]
-           step = -self._step
-       elif self._scrollType == TB_SCR_TYPE_DU:
-           start = self._dialogtop[1]
-           stop = self._bottomright.y
-           step = self._step
-       else:
-           errMsg = ("scrollType not supported (in ToasterBoxWindow.ScrollUp): %s" %
-                 self._scrollType)
-           raise ValueError(errMsg)
-
-       for i in xrange(start, stop, step):
-           if i > self._bottomright.y:
-               i = self._bottomright.y
-
-           windowsize = windowsize - self._step
-
-           # checking the type of the scroll (from up to down or from down to up)
-           if self._scrollType == TB_SCR_TYPE_UD:
-               dimY = self._dialogtop[1]
-           elif self._scrollType == TB_SCR_TYPE_DU:
-               dimY = i
-           else:
-               errMsg = ("scrollType not supported (in ToasterBoxWindow.ScrollUp): %s" %
-                     self._scrollType)
-               raise ValueError(errMsg)
-
-           self.SetDimensions(self._dialogtop[0], dimY,
-                              self.GetSize().GetWidth(), windowsize)
-
-           wx.Usleep(self._sleeptime)
-           self.Refresh()
-
-       self.Hide()
-       if self._parent2:
-           self._parent2.Notify()
-
-
-   def DrawText(self):
-       if self._staticbitmap is not None:
-           dc = wx.ClientDC(self._staticbitmap)
-       else:
-           dc = wx.ClientDC(self)
-       dc.SetFont(self._textfont)
-
-       if not hasattr(self, "text_coords"):
-           self._getTextCoords(dc)
-
-       dc.DrawTextList(*self.text_coords)
-
-
-   def _getTextCoords(self, dc):
-       """ Draw The User Specified Text Using The wx.DC. Use It Only For ToasterBoxes
-       Created With TB_SIMPLE Style. """
-
-       # border from sides and top to text (in pixels)
-       border = 7
-       # how much space between text lines
-       textPadding = 2
-
-       pText = self.GetPopupText()
-
-       max_len = len(pText)
-
-       tw, th = self._parent2._popupsize
-
-       if self._windowstyle == TB_CAPTION:
-           th = th - 20
-
-       while 1:
-           lines = textwrap.wrap(pText, max_len)
-
-           for line in lines:
-               w, h = dc.GetTextExtent(line)
-               if w > tw - border * 2:
-                   max_len -= 1
-                   break
-           else:
-               break
-
-       fh = 0
-       for line in lines:
-           w, h = dc.GetTextExtent(line)
-           fh += h + textPadding
-       y = (th - fh) / 2; coords = []
-
-       for line in lines:
-           w, h = dc.GetTextExtent(line)
-           x = (tw - w) / 2
-           coords.append((x, y))
-           y += h + textPadding
-
-       self.text_coords = (lines, coords)

+ 0 - 8
legacy/v2/src/libs/VERSION.py

@@ -1,8 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# author: oldj
-# blog: http://oldj.net
-# email: [email protected]
-#
-
-VERSION = "0.2.2.1802"

+ 0 - 6
legacy/v2/src/libs/__init__.py

@@ -1,6 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# author: oldj
-# blog: http://oldj.net
-# email: [email protected]
-#

+ 0 - 214
legacy/v2/src/libs/common_operations.py

@@ -1,214 +0,0 @@
-# -*- coding: utf-8 -*-
-
-u"""
-基本操作
-"""
-
-import os
-import sys
-import traceback
-import datetime
-import wx
-import chardet
-import urllib
-import re
-import threading
-import httplib
-import urlparse
-
-
-from icons import ICONS, ICONS2, ICONS_ICO
-
-
-def log(msg):
-
-    print(u"%s > %s" % (datetime.datetime.now().strftime("%H:%M:%S"), msg))
-
-
-def debugErr():
-
-    err = traceback.format_exc()
-    log("ERROR!")
-    log("-" * 50)
-    log(err)
-
-
-def GetMondrianData(i=0, fn=None):
-    if not fn:
-        idx = i if 0 <= i < len(ICONS) else 0
-        return ICONS_ICO[idx]
-    else:
-        return ICONS2[fn]
-
-
-def GetMondrianBitmap(i=0, fn=None):
-    return wx.BitmapFromImage(GetMondrianImage(i, fn))
-
-
-def GetMondrianImage(i=0, fn=None):
-    import cStringIO
-
-    stream = cStringIO.StringIO(GetMondrianData(i, fn))
-    return wx.ImageFromStream(stream)
-
-
-def GetMondrianIcon(i=0, fn=None):
-    icon = wx.EmptyIcon()
-    icon.CopyFromBitmap(GetMondrianBitmap(i, fn))
-    return icon
-
-
-
-def encode(s):
-
-#    print("--")
-#    print(chardet.detect(s))
-    return unicode(s).encode("UTF-8") if s else ""
-
-
-def decode(s):
-
-    s = s.strip()
-    if not s:
-        return ""
-
-    cd = {}
-    sample = s[:4096]
-    if sample:
-        try:
-            cd = chardet.detect(sample)
-        except Exception:
-#            print(traceback.format_exc())
-            pass
-#    log([sample, repr(cd)])
-
-    encoding = cd.get("encoding", "") if cd.get("confidence", 0) > 0.9 else ""
-
-    if encoding and encoding.upper() in ("GB2312", "GBK"):
-        encoding = "GB18030"
-
-    if not encoding:
-        encoding = "UTF-8"
-#    print s, cd, encoding, s.decode(encoding)
-
-    try:
-        s = s.decode(encoding)
-    except Exception:
-        pass
-
-    return s
-
-
-def checkLatestStableVersion(obj):
-
-    def _f(obj):
-        url = "https://github.com/oldj/SwitchHosts/blob/master/README.md"
-        ver = None
-
-        try:
-            c = urllib.urlopen(url).read()
-            v = re.search(r"\bLatest Stable:\s?(?P<version>[\d\.]+)\b", c)
-            if v:
-                ver = v.group("version")
-
-        except Exception:
-            pass
-
-        obj.setLatestStableVersion(ver)
-
-        return ver
-
-    t = threading.Thread(target=_f, args=(obj,))
-    t.setDaemon(True)
-    t.start()
-
-
-def httpExists(url):
-    host, path = urlparse.urlsplit(url)[1:3]
-    found = 0
-    try:
-        connection = httplib.HTTPConnection(host)  ## Make HTTPConnection Object
-        connection.request("HEAD", path)
-        responseOb = connection.getresponse()      ## Grab HTTPResponse Object
-
-        if responseOb.status == 200:
-            found = 1
-        elif responseOb.status == 302:
-            found = httpExists(urlparse.urljoin(url, responseOb.getheader('location', '')))
-        else:
-            print "Status %d %s : %s" % (responseOb.status, responseOb.reason, url)
-    except Exception, e:
-        print e.__class__, e, url
-    return found
-
-
-def compareVersion(v1, v2):
-    u"""比较两个版本的大小
-    版本的格式形如:0.1.5.3456
-
-    如果 v1 > v2,则返回 1
-    如果 v1 = v2,则返回 0
-    如果 v1 < v2,则返回 -1
-    """
-
-    a1 = v1.split(".")
-    a2 = v2.split(".")
-
-    try:
-        a1 = [int(i) for i in a1]
-        a2 = [int(i) for i in a2]
-    except Exception:
-        return 0
-
-    len1 = len(a1)
-    len2 = len(a2)
-    l = min(len1, len2)
-    for i in range(l):
-        if a1[i] > a2[i]:
-            return 1
-        elif a1[i] < a2[i]:
-            return -1
-
-    if len1 > len2:
-        return 1
-    elif len1 < len2:
-        return -1
-    else:
-        return 0
-
-
-def getLocalEncoding():
-    u"""取得本地编码"""
-
-    import locale
-    import codecs
-#    print locale.getpreferredencoding()
-
-    return "%s" % codecs.lookup(locale.getpreferredencoding()).name
-
-
-def getSystemType():
-    u"""取得系统类型
-        win
-        linux
-        mac
-    """
-
-    os_name = os.name
-
-    if os_name == "posix":
-
-        if sys.platform != "darwin":
-            # linux 系统
-            return "linux"
-
-        else:
-            # Mac 系统
-            return "mac"
-
-    elif os_name == "nt":
-        return "win"
-
-    return "unknow"
-
-

File diff suppressed because it is too large
+ 0 - 21
legacy/v2/src/libs/icons.py


+ 0 - 18
legacy/v2/src/libs/lang.py

@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# author: oldj
-# blog: http://oldj.net
-# email: [email protected]
-#
-
-
-lang = {
-    "common_hosts": u"公用 hosts",
-    "origin_hosts": u"当前系统 hosts",
-    "online_hosts": u"在线方案",
-    "local_hosts": u"本地方案",
-}
-
-def trans(key):
-
-    return lang.get(key) or "N/A"

+ 0 - 482
legacy/v2/src/libs/ui.py

@@ -1,482 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import os
-import wx, wx.html
-import wx.lib.buttons as buttons
-import common_operations as co
-import lang
-
-
-class Frame(wx.Frame):
-
-    ID_HOSTS_TEXT = wx.NewId()
-
-    def __init__(self,
-                 parent=None, id=wx.ID_ANY, title="SwitchHosts!", pos=wx.DefaultPosition,
-                 size=wx.DefaultSize,
-                 style=wx.DEFAULT_FRAME_STYLE,
-                 cls_TaskBarIcon=None
-    ):
-        wx.Frame.__init__(self, parent, id, title, pos, size, style)
-
-        self.SetIcon(co.GetMondrianIcon())
-        self.SetSizeHintsSz(wx.Size(400, 300), wx.DefaultSize)
-
-        self.m_menubar1 = wx.MenuBar(0)
-        self.m_menu1 = wx.Menu()
-        self.m_menuItem_new = wx.MenuItem(self.m_menu1, wx.ID_NEW, u"新建(&N)", wx.EmptyString, wx.ITEM_NORMAL)
-        self.m_menu1.AppendItem(self.m_menuItem_new)
-        self.m_menu1.AppendSeparator()
-
-        self.m_menuItem_export = wx.MenuItem(self.m_menu1, wx.NewId(), u"导出(&E)", wx.EmptyString, wx.ITEM_NORMAL)
-        self.m_menu1.AppendItem(self.m_menuItem_export)
-        self.m_menuItem_import = wx.MenuItem(self.m_menu1, wx.NewId(), u"导入(&I)", wx.EmptyString, wx.ITEM_NORMAL)
-        self.m_menu1.AppendItem(self.m_menuItem_import)
-
-        self.m_menu1.AppendSeparator()
-        self.m_menuItem_exit = wx.MenuItem(self.m_menu1, wx.ID_EXIT, u"退出(&X)", wx.EmptyString, wx.ITEM_NORMAL)
-        self.m_menu1.AppendItem(self.m_menuItem_exit)
-
-        self.m_menubar1.Append(self.m_menu1, u"文件(&F)")
-
-        self.m_menu2 = wx.Menu()
-        self.m_menuItem_about = wx.MenuItem(self.m_menu2, wx.ID_ABOUT, u"关于(&A)", wx.EmptyString, wx.ITEM_NORMAL)
-        self.m_menu2.AppendItem(self.m_menuItem_about)
-        self.m_menuItem_homepage = wx.MenuItem(self.m_menu2, wx.ID_ANY, u"主页(&H)", wx.EmptyString, wx.ITEM_NORMAL)
-        self.m_menu2.AppendItem(self.m_menuItem_homepage)
-        self.m_menuItem_feedback = wx.MenuItem(self.m_menu2, wx.ID_ANY, u"反馈建议(&F)", wx.EmptyString, wx.ITEM_NORMAL)
-        self.m_menu2.AppendItem(self.m_menuItem_feedback)
-        self.m_menuItem_chkUpdate = wx.MenuItem(self.m_menu2, wx.ID_ANY, u"检查更新(&U)", wx.EmptyString, wx.ITEM_NORMAL)
-        self.m_menu2.AppendItem(self.m_menuItem_chkUpdate)
-        self.m_menuItem_donate = wx.MenuItem(self.m_menu2, wx.ID_ANY, u"捐赠(&D)", wx.EmptyString, wx.ITEM_NORMAL)
-        self.m_menu2.AppendItem(self.m_menuItem_donate)
-
-        self.m_menubar1.Append(self.m_menu2, u"帮助(&H)")
-
-        self.SetMenuBar(self.m_menubar1)
-
-        bSizer1 = wx.BoxSizer(wx.VERTICAL)
-
-        self.m_panel1 = wx.Panel(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL)
-        bSizer4 = wx.BoxSizer(wx.HORIZONTAL)
-
-        bSizer5 = wx.BoxSizer(wx.VERTICAL)
-
-        self.m_tree = wx.TreeCtrl(self.m_panel1, wx.ID_ANY, wx.DefaultPosition, wx.Size(200, -1),
-            style=wx.TR_DEFAULT_STYLE|wx.NO_BORDER|wx.TR_NO_LINES\
-                |wx.TR_FULL_ROW_HIGHLIGHT#|wx.TR_HIDE_ROOT
-        )
-
-        self.m_tree.SetBackgroundColour(wx.Colour(218, 223, 230))
-        self.m_tree_root = self.m_tree.AddRoot(u"hosts")
-        self.m_tree_common = self.m_tree.AppendItem(self.m_tree_root, lang.trans("common_hosts"))
-        self.m_tree_origin = self.m_tree.AppendItem(self.m_tree_root, lang.trans("origin_hosts"))
-        self.m_tree_local = self.m_tree.AppendItem(self.m_tree_root, lang.trans("local_hosts"))
-        self.m_tree_online = self.m_tree.AppendItem(self.m_tree_root, lang.trans("online_hosts"))
-        self.m_tree.SetItemTextColour(self.m_tree_root, "#999999")
-        self.m_tree.SetItemTextColour(self.m_tree_common, "#3333ff")
-        self.m_tree.SetItemTextColour(self.m_tree_local, "#999999")
-        self.m_tree.SetItemTextColour(self.m_tree_online, "#999999")
-        self.m_tree.ExpandAll()
-        bSizer5.Add(self.m_tree, 1, wx.ALL | wx.EXPAND, 0)
-
-        self.image_list = wx.ImageList(16, 16)
-        self.ico_folder_idx = self.image_list.Add(
-            wx.ArtProvider.GetBitmap(wx.ART_FOLDER, wx.ART_OTHER, (16, 16))
-        )
-        self.ico_folder_open_idx = self.image_list.Add(
-            wx.ArtProvider.GetBitmap(wx.ART_FILE_OPEN, wx.ART_OTHER, (16, 16))
-        )
-        self.ico_file_idx = self.image_list.Add(
-            wx.ArtProvider.GetBitmap(wx.ART_NORMAL_FILE, wx.ART_OTHER, (16, 16))
-        )
-        self.ico_colors_idx = []
-        for i, icon in enumerate(co.ICONS):
-            self.ico_colors_idx.append(self.image_list.Add(co.GetMondrianBitmap(i)))
-
-        self.m_tree.AssignImageList(self.image_list)
-
-        for item_idx in (self.m_tree_root, self.m_tree_local, self.m_tree_online):
-            self.m_tree.SetItemImage(item_idx, self.ico_folder_idx, wx.TreeItemIcon_Normal)
-            self.m_tree.SetItemImage(item_idx, self.ico_folder_open_idx, wx.TreeItemIcon_Expanded)
-
-        self.m_staticline_left_bottom = wx.StaticLine(self.m_panel1, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize,
-            wx.LI_HORIZONTAL)
-        bSizer5.Add(self.m_staticline_left_bottom, 0, wx.EXPAND | wx.ALL, 0)
-
-        bSizer61 = wx.BoxSizer(wx.HORIZONTAL)
-
-        self.m_btn_add = wx.BitmapButton(self.m_panel1, wx.ID_ADD,
-            co.GetMondrianBitmap(fn="add"),
-            wx.DefaultPosition,
-            wx.DefaultSize, wx.BU_AUTODRAW|wx.NO_BORDER)
-        self.m_btn_add.SetToolTipString(u"添加")
-        bSizer61.Add(self.m_btn_add, 0, wx.EXPAND|wx.TOP|wx.BOTTOM|wx.LEFT, 5)
-
-        self.m_btn_refresh = wx.BitmapButton(self.m_panel1, wx.ID_REFRESH,
-            co.GetMondrianBitmap(fn="arrow_refresh"),
-            wx.DefaultPosition,
-            wx.DefaultSize, wx.BU_AUTODRAW|wx.NO_BORDER)
-        self.m_btn_add.SetToolTipString(u"刷新")
-        bSizer61.Add(self.m_btn_refresh, 0, wx.EXPAND|wx.TOP|wx.BOTTOM|wx.LEFT, 5)
-
-        self.m_btn_edit_info = wx.BitmapButton(self.m_panel1, wx.ID_EDIT,
-            co.GetMondrianBitmap(fn="pencil"),
-            wx.DefaultPosition,
-            wx.DefaultSize, wx.BU_AUTODRAW|wx.NO_BORDER)
-        self.m_btn_add.SetToolTipString(u"编辑")
-        bSizer61.Add(self.m_btn_edit_info, 0, wx.EXPAND|wx.TOP|wx.BOTTOM|wx.LEFT, 5)
-
-        self.m_btn_del = wx.BitmapButton(self.m_panel1, wx.ID_DELETE,
-            co.GetMondrianBitmap(fn="delete"),
-            wx.DefaultPosition,
-            wx.DefaultSize, wx.BU_AUTODRAW|wx.NO_BORDER)
-        self.m_btn_del.SetToolTipString(u"删除")
-        bSizer61.Add(self.m_btn_del, 0, wx.EXPAND|wx.TOP|wx.BOTTOM|wx.LEFT, 5)
-
-        bSizer5.Add(bSizer61, 0, wx.EXPAND, 5)
-
-        bSizer4.Add(bSizer5, 1, wx.EXPAND, 5)
-
-        self.m_staticline_main = wx.StaticLine(self.m_panel1, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize,
-            wx.LI_VERTICAL)
-        bSizer4.Add(self.m_staticline_main, 0, wx.EXPAND | wx.ALL, 0)
-
-        bSizer6 = wx.BoxSizer(wx.VERTICAL)
-
-        self.m_textCtrl_content = self.makeTextCtrl(bSizer6)
-
-        bSizer7 = wx.BoxSizer(wx.HORIZONTAL)
-
-        self.m_panel3 = wx.Panel(self.m_panel1, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL)
-        bSizer71 = wx.BoxSizer(wx.HORIZONTAL)
-
-#        self.m_btn_save = buttons.GenBitmapTextButton(self.m_panel3, wx.ID_SAVE, co.GetMondrianBitmap(fn="disk"), u"保存")
-#        bSizer71.Add(self.m_btn_save, 0, wx.ALL, 0)
-
-        self.m_panel3.SetSizer(bSizer71)
-        self.m_panel3.Layout()
-        bSizer71.Fit(self.m_panel3)
-        bSizer7.Add(self.m_panel3, 1, wx.EXPAND | wx.ALL, 5)
-
-#        self.m_btn_apply = buttons.GenBitmapTextButton(self.m_panel1, wx.ID_APPLY,
-#            co.GetMondrianBitmap(fn="accept"), u"应用",
-#            size=wx.Size(-1, 24),
-#            style=wx.BU_AUTODRAW|wx.STATIC_BORDER)
-        #        self.m_btn_apply = wx.Button(self.m_panel1, wx.ID_APPLY, u"应用", wx.DefaultPosition, wx.DefaultSize, 0)
-        self.m_btn_apply = wx.BitmapButton(self.m_panel1, wx.ID_APPLY,
-            co.GetMondrianBitmap(fn="accept"),
-            wx.DefaultPosition,
-            wx.Size(60, -1), wx.BU_AUTODRAW|wx.SIMPLE_BORDER)
-        self.m_btn_apply.SetToolTipString(u"应用当前 hosts 方案")
-        bSizer7.Add(self.m_btn_apply, 0, wx.ALL, 5)
-
-        if cls_TaskBarIcon and os.name == "nt":
-            # ubuntu 10.04 下点击这个图标时会报错,图标的菜单无法正常工作
-            # ubuntu 11.04 下这个图标总是无法显示
-            # 由于跨平台问题,暂时决定只在 windows 下显示快捷的任务栏图标
-            # 参见:http://stackoverflow.com/questions/7144756/wx-taskbaricon-on-ubuntu-11-04
-            self.m_btn_exit = buttons.GenBitmapTextButton(self.m_panel1, wx.ID_CLOSE, co.GetMondrianBitmap(fn="door"), u"隐藏")
-            #            self.m_btn_exit = wx.Button(self.m_panel1, wx.ID_CLOSE, u"隐藏", wx.DefaultPosition, wx.DefaultSize, 0)
-            bSizer7.Add(self.m_btn_exit, 0, wx.ALL, 5)
-
-        self.m_staticline_right_bottom = wx.StaticLine(self.m_panel1, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize,
-            wx.LI_HORIZONTAL)
-        bSizer6.Add(self.m_staticline_right_bottom, 0, wx.EXPAND | wx.ALL, 0)
-
-        bSizer6.Add(bSizer7, 0, wx.EXPAND, 5)
-
-        bSizer4.Add(bSizer6, 5, wx.EXPAND, 5)
-
-        self.m_panel1.SetSizer(bSizer4)
-        self.m_panel1.Layout()
-        bSizer4.Fit(self.m_panel1)
-        bSizer1.Add(self.m_panel1, 1, wx.EXPAND | wx.ALL, 0)
-
-        self.SetSizer(bSizer1)
-        self.Layout()
-
-        self.Centre(wx.BOTH)
-
-        self.font_bold = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
-        self.font_bold.SetWeight(wx.BOLD)
-        self.font_normal = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
-        self.font_normal.SetWeight(wx.NORMAL)
-
-        self.font_mono = wx.Font(10, wx.ROMAN, wx.NORMAL, wx.NORMAL, faceName="Courier New")
-
-
-    def alert(self, title, msg):
-        dlg = wx.MessageDialog(None, msg, title, wx.OK | wx.ICON_WARNING)
-        dlg.ShowModal()
-        dlg.Destroy()
-
-
-    def makeTextCtrl(self, container):
-
-        from HostsCtrl import HostsCtrl
-
-        txt_ctrl = HostsCtrl(
-            self.m_panel1, self.ID_HOSTS_TEXT, #wx.EmptyString,
-            pos=wx.DefaultPosition,
-            size=wx.DefaultSize,
-            style=wx.TE_MULTILINE|wx.TE_RICH2|wx.TE_PROCESS_TAB|wx.HSCROLL|wx.NO_BORDER)
-        txt_ctrl.AutoCompSetMaxWidth(0)
-
-        container.Add(txt_ctrl, 1, wx.ALL | wx.EXPAND, 0)
-
-        return txt_ctrl
-
-
-    def OnClose(self, event):
-
-        self.Hide()
-        return False
-
-
-
-
-class AboutHtml(wx.html.HtmlWindow):
-
-    def __init__(self, parent, id=-1, size=(480, 360)):
-
-        wx.html.HtmlWindow.__init__(self, parent, id, size=size)
-        if "gtk2" in wx.PlatformInfo:
-            self.SetStandardFonts()
-
-
-    def OnLinkClicked(self, link):
-
-        wx.LaunchDefaultBrowser(link.GetHref())
-
-
-class AboutBox(wx.Dialog):
-    u"""关于对话框
-
-    参考自:http://wiki.wxpython.org/wxPython%20by%20Example
-    """
-
-    def __init__(self, version=None, latest_stable_version=None):
-
-        wx.Dialog.__init__(self, None, -1, u"关于",
-                style=wx.DEFAULT_DIALOG_STYLE|wx.THICK_FRAME|wx.TAB_TRAVERSAL
-            )
-
-        update_version = u"欢迎使用!"
-        co.log([version, latest_stable_version])
-        if latest_stable_version and latest_stable_version != "0":
-            cv = co.compareVersion(version, latest_stable_version)
-            if cv < 0:
-                update_version = u"更新的稳定版 v%s 已经发布!" % latest_stable_version
-            else:
-                update_version = u"您正在使用最新稳定版本。"
-            
-
-        hwin = AboutHtml(self)
-        hwin.SetPage(u"""
-            <font size="9" color="#44474D"><b>SwitchHosts!</b></font><br />
-            <font size="3" color="#44474D">%(version)s</font><br /><br />
-            <font size="3" color="#909090"><i>%(update_version)s</i></font><br />
-            <p>
-                本程序用于在多个 hosts 之间快速切换。
-            </p>
-            <p>
-                主页:<a href="http://oldj.github.io/SwitchHosts/">http://oldj.github.io/SwitchHosts/</a><br />
-                <!--源码:<a href="https://github.com/oldj/SwitchHosts">https://github.com/oldj/SwitchHosts</a><br />-->
-                作者:<a href="http://oldj.net">oldj</a><br />
-                <br />
-                以下网友对本软件也有贡献:<br />
-                <a href="http://weibo.com/charlestang">@charlestang</a>,
-                <a href="http://weibo.com/allenm56">@allenm</a>,
-                <a href="http://www.weibo.com/emersonli">@emersonli</a>,
-                <a href="https://github.com/qiyuan4f">@qiyuan4f</a> <br />
-                <br />
-                <font color="#909090">本程序完全免费,如果您觉得它还不错,欢迎<a href="https://me.alipay.com/oldj">捐赠</a>支持作者,谢谢!</font>
-            </p>
-        """ % {
-            "version": version,
-            "update_version": update_version,
-        })
-
-        hwin.FindWindowById(wx.ID_OK)
-        irep = hwin.GetInternalRepresentation()
-        hwin.SetSize((irep.GetWidth() + 25, irep.GetHeight() + 30))
-        self.SetClientSize(hwin.GetSize())
-        self.CenterOnParent(wx.BOTH)
-        self.SetFocus()
-
-
-class Dlg_addHosts(wx.Dialog):
-
-    def __init__( self, parent ):
-        wx.Dialog.__init__(self, parent, id=wx.ID_ANY, title=wx.EmptyString, pos=wx.DefaultPosition,
-            size=wx.Size(400, 200), style=wx.DEFAULT_DIALOG_STYLE)
-
-        self.SetSizeHintsSz(wx.DefaultSize, wx.DefaultSize)
-
-        bSizer9 = wx.BoxSizer(wx.VERTICAL)
-
-        self.m_panel9 = wx.Panel(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL)
-        bSizer10 = wx.BoxSizer(wx.VERTICAL)
-
-        bSizer231 = wx.BoxSizer(wx.HORIZONTAL)
-
-        self.m_radioBtn_local = wx.RadioButton(self.m_panel9, wx.ID_ANY, lang.trans("local_hosts"), wx.DefaultPosition, wx.DefaultSize, 0)
-        self.m_radioBtn_local.SetValue(True)
-        bSizer231.Add(self.m_radioBtn_local, 0, wx.ALL, 5)
-
-        self.m_radioBtn_online = wx.RadioButton(self.m_panel9, wx.ID_ANY, lang.trans("online_hosts"), wx.DefaultPosition, wx.DefaultSize,
-            0)
-        bSizer231.Add(self.m_radioBtn_online, 0, wx.ALL, 5)
-
-        bSizer10.Add(bSizer231, 1, wx.EXPAND, 5)
-
-        bSizer111 = wx.BoxSizer(wx.HORIZONTAL)
-
-        self.m_staticText21 = wx.StaticText(self.m_panel9, wx.ID_ANY, u"方案名:", wx.DefaultPosition, wx.Size(60, -1), 0)
-        self.m_staticText21.Wrap(-1)
-        bSizer111.Add(self.m_staticText21, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
-
-        self.m_textCtrl_title = wx.TextCtrl(self.m_panel9, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize
-            , 0)
-        self.m_textCtrl_title.SetMaxLength(32)
-        self.m_textCtrl_title.SetToolTipString(u"在这儿输入方案名称。")
-
-        bSizer111.Add(self.m_textCtrl_title, 1, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
-
-        bSizer10.Add(bSizer111, 1, wx.EXPAND, 5)
-
-        bSizer1612 = wx.BoxSizer(wx.HORIZONTAL)
-
-        self.m_staticText512 = wx.StaticText(self.m_panel9, wx.ID_ANY, u"URL:", wx.DefaultPosition, wx.Size(60, -1), 0)
-        self.m_staticText512.Wrap(-1)
-        bSizer1612.Add(self.m_staticText512, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
-
-        self.m_textCtrl_url = wx.TextCtrl(self.m_panel9, wx.ID_ANY, u"http://", wx.DefaultPosition, wx.DefaultSize, 0)
-        self.m_textCtrl_url.SetMaxLength(1024)
-        self.m_textCtrl_url.Enable(False)
-        self.m_textCtrl_url.SetToolTipString(u"在这儿输入方案的url地址,如:\nhttp://192.168.1.100/hosts/sample.hosts 。")
-
-        bSizer1612.Add(self.m_textCtrl_url, 1, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
-
-        bSizer10.Add(bSizer1612, 1, wx.EXPAND, 5)
-
-        self.m_panel9.SetSizer(bSizer10)
-        self.m_panel9.Layout()
-        bSizer10.Fit(self.m_panel9)
-        bSizer9.Add(self.m_panel9, 2, wx.EXPAND | wx.ALL, 5)
-
-        self.m_staticline211 = wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL)
-        bSizer9.Add(self.m_staticline211, 0, wx.EXPAND | wx.ALL, 5)
-
-        m_sdbSizer1 = wx.StdDialogButtonSizer()
-        self.m_sdbSizer1OK = wx.Button(self, wx.ID_OK)
-        m_sdbSizer1.AddButton(self.m_sdbSizer1OK)
-        self.m_sdbSizer1Cancel = wx.Button(self, wx.ID_CANCEL)
-        m_sdbSizer1.AddButton(self.m_sdbSizer1Cancel)
-        m_sdbSizer1.Realize()
-        bSizer9.Add(m_sdbSizer1, 1, wx.EXPAND, 5)
-
-        self.SetSizer(bSizer9)
-        self.Layout()
-
-        self.Centre(wx.BOTH)
-
-        self.__binds()
-
-
-    def __del__( self ):
-        pass
-
-
-    def __binds(self):
-
-        self.Bind(wx.EVT_RADIOBUTTON, self.switchToLocal, self.m_radioBtn_local)
-        self.Bind(wx.EVT_RADIOBUTTON, self.switchToOnline, self.m_radioBtn_online)
-
-
-    def switchToLocal(self, event):
-
-#        print("local!")
-        self.m_textCtrl_url.Enabled = False
-
-
-    def switchToOnline(self, event):
-
-#        print("online!")
-        self.m_textCtrl_url.Enabled = True
-
-
-class Dlg_Import(wx.Dialog):
-
-    def __init__( self, parent ):
-
-        wx.Dialog.__init__(self, parent, id=wx.ID_ANY, title=wx.EmptyString, pos=wx.DefaultPosition,
-            size=wx.Size(400, 200), style=wx.DEFAULT_DIALOG_STYLE)
-
-        self.SetSizeHintsSz(wx.DefaultSize, wx.DefaultSize)
-
-        bSizer6 = wx.BoxSizer(wx.VERTICAL)
-
-        self.m_notebook = wx.Notebook(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, 0)
-        self.m_panel_local = wx.Panel(self.m_notebook, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL)
-        bSizer8 = wx.BoxSizer(wx.VERTICAL)
-
-        self.m_staticText4 = wx.StaticText(self.m_panel_local, wx.ID_ANY, u"请选择档案文件:", wx.DefaultPosition,
-            wx.DefaultSize, 0)
-        self.m_staticText4.Wrap(-1)
-        bSizer8.Add(self.m_staticText4, 0, wx.ALL, 5)
-
-        self.m_filePicker = wx.FilePickerCtrl(self.m_panel_local, wx.ID_ANY, wx.EmptyString, u"Select a file", u"*.*",
-            wx.DefaultPosition, wx.Size(180, -1), wx.FLP_DEFAULT_STYLE)
-        bSizer8.Add(self.m_filePicker, 0, wx.ALL | wx.ALIGN_CENTER_HORIZONTAL | wx.EXPAND, 5)
-
-        self.m_panel_local.SetSizer(bSizer8)
-        self.m_panel_local.Layout()
-        bSizer8.Fit(self.m_panel_local)
-        self.m_notebook.AddPage(self.m_panel_local, u"本地档案", False)
-        self.m_panel_online = wx.Panel(self.m_notebook, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize,
-            wx.TAB_TRAVERSAL)
-        bSizer9 = wx.BoxSizer(wx.VERTICAL)
-
-        self.m_staticText41 = wx.StaticText(self.m_panel_online, wx.ID_ANY, u"请输入档案URL:", wx.DefaultPosition,
-            wx.DefaultSize, 0)
-        self.m_staticText41.Wrap(-1)
-        bSizer9.Add(self.m_staticText41, 0, wx.ALL, 5)
-
-        self.m_textCtrl_url = wx.TextCtrl(self.m_panel_online, wx.ID_ANY, u"http://", wx.DefaultPosition, wx.DefaultSize
-            , 0)
-        bSizer9.Add(self.m_textCtrl_url, 0, wx.ALL | wx.EXPAND, 5)
-
-        self.m_panel_online.SetSizer(bSizer9)
-        self.m_panel_online.Layout()
-        bSizer9.Fit(self.m_panel_online)
-        self.m_notebook.AddPage(self.m_panel_online, u"在线档案", False)
-
-        bSizer6.Add(self.m_notebook, 4, wx.EXPAND | wx.ALL, 5)
-
-        self.m_panel2 = wx.Panel(self, wx.ID_ANY, wx.DefaultPosition, wx.Size(-1, 60), wx.TAB_TRAVERSAL)
-        bSizer7 = wx.BoxSizer(wx.VERTICAL)
-
-        m_sdbSizer3 = wx.StdDialogButtonSizer()
-        self.m_sdbSizer3OK = wx.Button(self.m_panel2, wx.ID_OK)
-        m_sdbSizer3.AddButton(self.m_sdbSizer3OK)
-        self.m_sdbSizer3Cancel = wx.Button(self.m_panel2, wx.ID_CANCEL)
-        m_sdbSizer3.AddButton(self.m_sdbSizer3Cancel)
-        m_sdbSizer3.Realize()
-        bSizer7.Add(m_sdbSizer3, 1, wx.EXPAND, 5)
-
-        self.m_panel2.SetSizer(bSizer7)
-        self.m_panel2.Layout()
-        bSizer6.Add(self.m_panel2, 1, wx.EXPAND | wx.ALL, 5)
-
-        self.SetSizer(bSizer6)
-        self.Layout()
-
-        self.Centre(wx.BOTH)
-
-    def __del__( self ):
-        pass
-
-
-

+ 0 - 34
legacy/v2/src/setup.py

@@ -1,34 +0,0 @@
-"""
-This is a setup.py script generated by py2applet
-
-Usage:
-    python setup.py py2app
-"""
-
-from setuptools import setup
-from libs.VERSION import VERSION
-
-APP = ["SwitchHosts.py"]
-DATA_FILES = ["img/logo.png"]
-
-setup(
-    app=APP,
-    data_files=DATA_FILES,
-    options={
-        "py2app": {
-            "argv_emulation": False,
-            "includes": ["wx"],
-            "iconfile": "img/logo.icns",
-            "resources": [],
-            "plist": {
-                "CFBundleName": "SwitchHosts!",
-                "CFBundleShortVersionString": VERSION,  # must be in X.X.X format
-                "CFBundleGetInfoString": "SwitchHosts! %s" % VERSION,
-                "CFBundleExecutable": "SwitchHosts!",
-                "CFBundleIdentifier": "net.oldj.switchhosts",
-                },
-            },
-        },
-    setup_requires=["py2app"],
-)
-

二進制
legacy/v2/ui/img/accept.png


二進制
legacy/v2/ui/img/add.png


二進制
legacy/v2/ui/img/asterisk_yellow.png


二進制
legacy/v2/ui/img/delete.png


二進制
legacy/v2/ui/img/disk.png


二進制
legacy/v2/ui/img/door.png


二進制
legacy/v2/ui/img/icon_0.ico


二進制
legacy/v2/ui/img/icon_0.png


二進制
legacy/v2/ui/img/icon_1.png


二進制
legacy/v2/ui/img/icon_2.png


二進制
legacy/v2/ui/img/icon_3.png


二進制
legacy/v2/ui/img/icon_4.png


二進制
legacy/v2/ui/img/icon_5.png


二進制
legacy/v2/ui/img/icon_6.png


+ 0 - 19
legacy/v2/ui/img/mkicon.py

@@ -1,19 +0,0 @@
-# -*- coding: utf-8 -*-
-
-def main():
-
-    icons = []
-
-    for i in range(7):
-        fn = "icon_%d.ico" % i
-        c = open(fn, "rb").read()
-        icons.append(c)
-
-    open("icons.py", "w").write(repr(icons))
-
-
-if __name__ == "__main__":
-
-    main()
-
-

+ 0 - 23
legacy/v2/ui/img/mkicon2.py

@@ -1,23 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import glob
-
-def main():
-
-    icons2 = {}
-
-    for fn in glob.glob("*.png"):
-        if fn.startswith("icon_"):
-            continue
-
-        c = open(fn, "rb").read()
-        icons2[fn.partition(".")[0]] = c
-
-    open("icons.py", "w").write(repr(icons2))
-
-
-if __name__ == "__main__":
-
-    main()
-
-

二進制
legacy/v2/ui/img/pencil.png


+ 0 - 848
legacy/v2/ui/main.fbp

@@ -1,848 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
-<wxFormBuilder_Project>
-    <FileVersion major="1" minor="10" />
-    <object class="Project" expanded="1">
-        <property name="class_decoration"></property>
-        <property name="code_generation">C++</property>
-        <property name="disconnect_events">1</property>
-        <property name="disconnect_mode">source_name</property>
-        <property name="disconnect_python_events">0</property>
-        <property name="encoding">UTF-8</property>
-        <property name="event_generation">connect</property>
-        <property name="file"></property>
-        <property name="first_id">1000</property>
-        <property name="help_provider">none</property>
-        <property name="internationalize">0</property>
-        <property name="name">MyProject1</property>
-        <property name="namespace"></property>
-        <property name="path">.</property>
-        <property name="precompiled_header"></property>
-        <property name="relative_path">1</property>
-        <property name="skip_python_events">1</property>
-        <property name="use_enum">0</property>
-        <property name="use_microsoft_bom">0</property>
-        <object class="Frame" expanded="1">
-            <property name="bg"></property>
-            <property name="center">wxBOTH</property>
-            <property name="context_help"></property>
-            <property name="context_menu">1</property>
-            <property name="enabled">1</property>
-            <property name="event_handler">impl_virtual</property>
-            <property name="extra_style"></property>
-            <property name="fg"></property>
-            <property name="font"></property>
-            <property name="hidden">0</property>
-            <property name="id">wxID_ANY</property>
-            <property name="maximum_size"></property>
-            <property name="minimum_size">400,300</property>
-            <property name="name">MyFrame1</property>
-            <property name="pos"></property>
-            <property name="size">640,480</property>
-            <property name="style">wxDEFAULT_FRAME_STYLE</property>
-            <property name="subclass"></property>
-            <property name="title"></property>
-            <property name="tooltip"></property>
-            <property name="validator_data_type"></property>
-            <property name="validator_style">wxFILTER_NONE</property>
-            <property name="validator_type">wxDefaultValidator</property>
-            <property name="validator_variable"></property>
-            <property name="window_extra_style"></property>
-            <property name="window_name"></property>
-            <property name="window_style">wxTAB_TRAVERSAL</property>
-            <property name="xrc_skip_sizer">1</property>
-            <event name="OnActivate"></event>
-            <event name="OnActivateApp"></event>
-            <event name="OnChar"></event>
-            <event name="OnClose"></event>
-            <event name="OnEnterWindow"></event>
-            <event name="OnEraseBackground"></event>
-            <event name="OnHibernate"></event>
-            <event name="OnIconize"></event>
-            <event name="OnIdle"></event>
-            <event name="OnKeyDown"></event>
-            <event name="OnKeyUp"></event>
-            <event name="OnKillFocus"></event>
-            <event name="OnLeaveWindow"></event>
-            <event name="OnLeftDClick"></event>
-            <event name="OnLeftDown"></event>
-            <event name="OnLeftUp"></event>
-            <event name="OnMiddleDClick"></event>
-            <event name="OnMiddleDown"></event>
-            <event name="OnMiddleUp"></event>
-            <event name="OnMotion"></event>
-            <event name="OnMouseEvents"></event>
-            <event name="OnMouseWheel"></event>
-            <event name="OnPaint"></event>
-            <event name="OnRightDClick"></event>
-            <event name="OnRightDown"></event>
-            <event name="OnRightUp"></event>
-            <event name="OnSetFocus"></event>
-            <event name="OnSize"></event>
-            <event name="OnUpdateUI"></event>
-            <object class="wxMenuBar" expanded="1">
-                <property name="bg"></property>
-                <property name="context_help"></property>
-                <property name="context_menu">1</property>
-                <property name="enabled">1</property>
-                <property name="fg"></property>
-                <property name="font"></property>
-                <property name="hidden">0</property>
-                <property name="id">wxID_ANY</property>
-                <property name="label">MyMenuBar</property>
-                <property name="maximum_size"></property>
-                <property name="minimum_size"></property>
-                <property name="name">m_menubar1</property>
-                <property name="permission">protected</property>
-                <property name="pos"></property>
-                <property name="size"></property>
-                <property name="style"></property>
-                <property name="subclass"></property>
-                <property name="tooltip"></property>
-                <property name="validator_data_type"></property>
-                <property name="validator_style">wxFILTER_NONE</property>
-                <property name="validator_type">wxDefaultValidator</property>
-                <property name="validator_variable"></property>
-                <property name="window_extra_style"></property>
-                <property name="window_name"></property>
-                <property name="window_style"></property>
-                <event name="OnChar"></event>
-                <event name="OnEnterWindow"></event>
-                <event name="OnEraseBackground"></event>
-                <event name="OnKeyDown"></event>
-                <event name="OnKeyUp"></event>
-                <event name="OnKillFocus"></event>
-                <event name="OnLeaveWindow"></event>
-                <event name="OnLeftDClick"></event>
-                <event name="OnLeftDown"></event>
-                <event name="OnLeftUp"></event>
-                <event name="OnMiddleDClick"></event>
-                <event name="OnMiddleDown"></event>
-                <event name="OnMiddleUp"></event>
-                <event name="OnMotion"></event>
-                <event name="OnMouseEvents"></event>
-                <event name="OnMouseWheel"></event>
-                <event name="OnPaint"></event>
-                <event name="OnRightDClick"></event>
-                <event name="OnRightDown"></event>
-                <event name="OnRightUp"></event>
-                <event name="OnSetFocus"></event>
-                <event name="OnSize"></event>
-                <event name="OnUpdateUI"></event>
-                <object class="wxMenu" expanded="0">
-                    <property name="label">文件(&amp;F)</property>
-                    <property name="name">m_menu1</property>
-                    <property name="permission">protected</property>
-                    <object class="wxMenuItem" expanded="1">
-                        <property name="bitmap"></property>
-                        <property name="checked">0</property>
-                        <property name="enabled">1</property>
-                        <property name="help"></property>
-                        <property name="id">wxID_ANY</property>
-                        <property name="kind">wxITEM_NORMAL</property>
-                        <property name="label">新建(&amp;N)</property>
-                        <property name="name">m_menuItem_new</property>
-                        <property name="permission">none</property>
-                        <property name="shortcut"></property>
-                        <property name="unchecked_bitmap"></property>
-                        <event name="OnMenuSelection"></event>
-                        <event name="OnUpdateUI"></event>
-                    </object>
-                    <object class="separator" expanded="1">
-                        <property name="name">m_separator1</property>
-                        <property name="permission">none</property>
-                    </object>
-                    <object class="wxMenuItem" expanded="0">
-                        <property name="bitmap"></property>
-                        <property name="checked">0</property>
-                        <property name="enabled">1</property>
-                        <property name="help"></property>
-                        <property name="id">wxID_EXIT</property>
-                        <property name="kind">wxITEM_NORMAL</property>
-                        <property name="label">退出(&amp;X)</property>
-                        <property name="name">m_menuItem_exit</property>
-                        <property name="permission">none</property>
-                        <property name="shortcut"></property>
-                        <property name="unchecked_bitmap"></property>
-                        <event name="OnMenuSelection"></event>
-                        <event name="OnUpdateUI"></event>
-                    </object>
-                </object>
-                <object class="wxMenu" expanded="1">
-                    <property name="label">帮助(&amp;H)</property>
-                    <property name="name">m_menu2</property>
-                    <property name="permission">protected</property>
-                    <object class="wxMenuItem" expanded="0">
-                        <property name="bitmap"></property>
-                        <property name="checked">0</property>
-                        <property name="enabled">1</property>
-                        <property name="help"></property>
-                        <property name="id">wxID_ABOUT</property>
-                        <property name="kind">wxITEM_NORMAL</property>
-                        <property name="label">关于(&amp;A)</property>
-                        <property name="name">m_menuItem_about</property>
-                        <property name="permission">none</property>
-                        <property name="shortcut"></property>
-                        <property name="unchecked_bitmap"></property>
-                        <event name="OnMenuSelection"></event>
-                        <event name="OnUpdateUI"></event>
-                    </object>
-                </object>
-            </object>
-            <object class="wxBoxSizer" expanded="1">
-                <property name="minimum_size"></property>
-                <property name="name">bSizer1</property>
-                <property name="orient">wxVERTICAL</property>
-                <property name="permission">none</property>
-                <object class="sizeritem" expanded="1">
-                    <property name="border">0</property>
-                    <property name="flag">wxEXPAND | wxALL</property>
-                    <property name="proportion">1</property>
-                    <object class="wxPanel" expanded="1">
-                        <property name="bg"></property>
-                        <property name="context_help"></property>
-                        <property name="context_menu">1</property>
-                        <property name="enabled">1</property>
-                        <property name="fg"></property>
-                        <property name="font"></property>
-                        <property name="hidden">0</property>
-                        <property name="id">wxID_ANY</property>
-                        <property name="maximum_size"></property>
-                        <property name="minimum_size"></property>
-                        <property name="name">m_panel1</property>
-                        <property name="permission">protected</property>
-                        <property name="pos"></property>
-                        <property name="size"></property>
-                        <property name="subclass"></property>
-                        <property name="tooltip"></property>
-                        <property name="validator_data_type"></property>
-                        <property name="validator_style">wxFILTER_NONE</property>
-                        <property name="validator_type">wxDefaultValidator</property>
-                        <property name="validator_variable"></property>
-                        <property name="window_extra_style"></property>
-                        <property name="window_name"></property>
-                        <property name="window_style">wxTAB_TRAVERSAL</property>
-                        <event name="OnChar"></event>
-                        <event name="OnEnterWindow"></event>
-                        <event name="OnEraseBackground"></event>
-                        <event name="OnKeyDown"></event>
-                        <event name="OnKeyUp"></event>
-                        <event name="OnKillFocus"></event>
-                        <event name="OnLeaveWindow"></event>
-                        <event name="OnLeftDClick"></event>
-                        <event name="OnLeftDown"></event>
-                        <event name="OnLeftUp"></event>
-                        <event name="OnMiddleDClick"></event>
-                        <event name="OnMiddleDown"></event>
-                        <event name="OnMiddleUp"></event>
-                        <event name="OnMotion"></event>
-                        <event name="OnMouseEvents"></event>
-                        <event name="OnMouseWheel"></event>
-                        <event name="OnPaint"></event>
-                        <event name="OnRightDClick"></event>
-                        <event name="OnRightDown"></event>
-                        <event name="OnRightUp"></event>
-                        <event name="OnSetFocus"></event>
-                        <event name="OnSize"></event>
-                        <event name="OnUpdateUI"></event>
-                        <object class="wxBoxSizer" expanded="1">
-                            <property name="minimum_size"></property>
-                            <property name="name">bSizer4</property>
-                            <property name="orient">wxHORIZONTAL</property>
-                            <property name="permission">none</property>
-                            <object class="sizeritem" expanded="1">
-                                <property name="border">5</property>
-                                <property name="flag">wxEXPAND</property>
-                                <property name="proportion">0</property>
-                                <object class="wxBoxSizer" expanded="1">
-                                    <property name="minimum_size"></property>
-                                    <property name="name">bSizer5</property>
-                                    <property name="orient">wxVERTICAL</property>
-                                    <property name="permission">none</property>
-                                    <object class="sizeritem" expanded="0">
-                                        <property name="border">5</property>
-                                        <property name="flag">wxALL|wxEXPAND</property>
-                                        <property name="proportion">1</property>
-                                        <object class="wxListCtrl" expanded="0">
-                                            <property name="bg"></property>
-                                            <property name="context_help"></property>
-                                            <property name="context_menu">1</property>
-                                            <property name="enabled">1</property>
-                                            <property name="fg"></property>
-                                            <property name="font"></property>
-                                            <property name="hidden">0</property>
-                                            <property name="id">wxID_ANY</property>
-                                            <property name="maximum_size"></property>
-                                            <property name="minimum_size"></property>
-                                            <property name="name">m_list</property>
-                                            <property name="permission">protected</property>
-                                            <property name="pos"></property>
-                                            <property name="size">160,320</property>
-                                            <property name="style">wxLC_REPORT|wxLC_SORT_ASCENDING</property>
-                                            <property name="subclass"></property>
-                                            <property name="tooltip"></property>
-                                            <property name="validator_data_type"></property>
-                                            <property name="validator_style">wxFILTER_NONE</property>
-                                            <property name="validator_type">wxDefaultValidator</property>
-                                            <property name="validator_variable"></property>
-                                            <property name="window_extra_style"></property>
-                                            <property name="window_name"></property>
-                                            <property name="window_style"></property>
-                                            <event name="OnChar"></event>
-                                            <event name="OnEnterWindow"></event>
-                                            <event name="OnEraseBackground"></event>
-                                            <event name="OnKeyDown"></event>
-                                            <event name="OnKeyUp"></event>
-                                            <event name="OnKillFocus"></event>
-                                            <event name="OnLeaveWindow"></event>
-                                            <event name="OnLeftDClick"></event>
-                                            <event name="OnLeftDown"></event>
-                                            <event name="OnLeftUp"></event>
-                                            <event name="OnListBeginDrag"></event>
-                                            <event name="OnListBeginLabelEdit"></event>
-                                            <event name="OnListBeginRDrag"></event>
-                                            <event name="OnListCacheHint"></event>
-                                            <event name="OnListColBeginDrag"></event>
-                                            <event name="OnListColClick"></event>
-                                            <event name="OnListColDragging"></event>
-                                            <event name="OnListColEndDrag"></event>
-                                            <event name="OnListColRightClick"></event>
-                                            <event name="OnListDeleteAllItems"></event>
-                                            <event name="OnListDeleteItem"></event>
-                                            <event name="OnListEndLabelEdit"></event>
-                                            <event name="OnListInsertItem"></event>
-                                            <event name="OnListItemActivated"></event>
-                                            <event name="OnListItemDeselected"></event>
-                                            <event name="OnListItemFocused"></event>
-                                            <event name="OnListItemMiddleClick"></event>
-                                            <event name="OnListItemRightClick"></event>
-                                            <event name="OnListItemSelected"></event>
-                                            <event name="OnListKeyDown"></event>
-                                            <event name="OnMiddleDClick"></event>
-                                            <event name="OnMiddleDown"></event>
-                                            <event name="OnMiddleUp"></event>
-                                            <event name="OnMotion"></event>
-                                            <event name="OnMouseEvents"></event>
-                                            <event name="OnMouseWheel"></event>
-                                            <event name="OnPaint"></event>
-                                            <event name="OnRightDClick"></event>
-                                            <event name="OnRightDown"></event>
-                                            <event name="OnRightUp"></event>
-                                            <event name="OnSetFocus"></event>
-                                            <event name="OnSize"></event>
-                                            <event name="OnUpdateUI"></event>
-                                        </object>
-                                    </object>
-                                    <object class="sizeritem" expanded="1">
-                                        <property name="border">5</property>
-                                        <property name="flag">wxEXPAND</property>
-                                        <property name="proportion">0</property>
-                                        <object class="wxBoxSizer" expanded="1">
-                                            <property name="minimum_size"></property>
-                                            <property name="name">bSizer61</property>
-                                            <property name="orient">wxHORIZONTAL</property>
-                                            <property name="permission">none</property>
-                                            <object class="sizeritem" expanded="1">
-                                                <property name="border">5</property>
-                                                <property name="flag">wxALL</property>
-                                                <property name="proportion">0</property>
-                                                <object class="wxBitmapButton" expanded="1">
-                                                    <property name="bg"></property>
-                                                    <property name="bitmap"></property>
-                                                    <property name="context_help"></property>
-                                                    <property name="context_menu">1</property>
-                                                    <property name="default">0</property>
-                                                    <property name="disabled"></property>
-                                                    <property name="enabled">1</property>
-                                                    <property name="fg"></property>
-                                                    <property name="focus"></property>
-                                                    <property name="font"></property>
-                                                    <property name="hidden">0</property>
-                                                    <property name="hover"></property>
-                                                    <property name="id">wxID_ANY</property>
-                                                    <property name="label">MyButton</property>
-                                                    <property name="maximum_size"></property>
-                                                    <property name="minimum_size"></property>
-                                                    <property name="name">m_btn_add</property>
-                                                    <property name="permission">protected</property>
-                                                    <property name="pos"></property>
-                                                    <property name="selected"></property>
-                                                    <property name="size"></property>
-                                                    <property name="style">wxBU_AUTODRAW</property>
-                                                    <property name="subclass"></property>
-                                                    <property name="tooltip"></property>
-                                                    <property name="validator_data_type"></property>
-                                                    <property name="validator_style">wxFILTER_NONE</property>
-                                                    <property name="validator_type">wxDefaultValidator</property>
-                                                    <property name="validator_variable"></property>
-                                                    <property name="window_extra_style"></property>
-                                                    <property name="window_name"></property>
-                                                    <property name="window_style"></property>
-                                                    <event name="OnButtonClick"></event>
-                                                    <event name="OnChar"></event>
-                                                    <event name="OnEnterWindow"></event>
-                                                    <event name="OnEraseBackground"></event>
-                                                    <event name="OnKeyDown"></event>
-                                                    <event name="OnKeyUp"></event>
-                                                    <event name="OnKillFocus"></event>
-                                                    <event name="OnLeaveWindow"></event>
-                                                    <event name="OnLeftDClick"></event>
-                                                    <event name="OnLeftDown"></event>
-                                                    <event name="OnLeftUp"></event>
-                                                    <event name="OnMiddleDClick"></event>
-                                                    <event name="OnMiddleDown"></event>
-                                                    <event name="OnMiddleUp"></event>
-                                                    <event name="OnMotion"></event>
-                                                    <event name="OnMouseEvents"></event>
-                                                    <event name="OnMouseWheel"></event>
-                                                    <event name="OnPaint"></event>
-                                                    <event name="OnRightDClick"></event>
-                                                    <event name="OnRightDown"></event>
-                                                    <event name="OnRightUp"></event>
-                                                    <event name="OnSetFocus"></event>
-                                                    <event name="OnSize"></event>
-                                                    <event name="OnUpdateUI"></event>
-                                                </object>
-                                            </object>
-                                            <object class="sizeritem" expanded="1">
-                                                <property name="border">5</property>
-                                                <property name="flag">wxALL</property>
-                                                <property name="proportion">0</property>
-                                                <object class="wxBitmapButton" expanded="1">
-                                                    <property name="bg"></property>
-                                                    <property name="bitmap"></property>
-                                                    <property name="context_help"></property>
-                                                    <property name="context_menu">1</property>
-                                                    <property name="default">0</property>
-                                                    <property name="disabled"></property>
-                                                    <property name="enabled">1</property>
-                                                    <property name="fg"></property>
-                                                    <property name="focus"></property>
-                                                    <property name="font"></property>
-                                                    <property name="hidden">0</property>
-                                                    <property name="hover"></property>
-                                                    <property name="id">wxID_ANY</property>
-                                                    <property name="label">MyButton</property>
-                                                    <property name="maximum_size"></property>
-                                                    <property name="minimum_size"></property>
-                                                    <property name="name">m_btn_del</property>
-                                                    <property name="permission">protected</property>
-                                                    <property name="pos"></property>
-                                                    <property name="selected"></property>
-                                                    <property name="size"></property>
-                                                    <property name="style">wxBU_AUTODRAW</property>
-                                                    <property name="subclass"></property>
-                                                    <property name="tooltip"></property>
-                                                    <property name="validator_data_type"></property>
-                                                    <property name="validator_style">wxFILTER_NONE</property>
-                                                    <property name="validator_type">wxDefaultValidator</property>
-                                                    <property name="validator_variable"></property>
-                                                    <property name="window_extra_style"></property>
-                                                    <property name="window_name"></property>
-                                                    <property name="window_style"></property>
-                                                    <event name="OnButtonClick"></event>
-                                                    <event name="OnChar"></event>
-                                                    <event name="OnEnterWindow"></event>
-                                                    <event name="OnEraseBackground"></event>
-                                                    <event name="OnKeyDown"></event>
-                                                    <event name="OnKeyUp"></event>
-                                                    <event name="OnKillFocus"></event>
-                                                    <event name="OnLeaveWindow"></event>
-                                                    <event name="OnLeftDClick"></event>
-                                                    <event name="OnLeftDown"></event>
-                                                    <event name="OnLeftUp"></event>
-                                                    <event name="OnMiddleDClick"></event>
-                                                    <event name="OnMiddleDown"></event>
-                                                    <event name="OnMiddleUp"></event>
-                                                    <event name="OnMotion"></event>
-                                                    <event name="OnMouseEvents"></event>
-                                                    <event name="OnMouseWheel"></event>
-                                                    <event name="OnPaint"></event>
-                                                    <event name="OnRightDClick"></event>
-                                                    <event name="OnRightDown"></event>
-                                                    <event name="OnRightUp"></event>
-                                                    <event name="OnSetFocus"></event>
-                                                    <event name="OnSize"></event>
-                                                    <event name="OnUpdateUI"></event>
-                                                </object>
-                                            </object>
-                                        </object>
-                                    </object>
-                                </object>
-                            </object>
-                            <object class="sizeritem" expanded="1">
-                                <property name="border">5</property>
-                                <property name="flag">wxEXPAND</property>
-                                <property name="proportion">1</property>
-                                <object class="wxBoxSizer" expanded="1">
-                                    <property name="minimum_size"></property>
-                                    <property name="name">bSizer6</property>
-                                    <property name="orient">wxVERTICAL</property>
-                                    <property name="permission">none</property>
-                                    <object class="sizeritem" expanded="1">
-                                        <property name="border">5</property>
-                                        <property name="flag">wxEXPAND | wxALL</property>
-                                        <property name="proportion">1</property>
-                                        <object class="wxPanel" expanded="1">
-                                            <property name="bg"></property>
-                                            <property name="context_help"></property>
-                                            <property name="context_menu">1</property>
-                                            <property name="enabled">1</property>
-                                            <property name="fg"></property>
-                                            <property name="font"></property>
-                                            <property name="hidden">0</property>
-                                            <property name="id">wxID_ANY</property>
-                                            <property name="maximum_size"></property>
-                                            <property name="minimum_size"></property>
-                                            <property name="name">m_panel31</property>
-                                            <property name="permission">protected</property>
-                                            <property name="pos"></property>
-                                            <property name="size"></property>
-                                            <property name="subclass"></property>
-                                            <property name="tooltip"></property>
-                                            <property name="validator_data_type"></property>
-                                            <property name="validator_style">wxFILTER_NONE</property>
-                                            <property name="validator_type">wxDefaultValidator</property>
-                                            <property name="validator_variable"></property>
-                                            <property name="window_extra_style"></property>
-                                            <property name="window_name"></property>
-                                            <property name="window_style">wxTAB_TRAVERSAL</property>
-                                            <event name="OnChar"></event>
-                                            <event name="OnEnterWindow"></event>
-                                            <event name="OnEraseBackground"></event>
-                                            <event name="OnKeyDown"></event>
-                                            <event name="OnKeyUp"></event>
-                                            <event name="OnKillFocus"></event>
-                                            <event name="OnLeaveWindow"></event>
-                                            <event name="OnLeftDClick"></event>
-                                            <event name="OnLeftDown"></event>
-                                            <event name="OnLeftUp"></event>
-                                            <event name="OnMiddleDClick"></event>
-                                            <event name="OnMiddleDown"></event>
-                                            <event name="OnMiddleUp"></event>
-                                            <event name="OnMotion"></event>
-                                            <event name="OnMouseEvents"></event>
-                                            <event name="OnMouseWheel"></event>
-                                            <event name="OnPaint"></event>
-                                            <event name="OnRightDClick"></event>
-                                            <event name="OnRightDown"></event>
-                                            <event name="OnRightUp"></event>
-                                            <event name="OnSetFocus"></event>
-                                            <event name="OnSize"></event>
-                                            <event name="OnUpdateUI"></event>
-                                        </object>
-                                    </object>
-                                    <object class="sizeritem" expanded="0">
-                                        <property name="border">5</property>
-                                        <property name="flag">wxALL|wxEXPAND</property>
-                                        <property name="proportion">1</property>
-                                        <object class="wxTextCtrl" expanded="0">
-                                            <property name="bg"></property>
-                                            <property name="context_help"></property>
-                                            <property name="context_menu">1</property>
-                                            <property name="enabled">1</property>
-                                            <property name="fg"></property>
-                                            <property name="font">Courier New,90,90,-1,70,0</property>
-                                            <property name="hidden">0</property>
-                                            <property name="id">wxID_ANY</property>
-                                            <property name="maximum_size"></property>
-                                            <property name="maxlength">0</property>
-                                            <property name="minimum_size"></property>
-                                            <property name="name">m_textCtrl_content</property>
-                                            <property name="permission">protected</property>
-                                            <property name="pos"></property>
-                                            <property name="size"></property>
-                                            <property name="style">wxHSCROLL|wxTE_MULTILINE</property>
-                                            <property name="subclass"></property>
-                                            <property name="tooltip"></property>
-                                            <property name="validator_data_type"></property>
-                                            <property name="validator_style">wxFILTER_NONE</property>
-                                            <property name="validator_type">wxDefaultValidator</property>
-                                            <property name="validator_variable"></property>
-                                            <property name="value"></property>
-                                            <property name="window_extra_style"></property>
-                                            <property name="window_name"></property>
-                                            <property name="window_style"></property>
-                                            <event name="OnChar"></event>
-                                            <event name="OnEnterWindow"></event>
-                                            <event name="OnEraseBackground"></event>
-                                            <event name="OnKeyDown"></event>
-                                            <event name="OnKeyUp"></event>
-                                            <event name="OnKillFocus"></event>
-                                            <event name="OnLeaveWindow"></event>
-                                            <event name="OnLeftDClick"></event>
-                                            <event name="OnLeftDown"></event>
-                                            <event name="OnLeftUp"></event>
-                                            <event name="OnMiddleDClick"></event>
-                                            <event name="OnMiddleDown"></event>
-                                            <event name="OnMiddleUp"></event>
-                                            <event name="OnMotion"></event>
-                                            <event name="OnMouseEvents"></event>
-                                            <event name="OnMouseWheel"></event>
-                                            <event name="OnPaint"></event>
-                                            <event name="OnRightDClick"></event>
-                                            <event name="OnRightDown"></event>
-                                            <event name="OnRightUp"></event>
-                                            <event name="OnSetFocus"></event>
-                                            <event name="OnSize"></event>
-                                            <event name="OnText"></event>
-                                            <event name="OnTextEnter"></event>
-                                            <event name="OnTextMaxLen"></event>
-                                            <event name="OnTextURL"></event>
-                                            <event name="OnUpdateUI"></event>
-                                        </object>
-                                    </object>
-                                    <object class="sizeritem" expanded="1">
-                                        <property name="border">5</property>
-                                        <property name="flag">wxEXPAND</property>
-                                        <property name="proportion">0</property>
-                                        <object class="wxBoxSizer" expanded="1">
-                                            <property name="minimum_size"></property>
-                                            <property name="name">bSizer7</property>
-                                            <property name="orient">wxHORIZONTAL</property>
-                                            <property name="permission">none</property>
-                                            <object class="sizeritem" expanded="1">
-                                                <property name="border">5</property>
-                                                <property name="flag">wxEXPAND | wxALL</property>
-                                                <property name="proportion">1</property>
-                                                <object class="wxPanel" expanded="1">
-                                                    <property name="bg"></property>
-                                                    <property name="context_help"></property>
-                                                    <property name="context_menu">1</property>
-                                                    <property name="enabled">1</property>
-                                                    <property name="fg"></property>
-                                                    <property name="font"></property>
-                                                    <property name="hidden">0</property>
-                                                    <property name="id">wxID_ANY</property>
-                                                    <property name="maximum_size"></property>
-                                                    <property name="minimum_size"></property>
-                                                    <property name="name">m_panel3</property>
-                                                    <property name="permission">protected</property>
-                                                    <property name="pos"></property>
-                                                    <property name="size"></property>
-                                                    <property name="subclass"></property>
-                                                    <property name="tooltip"></property>
-                                                    <property name="validator_data_type"></property>
-                                                    <property name="validator_style">wxFILTER_NONE</property>
-                                                    <property name="validator_type">wxDefaultValidator</property>
-                                                    <property name="validator_variable"></property>
-                                                    <property name="window_extra_style"></property>
-                                                    <property name="window_name"></property>
-                                                    <property name="window_style">wxTAB_TRAVERSAL</property>
-                                                    <event name="OnChar"></event>
-                                                    <event name="OnEnterWindow"></event>
-                                                    <event name="OnEraseBackground"></event>
-                                                    <event name="OnKeyDown"></event>
-                                                    <event name="OnKeyUp"></event>
-                                                    <event name="OnKillFocus"></event>
-                                                    <event name="OnLeaveWindow"></event>
-                                                    <event name="OnLeftDClick"></event>
-                                                    <event name="OnLeftDown"></event>
-                                                    <event name="OnLeftUp"></event>
-                                                    <event name="OnMiddleDClick"></event>
-                                                    <event name="OnMiddleDown"></event>
-                                                    <event name="OnMiddleUp"></event>
-                                                    <event name="OnMotion"></event>
-                                                    <event name="OnMouseEvents"></event>
-                                                    <event name="OnMouseWheel"></event>
-                                                    <event name="OnPaint"></event>
-                                                    <event name="OnRightDClick"></event>
-                                                    <event name="OnRightDown"></event>
-                                                    <event name="OnRightUp"></event>
-                                                    <event name="OnSetFocus"></event>
-                                                    <event name="OnSize"></event>
-                                                    <event name="OnUpdateUI"></event>
-                                                    <object class="wxBoxSizer" expanded="1">
-                                                        <property name="minimum_size"></property>
-                                                        <property name="name">bSizer71</property>
-                                                        <property name="orient">wxHORIZONTAL</property>
-                                                        <property name="permission">none</property>
-                                                        <object class="sizeritem" expanded="1">
-                                                            <property name="border">0</property>
-                                                            <property name="flag">wxALL</property>
-                                                            <property name="proportion">0</property>
-                                                            <object class="wxBitmapButton" expanded="1">
-                                                                <property name="bg"></property>
-                                                                <property name="bitmap"></property>
-                                                                <property name="context_help"></property>
-                                                                <property name="context_menu">1</property>
-                                                                <property name="default">0</property>
-                                                                <property name="disabled"></property>
-                                                                <property name="enabled">1</property>
-                                                                <property name="fg"></property>
-                                                                <property name="focus"></property>
-                                                                <property name="font"></property>
-                                                                <property name="hidden">0</property>
-                                                                <property name="hover"></property>
-                                                                <property name="id">wxID_ANY</property>
-                                                                <property name="label">保存</property>
-                                                                <property name="maximum_size"></property>
-                                                                <property name="minimum_size"></property>
-                                                                <property name="name">m_btn_save</property>
-                                                                <property name="permission">protected</property>
-                                                                <property name="pos"></property>
-                                                                <property name="selected"></property>
-                                                                <property name="size"></property>
-                                                                <property name="style">wxBU_AUTODRAW</property>
-                                                                <property name="subclass"></property>
-                                                                <property name="tooltip"></property>
-                                                                <property name="validator_data_type"></property>
-                                                                <property name="validator_style">wxFILTER_NONE</property>
-                                                                <property name="validator_type">wxDefaultValidator</property>
-                                                                <property name="validator_variable"></property>
-                                                                <property name="window_extra_style"></property>
-                                                                <property name="window_name"></property>
-                                                                <property name="window_style"></property>
-                                                                <event name="OnButtonClick"></event>
-                                                                <event name="OnChar"></event>
-                                                                <event name="OnEnterWindow"></event>
-                                                                <event name="OnEraseBackground"></event>
-                                                                <event name="OnKeyDown"></event>
-                                                                <event name="OnKeyUp"></event>
-                                                                <event name="OnKillFocus"></event>
-                                                                <event name="OnLeaveWindow"></event>
-                                                                <event name="OnLeftDClick"></event>
-                                                                <event name="OnLeftDown"></event>
-                                                                <event name="OnLeftUp"></event>
-                                                                <event name="OnMiddleDClick"></event>
-                                                                <event name="OnMiddleDown"></event>
-                                                                <event name="OnMiddleUp"></event>
-                                                                <event name="OnMotion"></event>
-                                                                <event name="OnMouseEvents"></event>
-                                                                <event name="OnMouseWheel"></event>
-                                                                <event name="OnPaint"></event>
-                                                                <event name="OnRightDClick"></event>
-                                                                <event name="OnRightDown"></event>
-                                                                <event name="OnRightUp"></event>
-                                                                <event name="OnSetFocus"></event>
-                                                                <event name="OnSize"></event>
-                                                                <event name="OnUpdateUI"></event>
-                                                            </object>
-                                                        </object>
-                                                    </object>
-                                                </object>
-                                            </object>
-                                            <object class="sizeritem" expanded="0">
-                                                <property name="border">5</property>
-                                                <property name="flag">wxALL</property>
-                                                <property name="proportion">0</property>
-                                                <object class="wxButton" expanded="0">
-                                                    <property name="bg"></property>
-                                                    <property name="context_help"></property>
-                                                    <property name="context_menu">1</property>
-                                                    <property name="default">0</property>
-                                                    <property name="enabled">1</property>
-                                                    <property name="fg"></property>
-                                                    <property name="font"></property>
-                                                    <property name="hidden">0</property>
-                                                    <property name="id">wxID_APPLY</property>
-                                                    <property name="label">应用</property>
-                                                    <property name="maximum_size"></property>
-                                                    <property name="minimum_size"></property>
-                                                    <property name="name">m_btn_apply</property>
-                                                    <property name="permission">protected</property>
-                                                    <property name="pos"></property>
-                                                    <property name="size"></property>
-                                                    <property name="style"></property>
-                                                    <property name="subclass"></property>
-                                                    <property name="tooltip"></property>
-                                                    <property name="validator_data_type"></property>
-                                                    <property name="validator_style">wxFILTER_NONE</property>
-                                                    <property name="validator_type">wxDefaultValidator</property>
-                                                    <property name="validator_variable"></property>
-                                                    <property name="window_extra_style"></property>
-                                                    <property name="window_name"></property>
-                                                    <property name="window_style"></property>
-                                                    <event name="OnButtonClick"></event>
-                                                    <event name="OnChar"></event>
-                                                    <event name="OnEnterWindow"></event>
-                                                    <event name="OnEraseBackground"></event>
-                                                    <event name="OnKeyDown"></event>
-                                                    <event name="OnKeyUp"></event>
-                                                    <event name="OnKillFocus"></event>
-                                                    <event name="OnLeaveWindow"></event>
-                                                    <event name="OnLeftDClick"></event>
-                                                    <event name="OnLeftDown"></event>
-                                                    <event name="OnLeftUp"></event>
-                                                    <event name="OnMiddleDClick"></event>
-                                                    <event name="OnMiddleDown"></event>
-                                                    <event name="OnMiddleUp"></event>
-                                                    <event name="OnMotion"></event>
-                                                    <event name="OnMouseEvents"></event>
-                                                    <event name="OnMouseWheel"></event>
-                                                    <event name="OnPaint"></event>
-                                                    <event name="OnRightDClick"></event>
-                                                    <event name="OnRightDown"></event>
-                                                    <event name="OnRightUp"></event>
-                                                    <event name="OnSetFocus"></event>
-                                                    <event name="OnSize"></event>
-                                                    <event name="OnUpdateUI"></event>
-                                                </object>
-                                            </object>
-                                            <object class="sizeritem" expanded="0">
-                                                <property name="border">5</property>
-                                                <property name="flag">wxALL</property>
-                                                <property name="proportion">0</property>
-                                                <object class="wxButton" expanded="0">
-                                                    <property name="bg"></property>
-                                                    <property name="context_help"></property>
-                                                    <property name="context_menu">1</property>
-                                                    <property name="default">0</property>
-                                                    <property name="enabled">1</property>
-                                                    <property name="fg"></property>
-                                                    <property name="font"></property>
-                                                    <property name="hidden">0</property>
-                                                    <property name="id">wxID_CLOSE</property>
-                                                    <property name="label">关闭</property>
-                                                    <property name="maximum_size"></property>
-                                                    <property name="minimum_size"></property>
-                                                    <property name="name">m_btn_exit</property>
-                                                    <property name="permission">protected</property>
-                                                    <property name="pos"></property>
-                                                    <property name="size"></property>
-                                                    <property name="style"></property>
-                                                    <property name="subclass"></property>
-                                                    <property name="tooltip"></property>
-                                                    <property name="validator_data_type"></property>
-                                                    <property name="validator_style">wxFILTER_NONE</property>
-                                                    <property name="validator_type">wxDefaultValidator</property>
-                                                    <property name="validator_variable"></property>
-                                                    <property name="window_extra_style"></property>
-                                                    <property name="window_name"></property>
-                                                    <property name="window_style"></property>
-                                                    <event name="OnButtonClick"></event>
-                                                    <event name="OnChar"></event>
-                                                    <event name="OnEnterWindow"></event>
-                                                    <event name="OnEraseBackground"></event>
-                                                    <event name="OnKeyDown"></event>
-                                                    <event name="OnKeyUp"></event>
-                                                    <event name="OnKillFocus"></event>
-                                                    <event name="OnLeaveWindow"></event>
-                                                    <event name="OnLeftDClick"></event>
-                                                    <event name="OnLeftDown"></event>
-                                                    <event name="OnLeftUp"></event>
-                                                    <event name="OnMiddleDClick"></event>
-                                                    <event name="OnMiddleDown"></event>
-                                                    <event name="OnMiddleUp"></event>
-                                                    <event name="OnMotion"></event>
-                                                    <event name="OnMouseEvents"></event>
-                                                    <event name="OnMouseWheel"></event>
-                                                    <event name="OnPaint"></event>
-                                                    <event name="OnRightDClick"></event>
-                                                    <event name="OnRightDown"></event>
-                                                    <event name="OnRightUp"></event>
-                                                    <event name="OnSetFocus"></event>
-                                                    <event name="OnSize"></event>
-                                                    <event name="OnUpdateUI"></event>
-                                                </object>
-                                            </object>
-                                        </object>
-                                    </object>
-                                </object>
-                            </object>
-                        </object>
-                    </object>
-                </object>
-            </object>
-        </object>
-    </object>
-</wxFormBuilder_Project>

+ 0 - 13
legacy/v3.0/app/config.js

@@ -1,13 +0,0 @@
-/**
- * @author oldj
- * @blog http://oldj.net
- */
-
-"use strict";
-
-module.exports = {
-    VERSION: '3.0.0'
-    , url_chk_version: 'http://oldj.github.io/SwitchHosts/v.txt'
-    , url_homepage: 'http://oldj.github.io/SwitchHosts/'
-    , url_feedback: 'https://github.com/oldj/SwitchHosts/issues'
-};

+ 0 - 39
legacy/v3.0/app/css/iconfont/iconfont.css

@@ -1,39 +0,0 @@
-
-@font-face {font-family: "iconfont";
-  src: url('iconfont.eot'); /* IE9*/
-  src: url('iconfont.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
-  url('iconfont.woff') format('woff'), /* chrome, firefox */
-  url('iconfont.ttf') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
-  url('iconfont.svg#iconfont') format('svg'); /* iOS 4.1- */
-}
-
-.iconfont {
-  font-family:"iconfont" !important;
-  font-size:16px;
-  font-style:normal;
-  -webkit-font-smoothing: antialiased;
-  -webkit-text-stroke-width: 0.2px;
-  -moz-osx-font-smoothing: grayscale;
-}
-.icon-switchoff:before { content: "\e60d"; }
-.icon-icon:before { content: "\e600"; }
-.icon-warnfill:before { content: "\e607"; }
-.icon-warn:before { content: "\e608"; }
-.icon-off:before { content: "\e613"; }
-.icon-on:before { content: "\e614"; }
-.icon-edit:before { content: "\e609"; }
-.icon-info:before { content: "\e601"; }
-.icon-add-s:before { content: "\e612"; }
-.icon-more:before { content: "\e602"; }
-.icon-grid:before { content: "\e603"; }
-.icon-movedown:before { content: "\e60a"; }
-.icon-moveup:before { content: "\e60b"; }
-.icon-add:before { content: "\e60c"; }
-.icon-folder:before { content: "\e604"; }
-.icon-timescircle:before { content: "\e60e"; }
-.icon-move:before { content: "\e60f"; }
-.icon-delete:before { content: "\e610"; }
-.icon-doc:before { content: "\e606"; }
-.icon-line:before { content: "\e611"; }
-.icon-switchon:before { content: "\e615"; }
-.icon-sysserver:before { content: "\e605"; }

二進制
legacy/v3.0/app/css/iconfont/iconfont.eot


+ 0 - 111
legacy/v3.0/app/css/iconfont/iconfont.svg

@@ -1,111 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
-<svg xmlns="http://www.w3.org/2000/svg">
-<metadata>
-Created by FontForge 20120731 at Thu Nov 26 19:05:35 2015
- By Ads
-</metadata>
-<defs>
-<font id="iconfont" horiz-adv-x="1024" >
-  <font-face 
-    font-family="iconfont"
-    font-weight="500"
-    font-stretch="normal"
-    units-per-em="1024"
-    panose-1="2 0 6 3 0 0 0 0 0 0"
-    ascent="896"
-    descent="-128"
-    x-height="792"
-    bbox="0 -212 1024 896"
-    underline-thickness="50"
-    underline-position="-100"
-    unicode-range="U+0078-E615"
-  />
-<missing-glyph horiz-adv-x="374" 
-d="M34 0v682h272v-682h-272zM68 34h204v614h-204v-614z" />
-    <glyph glyph-name=".notdef" horiz-adv-x="374" 
-d="M34 0v682h272v-682h-272zM68 34h204v614h-204v-614z" />
-    <glyph glyph-name=".null" horiz-adv-x="0" 
- />
-    <glyph glyph-name="nonmarkingreturn" horiz-adv-x="341" 
- />
-    <glyph glyph-name="x" unicode="x" horiz-adv-x="1001" 
-d="M281 543q-27 -1 -53 -1h-83q-18 0 -36.5 -6t-32.5 -18.5t-23 -32t-9 -45.5v-76h912v41q0 16 -0.5 30t-0.5 18q0 13 -5 29t-17 29.5t-31.5 22.5t-49.5 9h-133v-97h-438v97zM955 310v-52q0 -23 0.5 -52t0.5 -58t-10.5 -47.5t-26 -30t-33 -16t-31.5 -4.5q-14 -1 -29.5 -0.5
-t-29.5 0.5h-32l-45 128h-439l-44 -128h-29h-34q-20 0 -45 1q-25 0 -41 9.5t-25.5 23t-13.5 29.5t-4 30v167h911zM163 247q-12 0 -21 -8.5t-9 -21.5t9 -21.5t21 -8.5q13 0 22 8.5t9 21.5t-9 21.5t-22 8.5zM316 123q-8 -26 -14 -48q-5 -19 -10.5 -37t-7.5 -25t-3 -15t1 -14.5
-t9.5 -10.5t21.5 -4h37h67h81h80h64h36q23 0 34 12t2 38q-5 13 -9.5 30.5t-9.5 34.5q-5 19 -11 39h-368zM336 498v228q0 11 2.5 23t10 21.5t20.5 15.5t34 6h188q31 0 51.5 -14.5t20.5 -52.5v-227h-327z" />
-    <glyph glyph-name="uniE600" unicode="&#xe600;" 
-d="M488 745l132 -269l297 -43l-215 -209l51 -296l-265 140l-266 -140l51 296l-215 209l297 43z" />
-    <glyph glyph-name="uniE601" unicode="&#xe601;" 
-d="M512 -20q-110 0 -203 54t-147 147t-54 203t54 203t147 147t203 54t203 -54t147 -147t54 -203t-54 -203t-147 -147t-203 -54zM567 605q0 7 -5.5 12.5t-12.5 5.5h-74q-7 0 -12.5 -5.5t-5.5 -12.5v-74q0 -4 1.5 -7t4 -5.5t5.5 -4t7 -1.5h74q7 0 12.5 5t5.5 13v74zM567 402
-q0 5 -2.5 9.5t-6.5 7t-9 2.5h-74q-7 0 -12.5 -5.5t-5.5 -13.5v-239q0 -5 2.5 -9t6.5 -6.5t9 -2.5h74q7 0 12.5 5.5t5.5 12.5v239z" />
-    <glyph glyph-name="uniE602" unicode="&#xe602;" 
-d="M174.5 501q-41.5 0 -71 -29.5t-29.5 -71.5q0 -27 13.5 -50.5t36.5 -37t50.5 -13.5t51 13.5t37 37t13.5 50.5q0 42 -30 71.5t-71.5 29.5zM511 501q-42 0 -71.5 -29.5t-29.5 -71.5q0 -27 13.5 -50.5t37 -37t50.5 -13.5q42 0 71.5 29.5t29.5 71.5q0 10 -2 20t-6 19
-t-9.5 17.5t-12 15t-14.5 12t-17 9.5t-19 6t-21 2zM848 501q-42 0 -71.5 -29.5t-29.5 -71.5t29.5 -71.5t71.5 -29.5t71.5 29.5t29.5 71.5t-29.5 71.5t-71.5 29.5z" />
-    <glyph glyph-name="uniE603" unicode="&#xe603;" 
-d="M601 830h-179q-12 0 -21 -9t-9 -21v-179q0 -12 9 -21t21 -9h179q12 0 21 9t9 21v179q0 6 -2.5 11.5t-6.5 9.5t-9.5 6.5t-11.5 2.5zM929 830h-179q-12 0 -21 -9t-9 -21v-179q0 -12 9 -21t21 -9h179q8 0 15 4t11 11t4 15v179q0 12 -9 21t-21 9zM273 830h-179q-12 0 -21 -9
-t-9 -21v-179q0 -12 9 -21t21 -9h179q6 0 11.5 2.5t9.5 6.5t6.5 9.5t2.5 11.5v179q0 3 -1 6.5t-2.5 6.5t-3.5 5.5t-4.5 4.5t-5.5 3.5t-6.5 2.5t-6.5 1zM601 502h-179q-12 0 -21 -9t-9 -21v-179q0 -13 9 -21.5t21 -8.5h179q12 0 21 8.5t9 21.5v179q0 6 -2.5 11.5t-6.5 9.5
-t-9.5 6.5t-11.5 2.5zM929 502h-179q-12 0 -21 -9t-9 -21v-179q0 -8 4 -15t11 -11t15 -4h179q8 0 15 4t11 11t4 15v179q0 12 -9 21t-21 9zM273 502h-179q-8 0 -15 -4t-11 -11t-4 -15v-179q0 -13 9 -21.5t21 -8.5h179q12 0 21 8.5t9 21.5v179q0 8 -4 15t-11 11t-15 4zM601 174
-h-179q-12 0 -21 -9t-9 -21v-179q0 -13 9 -21.5t21 -8.5h179q6 0 11.5 2.5t9.5 6.5t6.5 9.5t2.5 11.5v179q0 6 -2.5 11.5t-6.5 9.5t-9.5 6.5t-11.5 2.5zM929 174h-179q-8 0 -15 -4t-11 -11t-4 -15v-179q0 -13 9 -21.5t21 -8.5h179q12 0 21 8.5t9 21.5v179q0 12 -9 21t-21 9z
-M273 174h-179q-6 0 -11.5 -2.5t-9.5 -6.5t-6.5 -9.5t-2.5 -11.5v-179q0 -8 4 -15t11 -11t15 -4h179q12 0 21 8.5t9 21.5v179q0 8 -4 15t-11 11t-15 4z" />
-    <glyph glyph-name="uniE604" unicode="&#xe604;" 
-d="M988 430v-402q0 -53 -37.5 -90.5t-90.5 -37.5h-694q-53 0 -90.5 37.5t-37.5 90.5v548q0 26 9.5 48.5t28.5 41.5q37 38 90 38h183q52 0 89.5 -38t37.5 -90v-19h384q26 0 49 -9t41 -28q38 -38 38 -90z" />
-    <glyph glyph-name="uniE605" unicode="&#xe605;" 
-d="M515 145q-36 0 -71 -12t-64 -41t-36 -69h338q-5 53 -57 87.5t-110 34.5zM955 157q-3 265 0 528q0 34 -12.5 47t-46.5 13q-45 -1 -384 -1t-390 1q-28 0 -40.5 -11t-12.5 -39q1 -231 0 -544q0 -18 4.5 -29.5t16 -17.5t30.5 -5q35 1 107 0.5t107 0.5q25 1 48 17
-q56 40 115.5 45t116.5 -28q63 -37 150 -35q94 2 132 0q33 -2 46 11t13 47zM892 213h-760v456h760v-456z" />
-    <glyph glyph-name="uniE606" unicode="&#xe606;" horiz-adv-x="1281" 
-d="M1280 422zM492 -7q2 -1 3.5 -2t5.5 -5.5t5.5 -9.5t-1.5 -11.5t-12 -13.5h-49h-68h-34q-4 0 -10.5 1.5t-24.5 9.5t-32 20.5t-26.5 38t-15.5 58.5v397l7 35q25 82 100 94h341l27 -8q74 -32 80 -128v-337q-1 -4 -2.5 -11.5t-11.5 -29.5t-24.5 -43t-43 -48t-65.5 -49h-1h-3
-h-5h-6h-6h-6h-6h-3h-1q-1 0 -2 0.5t-3.5 2.5t-4.5 4.5t-4 7t-2 9.5v32q0 19 1 37v18q0 1 0.5 4t2.5 11t5 15t9.5 17t14 17.5t20 13.5t27.5 9h81v326q0 3 -1 8.5t-5.5 20t-11.5 25.5t-21 21.5t-32 12.5h-332q-3 0 -7.5 -1t-16.5 -6t-21 -13.5t-17.5 -27.5t-10.5 -44l-1 -386
-l7 -32q19 -53 67 -60h40h40h34h24h8zM736 106h-70q-34 -10 -38 -49v-63l8 -1q5 0 34 29q37 37 66 84zM651 430q0 -10 -7.5 -17.5t-17.5 -7.5h-221q-7 0 -13 3.5t-9 9t-3 12.5q0 11 7.5 18.5t17.5 7.5h221q7 0 13 -3.5t9 -9.5t3 -13zM652 282q0 -11 -7.5 -18.5t-18.5 -7.5
-h-220q-11 0 -18.5 7.5t-7.5 18.5t7.5 18.5t18.5 7.5h220q11 0 18.5 -7.5t7.5 -18.5zM524 133q0 -11 -7.5 -19t-18.5 -8h-91q-11 0 -19 8t-8 19t8 19t19 8h91q11 0 18.5 -8t7.5 -19z" />
-    <glyph glyph-name="uniE607" unicode="&#xe607;" 
-d="M943 127l-341 609q-35 63 -90.5 63t-90.5 -63l-340 -609q-34 -62 -6 -111q29 -48 100 -48h674q71 0 99.5 48.5t-5.5 110.5zM480 576q0 13 9.5 22.5t22.5 9.5t22.5 -9.5t9.5 -22.5v-288q0 -13 -9.5 -22.5t-22.5 -9.5t-22.5 9.5t-9.5 22.5v288zM512 64q-13 0 -24 6.5
-t-17.5 17.5t-6.5 24q0 20 14 34t34 14t34 -14t14 -34t-14 -34t-34 -14z" />
-    <glyph glyph-name="uniE608" unicode="&#xe608;" 
-d="M849 -33h-674q-71 0 -99.5 49t5.5 111l340 609q35 63 91 63q13 0 25.5 -4t24 -12t22 -20t18.5 -27l341 -609q34 -63 5.5 -111.5t-99.5 -48.5zM512 735q-9 0 -18 -8t-17 -22l-340 -610q-17 -30 -7 -47t45 -17h674q35 0 45 17t-7 47l-341 610q-16 30 -34 30zM512 256
-q-13 0 -22.5 9.5t-9.5 22.5v288q0 13 9.5 22.5t22.5 9.5t22.5 -9.5t9.5 -22.5v-288q0 -13 -9.5 -22.5t-22.5 -9.5zM512 144zM464 144q0 20 14 34t34 14q13 0 24 -6.5t17.5 -17.5t6.5 -24q0 -20 -14 -34t-34 -14t-34 14t-14 34z" />
-    <glyph glyph-name="uniE609" unicode="&#xe609;" 
-d="M384 3l-169 169q-4 3 -5.5 8.5t0 10.5t5.5 9l380 380q4 4 9 5t10 0t9 -5l169 -169q4 -4 5 -9t0 -10t-5 -9l-380 -380q-6 -6 -14.5 -6t-13.5 6zM693 678q18 18 42.5 18t42.5 -18l112 -112q18 -18 18 -42.5t-18 -42.5l-56 -56l-197 197zM116 -96l56 254l198 -198z" />
-    <glyph glyph-name="uniE60A" unicode="&#xe60a;" 
-d="M768 108v384h-64v-384h-160l192 -192l192 192h-160zM320 556v-192h-192v192h192zM384 620h-320v-320h320v320zM64 172h96v-64h-96v64zM192 172h96v-64h-96v64zM320 172h64v-96h-64v96zM64 -52h64v-96h-64v96zM160 -84h96v-64h-96v64zM288 -84h96v-64h-96v64zM64 76h64
-v-96h-64v96zM320 44h64v-96h-64v96z" />
-    <glyph glyph-name="uniE60B" unicode="&#xe60b;" 
-d="M704 300v-384h64v384h160l-192 192l-192 -192h160zM64 620h96v-64h-96v64zM192 620h96v-64h-96v64zM320 620h64v-96h-64v96zM64 396h64v-96h-64v96zM160 364h96v-64h-96v64zM288 364h96v-64h-96v64zM64 524h64v-96h-64v96zM320 492h64v-96h-64v96zM320 108v-192h-192v192
-h192zM384 172h-320v-320h320v320z" />
-    <glyph glyph-name="uniE60C" unicode="&#xe60c;" 
-d="M512 -41q-115 0 -213 57t-155 155t-57 213t57 213t155 155t213 57t213 -57t155 -155t57 -213t-57 -213t-155 -155t-213 -57zM724 426h-170v170h-84v-170h-170v-84h170v-170h84v170h170v84z" />
-    <glyph glyph-name="uniE60D" unicode="&#xe60d;" 
-d="M832 812h-640q-80 0 -136 -56t-56 -136v-640q0 -79 56 -135.5t136 -56.5h640q79 0 135.5 56.5t56.5 135.5v640q0 80 -56.5 136t-135.5 56zM160 -84q-13 0 -22.5 9.5t-9.5 22.5t9.5 22.5t22.5 9.5t22.5 -9.5t9.5 -22.5t-9.5 -22.5t-22.5 -9.5zM160 620q-13 0 -22.5 9.5
-t-9.5 22.5t9.5 22.5t22.5 9.5t22.5 -9.5t9.5 -22.5t-9.5 -22.5t-22.5 -9.5zM704 -20q0 -27 -18.5 -45.5t-45.5 -18.5h-256q-27 0 -45.5 18.5t-18.5 45.5v640q0 26 19 45t45 19h256q27 0 45.5 -18.5t18.5 -45.5v-640zM864 -84q-13 0 -22.5 9.5t-9.5 22.5t9.5 22.5t22.5 9.5
-t22.5 -9.5t9.5 -22.5t-9.5 -22.5t-22.5 -9.5zM864 620q-13 0 -22.5 9.5t-9.5 22.5t9.5 22.5t22.5 9.5t22.5 -9.5t9.5 -22.5t-9.5 -22.5t-22.5 -9.5zM576 300h-128q-26 0 -45 -19t-19 -45v-192q0 -27 18.5 -45.5t45.5 -18.5h128q27 0 45.5 18.5t18.5 45.5v192
-q0 27 -18.5 45.5t-45.5 18.5z" />
-    <glyph glyph-name="uniE60E" unicode="&#xe60e;" 
-d="M657 171q0 15 -11 26l-104 103l104 103q11 11 11 26q0 16 -11 26l-52 52q-11 11 -26 11t-26 -11l-103 -104l-104 104q-10 11 -25 11q-16 0 -27 -11l-51 -52q-11 -10 -11 -26q0 -15 11 -26l103 -103l-103 -103q-11 -11 -11 -26q0 -16 11 -26l51 -52q11 -11 27 -11
-q15 0 25 11l104 104l103 -104q11 -11 26 -11t26 11l52 52q11 10 11 26zM878 300q0 -119 -59 -220t-160 -160t-220.5 -59t-220 59t-159.5 160t-59 220t59 220t159.5 160t220 59t220.5 -59t160 -160t59 -220z" />
-    <glyph glyph-name="uniE60F" unicode="&#xe60f;" 
-d="M1008 330l-156 155q-9 9 -21 12.5t-24 0t-21 -12.5q-14 -13 -14 -32.5t14 -33.5l76 -76h-303v309l76 -75q14 -14 33.5 -14t32.5 13q9 9 12.5 21.5t0 24.5t-12.5 21l-155 155q-7 7 -15.5 10.5t-17.5 3.5q-20 0 -33 -14l-156 -155q-9 -9 -12.5 -21t0 -24.5t12.5 -21.5
-q13 -13 32.5 -13t33.5 13l76 76v-309h-304l76 76q14 14 14 33.5t-14 32.5q-9 9 -21 12.5t-24 0t-21 -12.5l-156 -155q-13 -14 -13 -33.5t13 -32.5l156 -156q7 -7 15.5 -10.5t17.5 -3.5q6 0 12 1.5t11.5 4.5t9.5 8q9 9 12.5 21t0 24t-12.5 21l-76 76h304v-303l-76 76
-q-7 7 -15.5 10.5t-17.5 3.5t-18 -3.5t-15 -9.5q-14 -14 -14 -33.5t14 -33.5l155 -155q14 -14 33.5 -14t33.5 14l155 155q14 14 14 33.5t-13.5 33t-33 13.5t-33.5 -14l-76 -75v302h303l-76 -76q-7 -7 -10.5 -15.5t-3.5 -17.5t3.5 -17.5t10.5 -15.5q13 -14 33 -14q3 0 6 0.5
-t5.5 1t5.5 2t5.5 3t5.5 3.5t5 4l156 156q4 4 7 9.5t4.5 11t1.5 12.5q0 4 -1 8.5t-2.5 9t-4 8t-5.5 7.5z" />
-    <glyph glyph-name="uniE610" unicode="&#xe610;" 
-d="M924 573h-154v105q0 29 -20.5 49.5t-49.5 20.5h-376q-15 0 -28 -6t-22 -15t-14.5 -22t-5.5 -27v-105h-155q-14 -1 -24 -10q-10 -10 -10 -24.5t10 -24.5t24 -10h79v-581q0 -29 20.5 -49.5t49.5 -20.5h528q14 0 27 5.5t22.5 14.5t15 22t5.5 28v558v23h78q15 0 25 10
-t10 24.5t-10 24.5t-25 10zM412 -10q-9 0 -17 4.5t-12.5 12.5t-4.5 18l-1 372q0 7 3 13.5t7.5 11.5t11 7.5t13.5 2.5q15 0 25 -10t10 -25v-372q0 -15 -10 -25t-25 -10zM611.5 -10q-14.5 0 -24.5 10t-10 25v372q0 15 10 25t24.5 10t24.5 -10t10 -25l1 -372q0 -15 -10.5 -25
-t-25 -10zM323 635q0 17 13 30t31 13h290q18 0 31 -13t13 -30v-62h-378v62z" />
-    <glyph glyph-name="uniE611" unicode="&#xe611;" 
-d="M960 552q0 -17 -12 -29.5t-30 -12.5h-812q-7 0 -13.5 2t-11.5 6t-9 9t-6 11.5t-2 13.5t2 13.5t6 11.5t9 9t11.5 6t13.5 2h812q18 0 30 -12t12 -30zM960 300q0 -17 -12 -29.5t-30 -12.5h-812q-6 0 -11.5 1.5t-10 4t-8.5 6.5t-6.5 8.5t-4 10t-1.5 11.5q0 17 12 29.5
-t30 12.5h812q4 0 8.5 -1t8 -2.5t7 -3.5t6.5 -5t5 -6.5t3.5 -7t2.5 -8t1 -8.5zM960 48q0 -18 -12 -30t-30 -12h-812q-12 0 -21.5 5.5t-15 15t-5.5 21.5q0 17 12 29.5t30 12.5h812q29 0 39 -26q3 -9 3 -16z" />
-    <glyph glyph-name="uniE612" unicode="&#xe612;" 
-d="M699 358h-157v-158q0 -5 -2 -10t-5.5 -8.5t-8.5 -5.5t-10 -2q-11 0 -19 8t-8 18v158h-157q-11 0 -18.5 7.5t-7.5 18.5q0 7 3.5 13t9.5 9.5t13 3.5h157v157q0 11 8 18.5t19 7.5q5 0 10 -2t8.5 -5.5t5.5 -8.5t2 -10v-157h157q11 0 18.5 -7.5t7.5 -18.5t-7.5 -18.5
-t-18.5 -7.5z" />
-    <glyph glyph-name="uniE613" unicode="&#xe613;" 
-d="M729 90h-434q-116 0 -197.5 81.5t-81.5 196.5v32q0 115 81.5 196.5t197.5 81.5h434q116 0 197.5 -81.5t81.5 -196.5v-32q0 -115 -81.5 -196.5t-197.5 -81.5zM946 400q0 90 -63.5 153t-153.5 63h-434q-90 0 -153.5 -63t-63.5 -153v-32q0 -59 29 -109t79 -79t109 -29h434
-q90 0 153.5 63.5t63.5 153.5v32zM322 223q-44 0 -82 22.5t-60 60t-22 82.5q0 33 13 63.5t35 52.5t52.5 35t63.5 13q68 0 116 -48t48 -116t-48 -116.5t-116 -48.5z" />
-    <glyph glyph-name="uniE614" unicode="&#xe614;" 
-d="M729 90h-434q-116 0 -197.5 81.5t-81.5 196.5v32q0 115 81.5 196.5t197.5 81.5h434q116 0 197.5 -81.5t81.5 -196.5v-32q0 -115 -81.5 -196.5t-197.5 -81.5zM947 399q0 90 -63.5 153.5t-153.5 63.5h-436q-89 0 -152.5 -63.5t-63.5 -153.5v-31q0 -59 29 -109t79 -79
-t108 -29h436q90 0 153.5 63.5t63.5 153.5v31zM702 223q-44 0 -82 22t-60 60t-22 83q0 68 48 116t116 48t116.5 -48t48.5 -116q0 -17 -3.5 -33.5t-9.5 -31t-15 -27.5t-20.5 -24.5t-24.5 -20t-27.5 -15t-31 -10t-33.5 -3.5z" />
-    <glyph glyph-name="uniE615" unicode="&#xe615;" 
-d="M832 896h-640q-80 0 -136 -56t-56 -136v-640q0 -79 56 -135.5t136 -56.5h640q79 0 135.5 56.5t56.5 135.5v640q0 80 -56.5 136t-135.5 56zM160 0q-13 0 -22.5 9.5t-9.5 22.5t9.5 22.5t22.5 9.5t22.5 -9.5t9.5 -22.5t-9.5 -22.5t-22.5 -9.5zM160 704q-13 0 -22.5 9.5
-t-9.5 22.5t9.5 22.5t22.5 9.5t22.5 -9.5t9.5 -22.5t-9.5 -22.5t-22.5 -9.5zM704 64q0 -27 -18.5 -45.5t-45.5 -18.5h-256q-27 0 -45.5 18.5t-18.5 45.5v640q0 26 19 45t45 19h256q27 0 45.5 -18.5t18.5 -45.5v-640zM864 0q-13 0 -22.5 9.5t-9.5 22.5t9.5 22.5t22.5 9.5
-t22.5 -9.5t9.5 -22.5t-9.5 -22.5t-22.5 -9.5zM864 704q-13 0 -22.5 9.5t-9.5 22.5t9.5 22.5t22.5 9.5t22.5 -9.5t9.5 -22.5t-9.5 -22.5t-22.5 -9.5zM576 704h-128q-26 0 -45 -19t-19 -45v-192q0 -26 19 -45t45 -19h128q27 0 45.5 18.5t18.5 45.5v192q0 27 -18.5 45.5
-t-45.5 18.5z" />
-  </font>
-</defs></svg>

二進制
legacy/v3.0/app/css/iconfont/iconfont.ttf


二進制
legacy/v3.0/app/css/iconfont/iconfont.woff


+ 0 - 240
legacy/v3.0/app/css/style.css

@@ -1,240 +0,0 @@
-html,
-body {
-  margin: 0;
-  padding: 0;
-  background: #fff;
-  font-size: 12px;
-  line-height: 20px;
-  font-family: Arial, Helvetica, sans-serif;
-  color: #212121;
-}
-button,
-input {
-  font-family: Arial, Helvetica, sans-serif;
-}
-a {
-  text-decoration: none;
-}
-a:hover {
-  color: #1f3d66;
-}
-[v-cloak] {
-  display: none;
-}
-#sh-app {
-  position: fixed;
-  background: #fff;
-  top: 0;
-  right: 0;
-  bottom: 0;
-  left: 0;
-}
-#left {
-  position: fixed;
-  width: 240px;
-  background: #373d47;
-  border-right: solid 1px #373d47;
-  top: 0;
-  bottom: 0;
-  left: 0;
-  color: #979da7;
-}
-#left .operations {
-  position: absolute;
-  left: 0;
-  bottom: 0;
-  width: 240px;
-  hegith: 20px;
-}
-#left .operations ul {
-  list-style: none;
-  margin: 0;
-  padding: 0 18px 0 10px;
-}
-#left .operations ul li {
-  float: left;
-  margin: 0;
-  padding: 0;
-}
-#left .operations ul li a {
-  display: block;
-  min-width: 20px;
-  text-align: center;
-  color: #979da7;
-}
-#left .operations ul li a:hover {
-  background: #3d434e;
-}
-#left .operations ul li.right {
-  float: right;
-}
-#body {
-  position: fixed;
-  background: #ffc;
-  top: 0;
-  right: 0;
-  bottom: 0;
-  left: 241px;
-}
-#body .code textarea {
-  width: 98%;
-  line-height: 20px;
-  font-size: 12px;
-  font-family: Menlo, "Source Code Pro", Monaco, "Courier New", sans-serif;
-  padding: 4px 1%;
-  outline: none;
-  border: none;
-}
-#overlay {
-  position: fixed;
-  top: 0;
-  right: 0;
-  bottom: 0;
-  left: 0;
-  background: #000;
-  opacity: 0.618;
-  z-index: 90;
-}
-#edit-form,
-#pswd-form {
-  position: fixed;
-  top: 10%;
-  left: 50%;
-  background: #fff;
-  z-index: 100;
-  width: 400px;
-  margin-left: -200px;
-}
-#edit-form h2,
-#pswd-form h2 {
-  background: #f5f5f5;
-  font-size: 14px;
-  font-weight: normal;
-  padding: 0 10px;
-  margin: 0;
-  line-height: 40px;
-}
-#edit-form .body,
-#pswd-form .body {
-  padding: 20px;
-  line-height: 34px;
-}
-#edit-form .body .ln label,
-#pswd-form .body .ln label {
-  display: inline-block;
-  width: 80px;
-}
-#edit-form .body .ln input[type=text],
-#pswd-form .body .ln input[type=text],
-#edit-form .body .ln input[type=password],
-#pswd-form .body .ln input[type=password] {
-  width: 200px;
-  padding: 6px 10px;
-  outline: none;
-}
-#edit-form .body .ln input[type=password],
-#pswd-form .body .ln input[type=password] {
-  letter-spacing: 8px;
-}
-#edit-form .body .ln .inform,
-#pswd-form .body .ln .inform {
-  color: #f03;
-}
-#edit-form .body .ln .delete-hosts,
-#pswd-form .body .ln .delete-hosts {
-  color: #f03;
-}
-#edit-form .foot,
-#pswd-form .foot {
-  background: #f5f5f5;
-  padding: 16px 20px;
-  text-align: right;
-}
-#edit-form .foot button,
-#pswd-form .foot button {
-  border: none;
-  padding: 8px 16px;
-  margin-left: 1em;
-  cursor: pointer;
-  font-size: 14px;
-}
-.btn-default {
-  background: #09f;
-  color: #fff;
-}
-#hosts-list ul {
-  margin: 0;
-  padding: 0;
-  list-style: none;
-}
-#host-list li {
-  margin: 0;
-  padding: 0 20px 0 20px;
-  height: 34px;
-  line-height: 34px;
-  font-size: 14px;
-  cursor: pointer;
-}
-#host-list li i.i-h {
-  float: left;
-  display: inline-block;
-  width: 1.3em;
-}
-#host-list li .btn-edit {
-  display: none;
-  float: right;
-  margin-right: 10px;
-}
-#host-list li span.title {
-  float: left;
-  display: inline-block;
-  max-width: 130px;
-  overflow: hidden;
-  white-space: nowrap;
-  text-overflow: ellipsis;
-}
-#host-list li:hover {
-  background: #3d434e;
-}
-#host-list li.selected {
-  color: #fff;
-  background: #2c3139;
-}
-#host-list li.selected:hover .btn-edit {
-  display: inline-block;
-}
-#host-list li.dragged {
-  opacity: 0.4;
-}
-#host-list i.switch {
-  float: right;
-  display: inline-block;
-}
-#host-list i.switch.icon-on {
-  color: #af9;
-}
-#host-list i.switch.icon-off {
-  color: #979da7;
-}
-#custom-list {
-  overflow-y: auto;
-}
-[draggable] {
-  -moz-user-select: none;
-  -khtml-user-select: none;
-  -webkit-user-select: none;
-  user-select: none;
-/* Required to make elements draggable in old WebKit */
-  -khtml-user-drag: element;
-  -webkit-user-drag: element;
-}
-.cm-s-default .cm-comment {
-  color: #090;
-}
-.CodeMirror-gutters {
-  border-right: none;
-  padding-right: 6px;
-}
-.readonly .CodeMirror .CodeMirror-cursors {
-  display: none;
-}

File diff suppressed because it is too large
+ 0 - 0
legacy/v3.0/app/css/style.css.map


+ 0 - 266
legacy/v3.0/app/css/style.styl

@@ -1,266 +0,0 @@
-font_color=#212121
-font_color_left=#979da7
-bg_left=#373d47
-bd_color=bg_left
-bg_prompt=#f5f5f5
-left_width=240
-color_on=#af9
-color_off=font_color_left
-color_danger=#f03
-
-html, body
-  margin 0
-  padding 0
-  background #fff
-  font-size 12px
-  line-height 20px
-  font-family Arial, Helvetica, sans-serif
-  color font_color
-
-button, input
-  font-family Arial, Helvetica, sans-serif
-
-a
-  text-decoration none
-
-a:hover
-  color #1f3d66
-
-unselectable()
-  -moz-user-select none
-  -khtml-user-select none
-  -webkit-user-select none
-  -o-user-select none
-
-[v-cloak]
-  display none
-
-#sh-app
-  position fixed
-  background #fff
-  top 0
-  right 0
-  bottom 0
-  left 0
-
-#left
-  position fixed
-  width left_width px
-  background bg_left
-  border-right solid 1px bd_color
-  top 0
-  bottom 0
-  left 0
-  color font_color_left
-
-  .operations
-    position absolute
-    left 0
-    bottom 0
-    width left_width px
-    hegith 20px
-    //border-top solid 1px (bg_left * 0.9)
-
-    ul
-      list-style none
-      margin 0
-      padding 0 18px 0 10px
-
-      li
-        float left
-        margin 0
-        padding 0
-
-        a
-          display block
-          min-width 20px
-          text-align center
-          color font_color_left
-
-        a:hover
-          background bg_left * 1.1
-
-      li.right
-        float right
-
-  //.operations:hover
-  //  background bg_left * 0.95
-    //a
-    //  color #fff
-
-
-#body
-  position fixed
-  background #ffc
-  top 0
-  right 0
-  bottom 0
-  left (left_width + 1) px
-
-  .code
-
-    textarea
-      width 98%
-      //height 60em
-      line-height 20px
-      font-size 12px
-      font-family Menlo, "Source Code Pro", Monaco, "Courier New", sans-serif
-      padding 4px 1%
-      outline none
-      border none
-
-
-#overlay
-  position fixed
-  //display none
-  top 0
-  right 0
-  bottom 0
-  left 0
-  background #000
-  opacity 0.618
-  z-index 90
-
-#edit-form,
-#pswd-form
-  position fixed
-  //display none
-  top 10%
-  //right 50%
-  //bottom 50px
-  left 50%
-  background #fff
-  z-index 100
-  width 400px
-  margin-left -200px
-
-  h2
-    background bg_prompt
-    //border-bottom solid 1px bd_color
-    font-size 14px
-    font-weight normal
-    padding 0 10px
-    margin 0
-    line-height 40px
-
-  .body
-    padding 20px
-    line-height 34px
-
-    .ln
-      label
-        display inline-block
-        width 80px
-      input[type=text],
-      input[type=password]
-        width 200px
-        padding 6px 10px
-        outline none
-
-      input[type=password]
-        letter-spacing 8px
-
-      .inform
-        color color_danger
-
-      .delete-host
-        color color_danger
-
-  .foot
-    background bg_prompt
-    padding 16px 20px
-    text-align right
-
-    button
-      border none
-      padding 8px 16px
-      margin-left 1em
-      cursor pointer
-      font-size 14px
-
-.btn-default
-  background #09f
-  color #fff
-
-#host-list
-  ul
-    margin 0
-    padding 0
-    list-style none
-
-  li
-    margin 0
-    padding 0 20px 0 20px
-    height 34px
-    line-height @height
-    font-size 14px
-    cursor pointer
-
-    i.i-h
-      float left
-      display inline-block
-      width 1.3em
-
-    .btn-edit
-      display none
-      float right
-      margin-right 10px
-
-    span.title
-      float left
-      display inline-block
-      max-width 130px
-      overflow hidden
-      white-space nowrap
-      text-overflow ellipsis
-
-  li:hover
-    background bg_left * 1.1
-
-  li.selected
-    color #fff
-    background bg_left * 0.8
-
-  li.selected:hover
-    .btn-edit
-      display inline-block
-
-  li.dragged
-    opacity 0.4
-
-  i.switch
-    float right
-    display inline-block
-    //width 10px
-    //height 10px
-    //background color_off
-    //margin-top 12px
-
-  i.switch.icon-on
-    color color_on
-  i.switch.icon-off
-    color color_off
-
-#custom-list
-  overflow-y auto
-
-[draggable]
-  -moz-user-select none
-  -khtml-user-select none
-  -webkit-user-select none
-  user-select none
-  /* Required to make elements draggable in old WebKit */
-  -khtml-user-drag element
-  -webkit-user-drag element
-
-// CodeMirror
-.cm-s-default .cm-comment
-  color #090
-.CodeMirror-gutters
-  border-right none
-  padding-right 6px
-//.CodeMirror-linenumber
-//  cursor pointer
-.readonly .CodeMirror
-  .CodeMirror-cursors
-    display none

+ 0 - 32
legacy/v3.0/app/gulpfile.js

@@ -1,32 +0,0 @@
-/**
- * @author oldj
- * @blog http://oldj.net
- */
-
-var gulp = require("gulp");
-var sourcemaps = require("gulp-sourcemaps");
-//var shell = require("gulp-shell");
-//var concat = require("gulp-concat");
-var stylus = require("gulp-stylus");
-
-gulp.task("stylus", function () {
-    gulp.src(["./css/*.styl"])
-        .pipe(sourcemaps.init())
-        .pipe(stylus({
-            compress: true
-        }))
-        .pipe(sourcemaps.write("./"))
-        .pipe(gulp.dest("./css"))
-        //.pipe(shell("echo 'update: <%= file.path %>'"))
-        //.pipe(makeSCP_CMD())
-    ;
-});
-
-gulp.task("default", function () {
-    //gulp.start("react");
-    gulp.start("stylus");
-
-    gulp.watch([
-        "./css/*.styl"
-    ], ["stylus"]);
-});

二進制
legacy/v3.0/app/images/app.icns


二進制
legacy/v3.0/app/images/logo_512.png


二進制
legacy/v3.0/app/images/t.png


+ 0 - 104
legacy/v3.0/app/index.html

@@ -1,104 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-	<meta charset="utf-8">
-	<title>SwitchHosts!</title>
-	<link rel="stylesheet" href="css/iconfont/iconfont.css">
-	<link rel="stylesheet" href="node_modules/codemirror/lib/codemirror.css">
-	<!--<link rel="stylesheet" href="node_modules/codemirror/theme/neo.css">-->
-	<link rel="stylesheet" href="css/style.css">
-</head>
-
-<body>
-<div id="sh-app">
-	<div id="left">
-		<div id="host-list">
-			<ul id="sys-list">
-				<li class="sys" v-cloak @click="showSysHost()" :class="{selected:current_host.is_sys}">
-					<i class="iconfont icon-sysserver i-h"></i>
-					<span class="title">{{ lang.sys_host_title }}</span>
-				</li>
-			</ul>
-			<ul id="custom-list">
-				<li v-cloak
-					v-for="host in hosts.list"
-					@click="selectHost(host)"
-					v-draggable="{index: $index, dragged: 'dragged'}"
-					v-dropzone="sort(hosts.list, $index, $droptag, $dropdata)"
-					:class="{selected:host==current_host}">
-					<!--<i class="switch" @click="switchHost(host)" :class="{'on':host.on}"></i>-->
-					<i class="iconfont switch" @click="switchHost(host)" :class="{'icon-on':host.on, 'icon-off':!host.on}"></i>
-					<i class="iconfont icon-doc i-h"></i>
-					<span class="title">{{ host.title }}</span>
-					<i class="iconfont icon-edit btn-edit" @click="edit(host)"></i>
-				</li>
-			</ul>
-		</div>
-		<div class="operations">
-			<ul>
-				<li>
-					<a href="#" @click="add()" title="{{ lang.add_host }}"><i class="iconfont icon-add-s"></i></a>
-				</li>
-				<li class="right">
-					<a href="#" @click="tmpClean()" v-cloak v-if="could_tmp_clean_on" title="{{ lang.tmp_clean }}"><i class="iconfont icon-switchon"></i></a>
-					<a href="#" @click="tmpRecover()" v-cloak v-if="!could_tmp_clean_on" title="{{ lang.tmp_recover }}"><i class="iconfont icon-switchoff"></i></a>
-				</li>
-			</ul>
-		</div>
-	</div>
-
-	<div id="body">
-		<div class="code" :class="{readonly:current_host.is_editable===false}">
-			<textarea id="host-code" v-model="current_host.content" @input="updateHost(current_host)"></textarea>
-		</div>
-	</div>
-
-	<div id="overlay" v-show="is_prompt_show" v-cloak></div>
-	<div id="edit-form" class="prompt" v-show="is_edit_show" v-cloak>
-		<h2>{{ lang[add_or_edit + '_host'] }}</h2>
-
-		<div class="body">
-			<div class="ln">
-				<label for="ipt-host-title">{{ lang.host_title }}</label>
-				<input type="text" id="ipt-host-title" name="host_title"
-					   maxlength="24"
-					   v-model="current_edit_host.title"
-					   @input="chkHostTitle()"
-					   @keydown.13="toSave()"
-				>
-
-				<div class="inform">{{ current_edit_host.title_inform }}</div>
-			</div>
-			<div class="ln" v-if="add_or_edit=='edit'">
-				<a href="#" class="delete-host" @click="delHost(current_edit_host)"><i class="iconfont icon-delete"></i> {{ lang.del_host }}</a>
-			</div>
-		</div>
-		<div class="foot">
-			<button @click="closePrompt()">{{ lang.cancel }}</button>
-			<button class="btn-default" @click="toSave()">{{ lang.ok }}</button>
-		</div>
-	</div>
-
-	<div id="pswd-form" class="prompt" v-show="is_pswd_show" v-cloak>
-		<h2>{{ lang.input_sudo_pswd }}</h2>
-
-		<div class="body">
-			<div class="ln">
-				<label for="ipt-host-title">{{ lang.sudo_pswd }}</label>
-				<input type="password" id="ipt-pswd" name="pswd"
-					   v-model="sudo_pswd"
-					   @keydown.13="chkPswd()"
-				>
-
-				<div class="inform">{{ host_title_inform }}</div>
-			</div>
-		</div>
-		<div class="foot">
-			<button @click="closePrompt('pswd')">{{ lang.cancel }}</button>
-			<button class="btn-default" @click="chkPswd()">{{ lang.ok }}</button>
-		</div>
-	</div>
-</div>
-<script>require("./js/sh.js");</script>
-</body>
-</html>

+ 0 - 170
legacy/v3.0/app/js/cf.js

@@ -1,170 +0,0 @@
-/**
- * @author oldj
- * @blog http://oldj.net
- */
-
-"use strict";
-
-const fs = require('fs');
-const path = require('path');
-const exec = require('child_process').exec;
-const mkdirp = require('mkdirp');
-const is_win = process.platform == 'win32';
-
-let sys_host_path;
-
-if (is_win) {
-    // todo windows 有可能不在 C 盘,需要先取得当前系统安装盘
-    sys_host_path = 'C:\\Windows\\System32\\drivers\\etc\\hosts';
-} else {
-    sys_host_path = '/etc/hosts';
-}
-
-const work_path = getDataHome();
-const data_path = path.join(work_path, 'data.json');
-console.log('work_path:', work_path);
-mkdirp(work_path, function (err) {
-    err && console.log(err);
-});
-
-function copyObj(o) {
-    let k;
-    let o2 = {};
-    for (k in o) {
-        if (o.hasOwnProperty(k)) {
-            o2[k] = o[k];
-        }
-    }
-    return o2;
-}
-
-function mixObj(a, b) {
-    let k;
-    for (k in b) {
-        if (b.hasOwnProperty(k)) {
-            a[k] = b[k];
-        }
-    }
-    return a;
-}
-
-function getSysHosts() {
-    let s;
-    try {
-        s = fs.readFileSync(sys_host_path, 'utf-8');
-    } catch (e) {
-        console.log(sys_host_path);
-        alert(e.message);
-    }
-    return s;
-}
-
-function getDataHome() {
-    let data_path;
-    let folder = 'SwitchHosts';
-    if (is_win) {
-        data_path = process.env.LOCALAPPDATA || process.env.APPDATA || process.env.USERPROFILE;
-    } else {
-        data_path = process.env.HOME || process.env.HOMEPATH;
-        folder = '.' + folder;
-    }
-    data_path = data_path || process.cwd() || '';
-
-    return path.join(data_path, folder);
-}
-
-function makeBackupHosts() {
-    return {
-        title: 'backup',
-        on: true,
-        content: getSysHosts()
-    }
-}
-
-function getData(config) {
-    let s;
-    config = copyObj(config || {});
-
-    let default_hosts = {
-        title: 'My Hosts',
-        on: false,
-        content: '# My Hosts\n'
-    };
-
-    if (!fs.existsSync(data_path)) {
-        return mixObj(config, {
-            sys: getSysHosts(),
-            list: [default_hosts, makeBackupHosts()]
-        });
-    } else {
-        s = fs.readFileSync(data_path, 'utf-8');
-    }
-
-    try {
-        s = JSON.parse(s);
-        s = mixObj(config, s);
-        if (typeof s == 'object') {
-            s.sys = getSysHosts();
-            s.list = s.list || [default_hosts, makeBackupHosts()];
-            s.list.map(function (item) {
-                // set default value
-                item.title = item.title || '';
-                item.on = !!item.on;
-                item.content = item.content || '';
-            });
-            return s
-        }
-        alert('bad format!');
-    } catch (e) {
-        alert(e.message);
-    }
-}
-
-function saveData(data) {
-    fs.writeFile(data_path, JSON.stringify(data), 'utf-8', (e) => {
-        if (e) {
-            alert(e.message);
-            return;
-        }
-        //console.log('data saved.');
-    });
-}
-
-function saveHost(content, sudo_pswd, callback) {
-    let cmd;
-    //console.log(fs.statSync(sys_host_path));
-
-    if (sudo_pswd) {
-        // try to change the host file's permission
-        cmd = `echo '${sudo_pswd}' | sudo -S chmod 766 ${sys_host_path}`;
-        exec(cmd, function (err, stdout, stderr) {
-            if (!err) {
-                fs.writeFile(sys_host_path, content, 'utf-8', function (err) {
-                    // change the host file's permission back
-                    cmd = `echo '${sudo_pswd}' | sudo -S chmod 644 ${sys_host_path}`;
-                    exec(cmd, function (err) {
-                        //callback(err);
-                        err && console.log(err);
-                    });
-
-                    callback(err);
-                });
-            } else {
-                callback(err);
-            }
-        });
-    } else {
-        // try to write host directly
-        fs.writeFile(sys_host_path, content, 'utf-8', function (err) {
-            callback(err);
-        });
-    }
-
-}
-
-exports.sys_host_path = sys_host_path;
-exports.work_path = work_path;
-exports.getSysHosts = getSysHosts;
-exports.getData = getData;
-exports.saveData = saveData;
-exports.saveHost = saveHost;

+ 0 - 78
legacy/v3.0/app/js/chk.js

@@ -1,78 +0,0 @@
-/**
- * @author oldj
- * @blog http://oldj.net
- */
-
-"use strict";
-
-const http = require('http');
-const config = require('../config');
-const lang = require('./lang').getLang('en');
-
-function compareVersion(v1, v2) {
-    if (v1 == v2) return 0;
-
-    let a1 = v1.split('.');
-    let a2 = v2.split('.');
-    let i;
-    let l = Math.min(a1.length, a2.length);
-    let c1;
-    let c2;
-
-    for (i = 0; i < l; i ++) {
-        c1 = parseInt(a1[i]);
-        c2 = parseInt(a2[i]);
-
-        if (isNaN(c2) || c1 > c2) {
-            return 1;
-        } else if (c1 < c2) {
-            return -1;
-        }
-    }
-
-    return 0;
-}
-
-function chkUpdate(current_version, win) {
-    const dialog = require('electron').dialog;
-
-    http.get(config.url_chk_version, function (res) {
-        let s = '';
-        res.on('data', (c) => {
-            s += c;
-        });
-        res.on('end', () => {
-            //console.log(s);
-            let new_version = s.replace(/^\s+|\s+$/g, '');
-            if (compareVersion(current_version, new_version) < 0) {
-                // new version available
-                dialog.showMessageBox(win, {
-                    type: 'info'
-                    , buttons: ['cancel', 'YES']
-                    , title: 'New version found!'
-                    , message: lang.new_version_available + '\n\nv: ' + new_version
-                }, function (c) {
-                    if (c == 1) {
-                        require('electron').shell.openExternal(config.url_homepage);
-                    }
-                });
-            } else {
-                dialog.showMessageBox(win, {
-                    type: 'info'
-                    , buttons: ['OK']
-                    , title: 'You are up to date!'
-                    , message: lang.is_updated
-                });
-            }
-        });
-    }).on('error', function (e) {
-        dialog.showMessageBox(win, {
-            type: 'error'
-            , buttons: ['OK']
-            , title: 'Error'
-            , message: e.message
-        });
-    });
-}
-
-exports.chkUpdate = chkUpdate;

+ 0 - 53
legacy/v3.0/app/js/cm_hl.js

@@ -1,53 +0,0 @@
-// CodeMirror, copyright (c) by Marijn Haverbeke and others
-// Distributed under an MIT license: http://codemirror.net/LICENSE
-
-(function (mod) {
-    mod(require("codemirror"));
-})(function (CodeMirror) {
-    "use strict";
-
-    CodeMirror.defineMode('host', function () {
-
-        return {
-            token: function(stream) {
-                let tw_pos = stream.string.search(/[\t ]+?$/);
-
-                //if (!stream.sol() || tw_pos === 0) {
-                //    stream.skipToEnd();
-                    //return ("error " + (TOKEN_NAMES[stream.string.charAt(0)] || '')).replace(/ $/, '');
-                //}
-                //console.log(stream.string);
-
-                let c = stream.peek();
-                let token_name;
-                if (c == '#') {
-                    token_name = 'comment';
-                //} else if (!stream.string.match(/^\s*[\d\.]+\s+\w/i)) {
-                } else if (!stream.string.match(/^\s*([\d\.]+|[\da-f:\.%lo]+)\s+\w/i)) {
-                    token_name = 'error';
-                } else {
-                    token_name = stream.skipToEnd();
-                }
-
-                //let ip = stream.string.match(/^[\d\.]+\s/);
-                //if (ip) {
-                //    token_name = 'positive';
-                //    stream.pos = ip[0].length - 1;
-                //}
-
-                //if (tw_pos === -1) {
-                //    stream.skipToEnd();
-                //} else {
-                //    stream.pos = tw_pos;
-                //}
-                stream.skipToEnd();
-
-                return token_name;
-            },
-            lineComment: '#'
-        };
-    });
-
-    //CodeMirror.defineMIME('text/x-host', 'host');
-
-});

+ 0 - 101
legacy/v3.0/app/js/dnd.js

@@ -1,101 +0,0 @@
-'use strict';
-
-exports.install = function (Vue, options) {
-    var dropTo = '';
-    var _ = Vue.util;
-    Vue.directive('draggable', {
-        bind: function () {
-            this.data = {};
-            var _this = this;
-            this.dragstart = function (event) {
-                dropTo = _this.arg;
-                event.target.classList.add(_this.data.dragged);
-                event.dataTransfer.effectAllowed = 'all';
-                event.dataTransfer.setData('data', JSON.stringify(_this.data));
-                event.dataTransfer.setData('tag', _this.arg);
-                return false;
-            };
-            this.dragend = function (event) {
-                event.target.classList.remove(_this.data.dragged);
-                return false;
-            };
-            this.el.setAttribute('draggable', true);
-            _.on(this.el, 'dragstart', this.dragstart);
-            _.on(this.el, 'dragend', this.dragend);
-        },
-        update: function (value, old) {
-            this.data = value;
-        },
-        unbind: function () {
-            this.el.setAttribute('draggable', false);
-            _.off(this.el, 'dragstart', this.dragstart);
-            _.off(this.el, 'dragend', this.dragend);
-        }
-    });
-
-    Vue.directive('dropzone', {
-        acceptStatement: true,
-        bind: function () {
-            var self = this;
-            this.dragenter = function (event) {
-                if (dropTo == self.arg) {
-                    event.target.classList.add(self.arg);
-                }
-                return false;
-            };
-            this.dragover = function (event) {
-                if (event.preventDefault) {
-                    event.preventDefault();
-                }
-                // XXX
-                if (dropTo == self.arg) {
-                    event.dataTransfer.effectAllowed = 'all';
-                    event.dataTransfer.dropEffect = 'copy';
-                } else {
-                    event.dataTransfer.effectAllowed = 'none';
-                    event.dataTransfer.dropEffect = 'none';
-                }
-                return false;
-            };
-            this.dragleave = function (event) {
-                if (dropTo == self.arg) {
-                    event.target.classList.remove(self.arg);
-                }
-                return false;
-            };
-            this.drop = function (event) {
-                if (event.preventDefault) {
-                    event.preventDefault();
-                }
-                var tag = event.dataTransfer.getData('tag');
-                var data = event.dataTransfer.getData('data');
-                if (dropTo == self.arg) {
-                    self.handler(tag, JSON.parse(data));
-                    event.target.classList.remove(self.arg);
-                }
-                return false;
-            };
-            _.on(this.el, 'dragenter', this.dragenter);
-            _.on(this.el, 'dragleave', this.dragleave);
-            _.on(this.el, 'dragover', this.dragover);
-            _.on(this.el, 'drop', this.drop);
-        },
-        update: function (value, old) {
-            var vm = this.vm;
-            this.handler = function (tag, data) {
-                vm.$droptag = tag;
-                vm.$dropdata = data;
-                var res = value(tag, data);
-                vm.$droptag = null;
-                vm.$dropdata = null;
-                return res;
-            };
-        },
-        unbind: function () {
-            _.off(this.el, 'dragenter', this.dragenter);
-            _.off(this.el, 'dragleave', this.dragleave);
-            _.off(this.el, 'dragover', this.dragover);
-            _.off(this.el, 'drop', this.drop);
-        }
-    });
-};

+ 0 - 58
legacy/v3.0/app/js/lang.js

@@ -1,58 +0,0 @@
-/**
- * @author oldj
- * @blog http://oldj.net
- */
-
-"use strict";
-
-const languages = {
-    'en': {
-        add: 'Add'
-        , cancel: 'Cancel'
-        , ok: 'OK'
-        , add_host: 'Add new rules.'
-        , edit_host: 'Edit host'
-        , host_title: 'Host title'
-        , host_title_cant_be_empty: 'Host title could not be empty!'
-        , sys_host_title: 'System Hosts'
-        , input_sudo_pswd: 'Input your sudo password'
-        , sudo_pswd: 'Password'
-        , del_host: 'Delete current host'
-        , confirm_del: 'Are you sure you want to delete this host?'
-        , tmp_clean: 'Temporarily turn off all rules.'
-        , tmp_recover: 'Recover rules.'
-        , new_version_available: 'New version available, download now?'
-        , is_updated: 'You already have the latest version of SwitchHosts! installed.'
-    },
-    'cn': {
-        add: '添加'
-        , cancel: '取消'
-        , ok: '确定'
-        , add_host: '添加 host 规则'
-        , edit_host: '修改 host'
-        , host_title: 'host 方案名'
-        , host_title_cant_be_empty: 'Host 方案名不能为空!'
-        , sys_host_title: '系统 Hosts'
-        , input_sudo_pswd: '请输入管理员密码'
-        , sudo_pswd: '密码'
-        , del_host: '删除当前 host'
-        , confirm_del: '确定要删除此 host 吗?'
-        , tmp_clean: '临时去掉所有绑定'
-        , tmp_recover: '恢复绑定'
-        , new_version_available: '检测到新版本,是否要下载?'
-        , is_updated: '当前版本是最新版本。'
-    }
-};
-
-module.exports = {
-    languages: languages,
-    getLang: function (lang) {
-        lang = lang.toLowerCase();
-        if (lang == 'cn' || lang == 'zh-cn') {
-            lang = 'cn';
-        } else {
-            lang = 'en';
-        }
-        return languages[lang] || languages['en'];
-    }
-};

+ 0 - 199
legacy/v3.0/app/js/menu.js

@@ -1,199 +0,0 @@
-/**
- * @author oldj
- * @blog http://oldj.net
- */
-
-"use strict";
-
-const Menu = require('menu');
-const config = require('../config');
-
-const is_mac = process.platform == 'darwin';
-
-function makeMenu(app, mainWindow) {
-
-    let template = [{
-        label: 'Edit',
-        submenu: [{
-            label: 'Undo',
-            accelerator: 'CmdOrCtrl+Z',
-            role: 'undo'
-        }, {
-            label: 'Redo',
-            accelerator: 'Shift+CmdOrCtrl+Z',
-            role: 'redo'
-        }, {
-            type: 'separator'
-        }, {
-            label: 'Cut',
-            accelerator: 'CmdOrCtrl+X',
-            role: 'cut'
-        }, {
-            label: 'Copy',
-            accelerator: 'CmdOrCtrl+C',
-            role: 'copy'
-        }, {
-            label: 'Paste',
-            accelerator: 'CmdOrCtrl+V',
-            role: 'paste'
-        }, {
-            label: 'Select All',
-            accelerator: 'CmdOrCtrl+A',
-            role: 'selectall'
-        }]
-    }, {
-        label: 'View',
-        submenu: [{
-            label: 'Toggle Full Screen',
-            accelerator: (function () {
-                if (is_mac) {
-                    return 'Ctrl+Command+F';
-                } else {
-                    return 'F11';
-                }
-            })(),
-            click: function (item, focusedWindow) {
-                if (focusedWindow) {
-                    focusedWindow.setFullScreen(!focusedWindow.isFullScreen());
-                }
-            }
-            //},
-            //{
-            //    label: 'Toggle Developer Tools',
-            //    accelerator: (function () {
-            //        if (is_mac) {
-            //            return 'Alt+Command+I';
-            //        } else {
-            //            return 'Ctrl+Shift+I';
-            //        }
-            //    })(),
-            //    click: function (item, focusedWindow) {
-            //        if (focusedWindow) {
-            //            focusedWindow.toggleDevTools();
-            //        }
-            //    }
-        }]
-    }, {
-        label: 'Window',
-        role: 'window',
-        submenu: [{
-            label: 'Minimize',
-            accelerator: 'CmdOrCtrl+M',
-            role: 'minimize'
-        }, {
-            label: 'Close',
-            accelerator: 'CmdOrCtrl+W',
-            role: 'close'
-        }]
-    }, {
-        label: 'Help',
-        role: 'help',
-        submenu: [{
-            label: 'Homepage',
-            click: function () {
-                require('electron').shell.openExternal(config.url_homepage);
-            }
-        }, {
-            label: 'Feedback',
-            click: function () {
-                require('electron').shell.openExternal(config.url_feedback);
-            }
-        }]
-    }];
-
-    if (app.__is_debug) {
-        template[1].submenu.push({
-            label: 'Reload',
-            accelerator: 'CmdOrCtrl+R',
-            click: function (item, focusedWindow) {
-                if (focusedWindow)
-                    focusedWindow.reload();
-            }
-        });
-    }
-
-    let app_name = require('electron').app.getName();
-    if (is_mac) {
-        template.unshift({
-            label: app_name,
-            submenu: [{
-                label: 'About ' + app_name,
-                role: 'about'
-            }, {
-                label: 'Check for Updates...',
-                click: function () {
-                    require('./chk').chkUpdate(config.VERSION, mainWindow);
-                }
-            }, {
-                type: 'separator'
-            }, {
-                label: 'Services',
-                role: 'services',
-                submenu: []
-            }, {
-                type: 'separator'
-            }, {
-                label: 'Hide ' + app_name,
-                accelerator: 'Command+H',
-                role: 'hide'
-            }, {
-                label: 'Hide Others',
-                accelerator: 'Command+Shift+H',
-                role: 'hideothers'
-            }, {
-                label: 'Show All',
-                role: 'unhide'
-            }, {
-                type: 'separator'
-            }, {
-                label: 'Quit',
-                accelerator: 'Command+Q',
-                click: function () {
-                    app.__force_quit = true;
-                    app.quit();
-                }
-            }]
-        });
-        // Window menu.
-        template[3].submenu.push(
-            {
-                type: 'separator'
-            },
-            {
-                label: 'Bring All to Front',
-                role: 'front'
-            }
-        );
-
-    } else {
-        // windows / linux
-
-        template.unshift({
-            label: 'File',
-            submenu: [{
-                //label: 'About ' + app_name,
-                //role: 'about'
-            //}, {
-                label: 'Check for Updates...',
-                click: function () {
-                    require('./chk').chkUpdate(config.VERSION, mainWindow);
-                }
-            }, {
-                type: 'separator'
-            }, {
-                label: 'Quit',
-                //accelerator: 'Command+Q',
-                click: function () {
-                    app.__force_quit = true;
-                    app.quit();
-                }
-            }]
-        });
-
-    }
-
-    let menu = Menu.buildFromTemplate(template);
-    Menu.setApplicationMenu(menu);
-}
-
-exports.makeMenu = makeMenu;

+ 0 - 323
legacy/v3.0/app/js/sh.js

@@ -1,323 +0,0 @@
-/**
- * @author oldj
- * @blog http://oldj.net
- */
-
-"use strict";
-
-const config = require('../config');
-const $ = require('jquery');
-const Vue = require('vue');
-//Vue.config.debug = true;
-Vue.use(require('./dnd'));
-const CodeMirror = require('codemirror');
-//require('codemirror/mode/shell/shell');
-require('./cm_hl');
-const cf = require('./cf');
-const lang = require('./lang').getLang(navigator.language);
-const is_win = process.platform == 'win32';
-let my_codemirror;
-
-const app = new Vue({
-    el: '#sh-app',
-    data: {
-        lang: lang,
-        hosts: cf.getData({
-            VERSION: config.VERSION
-        }),
-        is_prompt_show: false,
-        is_edit_show: false,
-        is_pswd_show: false,
-        current_host: {
-            content: cf.getSysHosts(),
-            is_sys: true,
-            is_editable: false
-        },
-        on_after_permission: [],
-        could_tmp_clean_on: true,
-        current_edit_host: {},
-        add_or_edit: '',
-        sudo_pswd: ''
-    },
-    watch: {
-        'current_host': function (host) {
-            my_codemirror.getDoc().setValue(host.content || '');
-            if (host.is_editable === false) {
-                my_codemirror.setOption('readOnly', true);
-            } else {
-                my_codemirror.setOption('readOnly', false);
-            }
-
-            host._just_switch = 1;
-        },
-        'current_host.content': function () {
-            let host = this.current_host;
-            if (host._just_switch) {
-                host._just_switch = 0;
-                return;
-            }
-            this.doSave();
-            if (host.on) {
-                this.caculateHosts(host);
-            }
-        }
-    },
-    methods: {
-        add: function () {
-            this.is_prompt_show = true;
-            this.is_edit_show = true;
-            this.current_edit_host = {};
-            this.add_or_edit = 'add';
-            //this.chkHostTitle();
-
-            setTimeout(() => $('#ipt-host-title').focus(), 100);
-        },
-        edit: function (host) {
-            this.is_prompt_show = true;
-            this.is_edit_show = true;
-            this.current_edit_host = host;
-            this.add_or_edit = 'edit';
-
-            setTimeout(() => $('#ipt-host-title').focus(), 100);
-        },
-        chkHostTitle: function () {
-            let host_title = this.current_edit_host.title.replace(/^\s+|\s+$/g, '');
-            if (!host_title) {
-                this.current_edit_host.title_inform = this.lang.host_title_cant_be_empty;
-                $('#ipt-host-title').focus();
-                return false;
-            } else {
-                this.current_edit_host.title_inform = '';
-                this.host_title = host_title;
-                return true;
-            }
-        },
-        toSave: function () {
-            if (!this.chkHostTitle()) {
-                return;
-            }
-            let host;
-
-            //if (this.hosts.list.indexOf(this.current_edit_host) > -1) {
-            if (this.add_or_edit == 'edit') {
-                // edit
-            } else {
-                // add new
-                host = {
-                    title: this.current_edit_host.title,
-                    content: `# ${this.current_edit_host.title}`,
-                    on: false
-                };
-                this.hosts.list.push(host);
-                this.selectHost(host);
-            }
-
-            this.doSave(true);
-            this.closePrompt();
-        },
-        doSave: function (now) {
-            clearTimeout(this._t_save);
-            this._t_save = setTimeout(() => cf.saveData(this.hosts), now ? 0 : 1000);
-        },
-        closePrompt: function (action) {
-            this.is_prompt_show = false;
-            this.is_edit_show = false;
-            this.is_pswd_show = false;
-
-            if (action == 'pswd') {
-                //    this._to_switch_host.on = !this._to_switch_host.on;
-                this.sudo_pswd = '';
-                //this.tmpRecover();
-                this._on_hosts && this._on_hosts.map((host) => {
-                    host.on = true;
-                });
-                this._on_hosts = [];
-            }
-        },
-        selectHost: function (host) {
-            this.current_host = host;
-        },
-        switchHost: function (host) {
-            if (!host) return;
-            this._to_switch_host = host;
-            if (!host.is_sys) {
-                this.could_tmp_clean_on = true;
-            }
-
-            this.caculateHosts(host, (err) => {
-                if (err) {
-                } else {
-                    host.on = !host.on;
-                    this.doSave();
-                }
-                this._to_switch_host = null;
-            });
-        },
-        updateHost: function (host) {
-            this.doSave();
-        },
-        showSysHost: function () {
-            this.current_host = {
-                content: cf.getSysHosts(),
-                is_sys: true,
-                is_editable: false
-            };
-        },
-        delHosts: function (host) {
-            if (!confirm(this.lang.confirm_del)) {
-                return;
-            }
-
-            let i = this.hosts.list.indexOf(host);
-            if (i > -1) {
-                this.hosts.list.splice(i, 1);
-                this.current_edit_host = {};
-                this.closePrompt();
-                this.doSave();
-            }
-        },
-        caculateHosts: function (host, callback) {
-            let on_hosts = [];
-            host = host || this.current_host;
-            this.hosts.list.map((host) => {
-                if ((host.on && host != this._to_switch_host) || (!host.on && host == this._to_switch_host)) {
-                    on_hosts.push(host.content);
-                }
-            });
-
-            let s_hosts = on_hosts.join('\n\n# --------------------\n\n');
-            s_hosts = `# SwitchHosts!\n${s_hosts}`;
-            cf.saveHost(s_hosts, this.sudo_pswd, (err) => {
-                if (err) {
-                    console.log(err);
-                    if (!is_win) {
-                        // mac & linux
-                        if (err.message.indexOf('EACCES') > -1 || err.message.indexOf('permission denied') > -1) {
-                            // get permission
-                            this.askForPermission(() => {
-                                this.caculateHosts(host, callback)
-                            });
-                        } else if (err.message.indexOf('Command failed') > -1) {
-                            // todo show inform
-                            this.sudo_pswd = '';
-                        } else {
-                            alert(err);
-                        }
-                    } else {
-                        // windows
-                        alert(err);
-                    }
-                    return;
-                }
-                callback && callback.call(this);
-                if (this.current_host.is_sys) {
-                    this.showSysHost();
-                }
-            });
-        },
-        askForPermission: function (callback) {
-            this.is_prompt_show = true;
-            this.is_pswd_show = true;
-            this.sudo_pswd = '';
-            callback && this.on_after_permission.push(callback);
-
-            setTimeout(() => $('#ipt-pswd').focus(), 100);
-        },
-        chkPswd: function () {
-            //this.switchHost(this._to_switch_host);
-            this.closePrompt();
-            //this._to_switch_host = null;
-
-            let f;
-            while (f = this.on_after_permission.shift()) {
-                f && f.call(this);
-            }
-        },
-        tmpClean: function () {
-            this.could_tmp_clean_on = false;
-            this._to_switch_host = null;
-            this._on_hosts = [];
-            this.hosts.list.map((host) => {
-                if (host.on) {
-                    this._on_hosts.push(host);
-                    host.on = false;
-                }
-            });
-            this.caculateHosts();
-            this.doSave(true);
-        },
-        tmpRecover: function () {
-            this.could_tmp_clean_on = true;
-            if (!this._on_hosts) return;
-
-            this._on_hosts.map((host) => {
-                host.on = true;
-            });
-            this._on_hosts = [];
-            this.caculateHosts();
-            this.doSave(1);
-        },
-        sort: function (list, id, tag, data) {
-            let tmp = list[data.index];
-            list.splice(data.index, 1);
-            list.splice(id, 0, tmp);
-
-            this.doSave(1);
-        },
-        move: function (from, to, id, tag, data) {
-            let tmp = from[data.index];
-            from.splice(data.index, 1);
-            to.splice(id, 0, tmp);
-        },
-        remove: function (from, tag, data) {
-            from.splice(data.index, 1);
-        },
-        log: function (obj) {
-            console.log(obj);
-            return 1;
-        }
-    }
-});
-
-function resize() {
-    let wh = window.innerHeight;
-    let h = wh - $('#sys-list').height() - 20;
-    $('#custom-list').css('height', h);
-    my_codemirror.setSize('100%', wh);
-}
-
-$(document).ready(function () {
-    let el_textarea = $('#host-code');
-    //el_textarea.css('height', window.innerHeight - 8);
-
-    my_codemirror = CodeMirror.fromTextArea(el_textarea[0], {
-        lineNumbers: true,
-        readOnly: true,
-        mode: 'host'
-    });
-
-    my_codemirror.on('change', function (a, b) {
-        app.current_host.content = a.getDoc().getValue();
-    });
-
-    my_codemirror.on('gutterClick', function (cm, n) {
-        if (app.current_host.is_editable === false) return;
-
-        let info = cm.lineInfo(n);
-        //cm.setGutterMarker(n, "breakpoints", info.gutterMarkers ? null : makeMarker());
-        let ln = info.text;
-        if (/^\s*$/.test(ln)) return;
-
-        let new_ln;
-        if (/^#/.test(ln)) {
-            new_ln = ln.replace(/^#\s*/, '');
-        } else {
-            new_ln = '# ' + ln;
-        }
-        my_codemirror.getDoc().replaceRange(new_ln, {line: info.line, ch: 0}, {line: info.line, ch: ln.length});
-        //app.caculateHosts();
-    });
-
-    resize();
-    $(window).resize(resize);
-});

+ 0 - 29
legacy/v3.0/app/js/tray.js

@@ -1,29 +0,0 @@
-/**
- * @author oldj
- * @blog http://oldj.net
- */
-
-"use strict";
-
-//const Tray = require('tray');
-
-let appIcon = null;
-
-function makeTray(app) {
-    /*
-     //console.log('file://' + __dirname + '/images/t.png');
-     // @see https://github.com/atom/electron/blob/master/docs/api/tray.md
-     appIcon = new Tray(__dirname + '/images/t.png');
-     //appIcon = new Tray('/Users/wu/studio/owl/sh3/app/images/t.png');
-     let contextMenu = Menu.buildFromTemplate([
-     {label: 'Item1', type: 'radio'},
-     {label: 'Item2', type: 'radio'},
-     {label: 'Item3', type: 'radio', checked: true},
-     {label: 'Item4', type: 'radio'}
-     ]);
-     appIcon.setToolTip('This is my application.');
-     appIcon.setContextMenu(contextMenu);
-     */
-}
-
-exports.makeTray = makeTray;

+ 0 - 78
legacy/v3.0/app/main.js

@@ -1,78 +0,0 @@
-/**
- * @author oldj
- * @blog http://oldj.net
- */
-
-'use strict';
-
-const config = require('./config');
-
-const app = require('app');  // Module to control application life.
-const BrowserWindow = require('browser-window');  // Module to create native browser window.
-const http = require('http');
-
-//app.__is_debug = true;
-app.__is_debug = false;
-
-
-// Report crashes to our server.
-require('crash-reporter').start();
-
-// Keep a global reference of the window object, if you don't, the window will
-// be closed automatically when the javascript object is GCed.
-let mainWindow = null;
-
-// Quit when all windows are closed.
-app.on('window-all-closed', function () {
-    if (process.platform != 'darwin') {
-        app.quit();
-    }
-});
-
-// This method will be called when atom-shell has done everything
-// initialization and ready for creating browser windows.
-app.on('ready', function () {
-    // Create the browser window.
-    mainWindow = new BrowserWindow({width: 800, height: 600});
-
-    // and load the index.html of the app.
-    mainWindow.loadURL('file://' + __dirname + '/index.html');
-    //app.dock.hide();
-
-    if (app.__is_debug) {
-        mainWindow.toggleDevTools();
-    }
-
-    mainWindow.on('close', function (e) {
-        console.log('close');
-        if (!app.__force_quit) {
-            e.preventDefault();
-            mainWindow.hide();
-        }
-    });
-
-    // You can use 'before-quit' instead of (or with) the close event
-    app.on('before-quit', function (e) {
-        console.log('before-quit');
-        // Handle menu-item or keyboard shortcut quit here
-        app.__force_quit = true;
-    });
-
-    // Remove mainWindow.on('closed'), as it is redundant
-    /*
-     // Emitted when the window is closed.
-     mainWindow.on('closed', function () {
-     // Dereference the window object, usually you would store windows
-     // in an array if your app supports multi windows, this is the time
-     // when you should delete the corresponding element.
-     mainWindow = null;
-     app.quit();
-     });*/
-
-    app.on('activate', function () {
-        mainWindow.show();
-    });
-
-    require('./js/menu').makeMenu(app, mainWindow);
-    require('./js/tray').makeTray(app);
-});

+ 0 - 21
legacy/v3.0/app/package.json

@@ -1,21 +0,0 @@
-{
-  "name": "SwitchHosts!",
-  "version": "0.3.1",
-  "main": "main.js",
-  "devDependencies": {
-    "gulp": "^3.8.11",
-    "gulp-sourcemaps": "^1.5.1",
-    "gulp-stylus": "^2.0.6",
-    "stylus": "~0.52.4"
-  },
-  "dependencies": {
-    "codemirror": "~5.9.0",
-    "jquery": "~2.1.4",
-    "mkdirp": "~0.5.1",
-    "vue": "~1.0.10",
-    "vue-dnd": "^0.1.1"
-  },
-  "scripts": {
-    "start": "electron ."
-  }
-}

+ 0 - 2
legacy/v3.1_macgap/app/SH3/.gitignore

@@ -1,2 +0,0 @@
-public/status.png
-.DS_Store

+ 0 - 17
legacy/v3.1_macgap/app/SH3/MacGap/AppDelegate.h

@@ -1,17 +0,0 @@
-//
-//  AppDelegate.h
-//  MG
-//
-//  Created by Tim Debo on 5/19/14.
-//
-//
-
-#import <Cocoa/Cocoa.h>
-
-@class WindowController;
-
-@interface AppDelegate : NSObject <NSApplicationDelegate,NSUserNotificationCenterDelegate>
-
-@property (retain, nonatomic) WindowController *windowController;
-
-@end

+ 0 - 41
legacy/v3.1_macgap/app/SH3/MacGap/AppDelegate.m

@@ -1,41 +0,0 @@
-//
-//  AppDelegate.m
-//  MG
-//
-//  Created by Tim Debo on 5/19/14.
-//
-//
-
-#import "AppDelegate.h"
-#import "WindowController.h"
-
-@implementation AppDelegate
-
-- (void)applicationWillFinishLaunching:(NSNotification *)aNotification
-{
-    // Insert code here to initialize your application
-    // [NSApp setActivationPolicy:NSApplicationActivationPolicyAccessory];
-
-}
-
--(BOOL)applicationShouldHandleReopen:(NSApplication*)application
-                   hasVisibleWindows:(BOOL)visibleWindows{
-    if(!visibleWindows){
-        [self.windowController.window makeKeyAndOrderFront: nil];
-    }
-    return YES;
-}
-
-- (void) applicationDidFinishLaunching:(NSNotification *)aNotification {
-    self.windowController = [[WindowController alloc] initWithURL: kStartPage];
-    [self.windowController setWindowParams];
-    [self.windowController showWindow:self];
-    [[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:self];
-}
-
-- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center
-     shouldPresentNotification:(NSUserNotification *)notification
-{
-    return YES;
-}
-@end

+ 0 - 213
legacy/v3.1_macgap/app/SH3/MacGap/Base.lproj/MainMenu.xib

@@ -1,213 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="9531" systemVersion="15C50" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
-    <dependencies>
-        <deployment identifier="macosx"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="9531"/>
-    </dependencies>
-    <objects>
-        <customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
-            <connections>
-                <outlet property="delegate" destination="Voe-Tx-rLC" id="GzC-gU-4Uq"/>
-            </connections>
-        </customObject>
-        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
-        <customObject id="-3" userLabel="Application" customClass="NSObject"/>
-        <customObject id="Voe-Tx-rLC" customClass="AppDelegate"/>
-        <customObject id="YLy-65-1bz" customClass="NSFontManager"/>
-        <menu title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
-            <items>
-                <menuItem title="SwitchHosts!" id="1Xt-HY-uBw">
-                    <modifierMask key="keyEquivalentModifierMask"/>
-                    <menu key="submenu" title="SwitchHosts!" systemMenu="apple" id="uQy-DD-JDr">
-                        <items>
-                            <menuItem title="About SwitchHosts!" id="5kV-Vb-QxS">
-                                <modifierMask key="keyEquivalentModifierMask"/>
-                                <connections>
-                                    <action selector="orderFrontStandardAboutPanel:" target="-1" id="Exp-CZ-Vem"/>
-                                </connections>
-                            </menuItem>
-                            <menuItem title="Check for Updates..." id="nlY-XH-oPO">
-                                <modifierMask key="keyEquivalentModifierMask"/>
-                            </menuItem>
-                            <menuItem isSeparatorItem="YES" id="VOq-y0-SEH"/>
-                            <menuItem title="Preferences…" keyEquivalent="," id="BOF-NM-1cW"/>
-                            <menuItem isSeparatorItem="YES" id="wFC-TO-SCJ"/>
-                            <menuItem title="Services" id="NMo-om-nkz">
-                                <modifierMask key="keyEquivalentModifierMask"/>
-                                <menu key="submenu" title="Services" systemMenu="services" id="hz9-B4-Xy5"/>
-                            </menuItem>
-                            <menuItem isSeparatorItem="YES" id="4je-JR-u6R"/>
-                            <menuItem title="Hide SwitchHosts!" keyEquivalent="h" id="Olw-nP-bQN">
-                                <connections>
-                                    <action selector="hide:" target="-1" id="PnN-Uc-m68"/>
-                                </connections>
-                            </menuItem>
-                            <menuItem title="Hide Others" keyEquivalent="h" id="Vdr-fp-XzO">
-                                <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
-                                <connections>
-                                    <action selector="hideOtherApplications:" target="-1" id="VT4-aY-XCT"/>
-                                </connections>
-                            </menuItem>
-                            <menuItem title="Show All" id="Kd2-mp-pUS">
-                                <modifierMask key="keyEquivalentModifierMask"/>
-                                <connections>
-                                    <action selector="unhideAllApplications:" target="-1" id="Dhg-Le-xox"/>
-                                </connections>
-                            </menuItem>
-                            <menuItem isSeparatorItem="YES" id="kCx-OE-vgT"/>
-                            <menuItem title="Quit SwitchHosts!" keyEquivalent="q" id="4sb-4s-VLi">
-                                <connections>
-                                    <action selector="terminate:" target="-1" id="Te7-pn-YzF"/>
-                                </connections>
-                            </menuItem>
-                        </items>
-                    </menu>
-                </menuItem>
-                <menuItem title="File" id="dMs-cI-mzQ">
-                    <modifierMask key="keyEquivalentModifierMask"/>
-                    <menu key="submenu" title="File" id="bib-Uj-vzu">
-                        <items>
-                            <menuItem title="New" keyEquivalent="n" id="Was-JA-tGl">
-                                <connections>
-                                    <action selector="newDocument:" target="-1" id="4Si-XN-c54"/>
-                                </connections>
-                            </menuItem>
-                            <menuItem isSeparatorItem="YES" id="m54-Is-iLE"/>
-                            <menuItem title="Close" keyEquivalent="w" id="DVo-aG-piG">
-                                <connections>
-                                    <action selector="performClose:" target="-1" id="HmO-Ls-i7Q"/>
-                                </connections>
-                            </menuItem>
-                            <menuItem isSeparatorItem="YES" id="dJd-7H-Hnl"/>
-                            <menuItem title="Import" keyEquivalent="i" id="Wb3-1u-mn7">
-                                <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
-                            </menuItem>
-                            <menuItem title="Export" keyEquivalent="e" id="HK8-zQ-wnp">
-                                <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
-                            </menuItem>
-                        </items>
-                    </menu>
-                </menuItem>
-                <menuItem title="Edit" id="5QF-Oa-p0T">
-                    <modifierMask key="keyEquivalentModifierMask"/>
-                    <menu key="submenu" title="Edit" id="W48-6f-4Dl">
-                        <items>
-                            <menuItem title="Undo" keyEquivalent="z" id="dRJ-4n-Yzg">
-                                <connections>
-                                    <action selector="undo:" target="-1" id="M6e-cu-g7V"/>
-                                </connections>
-                            </menuItem>
-                            <menuItem title="Redo" keyEquivalent="Z" id="6dh-zS-Vam">
-                                <connections>
-                                    <action selector="redo:" target="-1" id="oIA-Rs-6OD"/>
-                                </connections>
-                            </menuItem>
-                            <menuItem isSeparatorItem="YES" id="WRV-NI-Exz"/>
-                            <menuItem title="Cut" keyEquivalent="x" id="uRl-iY-unG">
-                                <connections>
-                                    <action selector="cut:" target="-1" id="YJe-68-I9s"/>
-                                </connections>
-                            </menuItem>
-                            <menuItem title="Copy" keyEquivalent="c" id="x3v-GG-iWU">
-                                <connections>
-                                    <action selector="copy:" target="-1" id="G1f-GL-Joy"/>
-                                </connections>
-                            </menuItem>
-                            <menuItem title="Paste" keyEquivalent="v" id="gVA-U4-sdL">
-                                <connections>
-                                    <action selector="paste:" target="-1" id="UvS-8e-Qdg"/>
-                                </connections>
-                            </menuItem>
-                            <menuItem title="Paste and Match Style" keyEquivalent="V" id="WeT-3V-zwk">
-                                <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
-                                <connections>
-                                    <action selector="pasteAsPlainText:" target="-1" id="cEh-KX-wJQ"/>
-                                </connections>
-                            </menuItem>
-                            <menuItem title="Delete" id="pa3-QI-u2k">
-                                <string key="keyEquivalent" base64-UTF8="YES">
-CA
-</string>
-                                <modifierMask key="keyEquivalentModifierMask"/>
-                                <connections>
-                                    <action selector="delete:" target="-1" id="0Mk-Ml-PaM"/>
-                                </connections>
-                            </menuItem>
-                            <menuItem title="Select All" keyEquivalent="a" id="Ruw-6m-B2m">
-                                <connections>
-                                    <action selector="selectAll:" target="-1" id="VNm-Mi-diN"/>
-                                </connections>
-                            </menuItem>
-                            <menuItem isSeparatorItem="YES" id="uyl-h8-XO2"/>
-                            <menuItem title="Find" keyEquivalent="f" id="4EN-yA-p0u"/>
-                        </items>
-                    </menu>
-                </menuItem>
-                <menuItem title="View" id="H8h-7b-M4v">
-                    <modifierMask key="keyEquivalentModifierMask"/>
-                    <menu key="submenu" title="View" id="HyV-fh-RgO">
-                        <items>
-                            <menuItem title="Show Toolbar" keyEquivalent="t" id="snW-S8-Cw5">
-                                <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
-                                <connections>
-                                    <action selector="toggleToolbarShown:" target="-1" id="BXY-wc-z0C"/>
-                                </connections>
-                            </menuItem>
-                            <menuItem title="Customize Toolbar…" id="1UK-8n-QPP">
-                                <modifierMask key="keyEquivalentModifierMask"/>
-                                <connections>
-                                    <action selector="runToolbarCustomizationPalette:" target="-1" id="pQI-g3-MTW"/>
-                                </connections>
-                            </menuItem>
-                            <menuItem isSeparatorItem="YES" id="7gu-tM-cp2"/>
-                            <menuItem title="Previous hosts" keyEquivalent="" id="8Pb-h9-Bzr">
-                                <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
-                            </menuItem>
-                            <menuItem title="Next hosts" keyEquivalent="" id="dGY-Ua-09q">
-                                <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
-                            </menuItem>
-                        </items>
-                    </menu>
-                </menuItem>
-                <menuItem title="Window" id="aUF-d1-5bR">
-                    <modifierMask key="keyEquivalentModifierMask"/>
-                    <menu key="submenu" title="Window" systemMenu="window" id="Td7-aD-5lo">
-                        <items>
-                            <menuItem title="Minimize" keyEquivalent="m" id="OY7-WF-poV">
-                                <connections>
-                                    <action selector="performMiniaturize:" target="-1" id="VwT-WD-YPe"/>
-                                </connections>
-                            </menuItem>
-                            <menuItem title="Zoom" id="R4o-n2-Eq4">
-                                <modifierMask key="keyEquivalentModifierMask"/>
-                                <connections>
-                                    <action selector="performZoom:" target="-1" id="DIl-cC-cCs"/>
-                                </connections>
-                            </menuItem>
-                            <menuItem isSeparatorItem="YES" id="eu3-7i-yIM"/>
-                            <menuItem title="Bring All to Front" id="LE2-aR-0XJ">
-                                <modifierMask key="keyEquivalentModifierMask"/>
-                                <connections>
-                                    <action selector="arrangeInFront:" target="-1" id="DRN-fu-gQh"/>
-                                </connections>
-                            </menuItem>
-                        </items>
-                    </menu>
-                </menuItem>
-                <menuItem title="Help" id="wpr-3q-Mcd">
-                    <modifierMask key="keyEquivalentModifierMask"/>
-                    <menu key="submenu" title="Help" systemMenu="help" id="F2S-fz-NVQ">
-                        <items>
-                            <menuItem title="Feedback" id="HIg-UM-Jbe">
-                                <modifierMask key="keyEquivalentModifierMask"/>
-                            </menuItem>
-                            <menuItem title="Homepage" id="nsr-z8-V76">
-                                <modifierMask key="keyEquivalentModifierMask"/>
-                            </menuItem>
-                        </items>
-                    </menu>
-                </menuItem>
-            </items>
-        </menu>
-    </objects>
-</document>

+ 0 - 38
legacy/v3.1_macgap/app/SH3/MacGap/Base.lproj/MainWindow.xib

@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="9531" systemVersion="15C50" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none">
-    <dependencies>
-        <deployment identifier="macosx"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="9531"/>
-        <plugIn identifier="com.apple.WebKitIBPlugin" version="9531"/>
-    </dependencies>
-    <objects>
-        <customObject id="-2" userLabel="File's Owner" customClass="WindowController">
-            <connections>
-                <outlet property="webView" destination="TAr-Rf-hWt" id="ELL-aJ-ING"/>
-                <outlet property="window" destination="F0z-JX-Cv5" id="gIp-Ho-8D9"/>
-            </connections>
-        </customObject>
-        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
-        <customObject id="-3" userLabel="Application" customClass="NSObject"/>
-        <window title="SwitchHosts!" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" animationBehavior="default" id="F0z-JX-Cv5">
-            <windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
-            <windowCollectionBehavior key="collectionBehavior" fullScreenPrimary="YES"/>
-            <rect key="contentRect" x="931" y="455" width="600" height="400"/>
-            <rect key="screenRect" x="0.0" y="0.0" width="2560" height="1418"/>
-            <view key="contentView" id="se5-gp-TjO">
-                <rect key="frame" x="0.0" y="0.0" width="600" height="400"/>
-                <autoresizingMask key="autoresizingMask"/>
-                <subviews>
-                    <webView id="TAr-Rf-hWt">
-                        <rect key="frame" x="0.0" y="0.0" width="600" height="400"/>
-                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
-                        <webPreferences key="preferences" defaultFontSize="12" defaultFixedFontSize="12">
-                            <nil key="identifier"/>
-                        </webPreferences>
-                    </webView>
-                </subviews>
-            </view>
-        </window>
-        <userDefaultsController representsSharedInstance="YES" id="ZCr-Cb-xhD"/>
-    </objects>
-</document>

+ 0 - 19
legacy/v3.1_macgap/app/SH3/MacGap/Categories/JSON.h

@@ -1,19 +0,0 @@
-//
-//  JSON.h
-//  MacGap
-//
-//  Created by Tim Debo on 5/17/14.
-//  Copyright (c) 2014 Raw Creative Studios LLC. All rights reserved.
-//
-
-@interface NSArray (MGJSON)
-- (NSString*)JSONString;
-@end
-
-@interface NSDictionary (MGJSON)
-- (NSString*)JSONString;
-@end
-
-@interface NSString (MGJSON)
-- (id)JSONObject;
-@end

+ 0 - 66
legacy/v3.1_macgap/app/SH3/MacGap/Categories/JSON.m

@@ -1,66 +0,0 @@
-//
-//  JSON.m
-//  MacGap
-//
-//  Created by Tim Debo on 5/17/14.
-//  Copyright (c) 2014 Raw Creative Studios LLC. All rights reserved.
-//
-
-#import "JSON.h"
-#import <Foundation/NSJSONSerialization.h>
-
-@implementation NSArray (MGJSON)
-
-- (NSString*)JSONString
-{
-    NSError* error = nil;
-    NSData* jsonData = [NSJSONSerialization dataWithJSONObject:self
-                                                       options:NSJSONWritingPrettyPrinted
-                                                         error:&error];
-    
-    if (error != nil) {
-        NSLog(@"NSArray JSONString error: %@", [error localizedDescription]);
-        return nil;
-    } else {
-        return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
-    }
-}
-
-@end
-
-@implementation NSDictionary (MGJSON)
-
-- (NSString*)JSONString
-{
-    NSError* error = nil;
-    NSData* jsonData = [NSJSONSerialization dataWithJSONObject:self
-                                                       options:NSJSONWritingPrettyPrinted
-                                                         error:&error];
-    
-    if (error != nil) {
-        NSLog(@"NSDictionary JSONString error: %@", [error localizedDescription]);
-        return nil;
-    } else {
-        return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
-    }
-}
-
-@end
-
-@implementation NSString (MGJSON)
-
-- (id)JSONObject
-{
-    NSError* error = nil;
-    id object = [NSJSONSerialization JSONObjectWithData:[self dataUsingEncoding:NSUTF8StringEncoding]
-                                                options:kNilOptions
-                                                  error:&error];
-    
-    if (error != nil) {
-        NSLog(@"NSString JSONObject error: %@", [error localizedDescription]);
-    }
-    
-    return object;
-}
-
-@end

+ 0 - 27
legacy/v3.1_macgap/app/SH3/MacGap/Categories/NSData+Base64.h

@@ -1,27 +0,0 @@
-//
-//  NSData+Base64.h
-//  MG
-//
-//  Created by Tim Debo on 5/20/14.
-//
-//
-
-#import <Foundation/Foundation.h>
-
-void *NewBase64Decode(
-                         const char* inputBuffer,
-                         size_t    length,
-                         size_t    * outputLength);
-
-char *NewBase64Encode(
-                         const void* inputBuffer,
-                         size_t    length,
-                         bool      separateLines,
-                         size_t    * outputLength);
-
-@interface NSData (Base64)
-
-+ (NSData*)dataFromBase64String:(NSString*)aString;
-- (NSString*)base64EncodedString;
-
-@end

+ 0 - 276
legacy/v3.1_macgap/app/SH3/MacGap/Categories/NSData+Base64.m

@@ -1,276 +0,0 @@
-//
-//  NSData+Base64.m
-//  MG
-//
-//  Created by Tim Debo on 5/20/14.
-//
-//
-
-#import "NSData+Base64.h"
-
-//
-// Mapping from 6 bit pattern to ASCII character.
-//
-static unsigned char base64EncodeLookup[65] =
-"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-//
-// Definition for "masked-out" areas of the base64DecodeLookup mapping
-//
-#define xx 65
-
-//
-// Mapping from ASCII character to 6 bit pattern.
-//
-static unsigned char base64DecodeLookup[256] =
-{
-    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
-    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
-    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 62, xx, xx, xx, 63,
-    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, xx, xx, xx, xx, xx, xx,
-    xx, 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14,
-    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, xx, xx, xx, xx, xx,
-    xx, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
-    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, xx, xx, xx, xx, xx,
-    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
-    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
-    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
-    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
-    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
-    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
-    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
-    xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
-};
-
-//
-// Fundamental sizes of the binary and base64 encode/decode units in bytes
-//
-#define _BINARY_UNIT_SIZE 3
-#define _BASE64_UNIT_SIZE 4
-
-//
-// NewBase64Decode
-//
-// Decodes the base64 ASCII string in the inputBuffer to a newly malloced
-// output buffer.
-//
-//  inputBuffer - the source ASCII string for the decode
-//	length - the length of the string or -1 (to specify strlen should be used)
-//	outputLength - if not-NULL, on output will contain the decoded length
-//
-// returns the decoded buffer. Must be freed by caller. Length is given by
-//	outputLength.
-//
-void *NewBase64Decode(
-                         const char* inputBuffer,
-                         size_t    length,
-                         size_t    * outputLength)
-{
-    if (length == -1) {
-        length = strlen(inputBuffer);
-    }
-    
-    size_t outputBufferSize = (length / _BASE64_UNIT_SIZE) * _BINARY_UNIT_SIZE;
-    unsigned char* outputBuffer = (unsigned char*)malloc(outputBufferSize);
-    
-    size_t i = 0;
-    size_t j = 0;
-    
-    while (i < length) {
-        //
-        // Accumulate 4 valid characters (ignore everything else)
-        //
-        unsigned char accumulated[_BASE64_UNIT_SIZE];
-        bzero(accumulated, sizeof(unsigned char) * _BASE64_UNIT_SIZE);
-        size_t accumulateIndex = 0;
-        
-        while (i < length) {
-            unsigned char decode = base64DecodeLookup[inputBuffer[i++]];
-            if (decode != xx) {
-                accumulated[accumulateIndex] = decode;
-                accumulateIndex++;
-                
-                if (accumulateIndex == _BASE64_UNIT_SIZE) {
-                    break;
-                }
-            }
-        }
-        
-        //
-        // Store the 6 bits from each of the 4 characters as 3 bytes
-        //
-        outputBuffer[j] = (accumulated[0] << 2) | (accumulated[1] >> 4);
-        outputBuffer[j + 1] = (accumulated[1] << 4) | (accumulated[2] >> 2);
-        outputBuffer[j + 2] = (accumulated[2] << 6) | accumulated[3];
-        j += accumulateIndex - 1;
-    }
-    
-    if (outputLength) {
-        *outputLength = j;
-    }
-    return outputBuffer;
-}
-
-//
-// NewBase64Decode
-//
-// Encodes the arbitrary data in the inputBuffer as base64 into a newly malloced
-// output buffer.
-//
-//  inputBuffer - the source data for the encode
-//	length - the length of the input in bytes
-//  separateLines - if zero, no CR/LF characters will be added. Otherwise
-//		a CR/LF pair will be added every 64 encoded chars.
-//	outputLength - if not-NULL, on output will contain the encoded length
-//		(not including terminating 0 char)
-//
-// returns the encoded buffer. Must be freed by caller. Length is given by
-//	outputLength.
-//
-char *NewBase64Encode(
-                         const void* buffer,
-                         size_t    length,
-                         bool      separateLines,
-                         size_t    * outputLength)
-{
-    const unsigned char* inputBuffer = (const unsigned char*)buffer;
-    
-#define MAX_NUM_PADDING_CHARS 2
-#define OUTPUT_LINE_LENGTH 64
-#define INPUT_LINE_LENGTH ((OUTPUT_LINE_LENGTH / _BASE64_UNIT_SIZE) * _BINARY_UNIT_SIZE)
-#define CR_LF_SIZE 0
-    
-    //
-    // Byte accurate calculation of final buffer size
-    //
-    size_t outputBufferSize =
-    ((length / _BINARY_UNIT_SIZE)
-     + ((length % _BINARY_UNIT_SIZE) ? 1 : 0))
-    * _BASE64_UNIT_SIZE;
-    if (separateLines) {
-        outputBufferSize +=
-        (outputBufferSize / OUTPUT_LINE_LENGTH) * CR_LF_SIZE;
-    }
-    
-    //
-    // Include space for a terminating zero
-    //
-    outputBufferSize += 1;
-    
-    //
-    // Allocate the output buffer
-    //
-    char* outputBuffer = (char*)malloc(outputBufferSize);
-    if (!outputBuffer) {
-        return NULL;
-    }
-    
-    size_t i = 0;
-    size_t j = 0;
-    const size_t lineLength = separateLines ? INPUT_LINE_LENGTH : length;
-    size_t lineEnd = lineLength;
-    
-    while (true) {
-        if (lineEnd > length) {
-            lineEnd = length;
-        }
-        
-        for (; i + _BINARY_UNIT_SIZE - 1 < lineEnd; i += _BINARY_UNIT_SIZE) {
-            //
-            // Inner loop: turn 48 bytes into 64 base64 characters
-            //
-            outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2];
-            outputBuffer[j++] = base64EncodeLookup[((inputBuffer[i] & 0x03) << 4)
-                                                      | ((inputBuffer[i + 1] & 0xF0) >> 4)];
-            outputBuffer[j++] = base64EncodeLookup[((inputBuffer[i + 1] & 0x0F) << 2)
-                                                      | ((inputBuffer[i + 2] & 0xC0) >> 6)];
-            outputBuffer[j++] = base64EncodeLookup[inputBuffer[i + 2] & 0x3F];
-        }
-        
-        if (lineEnd == length) {
-            break;
-        }
-        
-        //
-        // Add the newline
-        //
-        // outputBuffer[j++] = '\r';
-        // outputBuffer[j++] = '\n';
-        lineEnd += lineLength;
-    }
-    
-    if (i + 1 < length) {
-        //
-        // Handle the single '=' case
-        //
-        outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2];
-        outputBuffer[j++] = base64EncodeLookup[((inputBuffer[i] & 0x03) << 4)
-                                                  | ((inputBuffer[i + 1] & 0xF0) >> 4)];
-        outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i + 1] & 0x0F) << 2];
-        outputBuffer[j++] = '=';
-    } else if (i < length) {
-        //
-        // Handle the double '=' case
-        //
-        outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2];
-        outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0x03) << 4];
-        outputBuffer[j++] = '=';
-        outputBuffer[j++] = '=';
-    }
-    outputBuffer[j] = 0;
-    
-    //
-    // Set the output length and return the buffer
-    //
-    if (outputLength) {
-        *outputLength = j;
-    }
-    return outputBuffer;
-}
-
-@implementation NSData (Base64)
-
-//
-// dataFromBase64String:
-//
-// Creates an NSData object containing the base64 decoded representation of
-// the base64 string 'aString'
-//
-// Parameters:
-//    aString - the base64 string to decode
-//
-// returns the autoreleased NSData representation of the base64 string
-//
-+ (NSData*)dataFromBase64String:(NSString*)aString
-{
-    size_t outputLength = 0;
-    void* outputBuffer = NewBase64Decode([aString UTF8String], [aString length], &outputLength);
-    
-    return [NSData dataWithBytesNoCopy:outputBuffer length:outputLength freeWhenDone:YES];
-}
-
-//
-// base64EncodedString
-//
-// Creates an NSString object that contains the base 64 encoding of the
-// receiver's data. Lines are broken at 64 characters long.
-//
-// returns an autoreleased NSString being the base 64 representation of the
-//	receiver.
-//
-- (NSString*)base64EncodedString
-{
-    size_t outputLength = 0;
-    char* outputBuffer =
-    NewBase64Encode([self bytes], [self length], true, &outputLength);
-    
-    NSString* result = [[NSString alloc] initWithBytesNoCopy:outputBuffer
-                                                      length:outputLength
-                                                    encoding:NSASCIIStringEncoding
-                                                freeWhenDone:YES];
-    
-    return result;
-}
-
-
-@end

+ 0 - 42
legacy/v3.1_macgap/app/SH3/MacGap/Classes/Commands/App.h

@@ -1,42 +0,0 @@
-//
-//  App.h
-//  MG
-//
-//  Created by Tim Debo on 5/27/14.
-//
-//
-
-#import "Command.h"
-
-
-@protocol AppExports <JSExport>
-
-- (void) terminate;
-- (void) activate;
-- (void) hide;
-- (void) unhide;
-- (void) beep;
-- (void) bounce;
-- (void) notify:(NSDictionary*)aNotification;
-- (void) closeNotification:(NSString*)notificationId;
-
-JSExportAs(setUserAgent, - (void) setCustomUserAgent:(NSString *)userAgentString);
-- (void) openURL:(NSString*)url;
-- (void) launch:(NSString *)name;
-- (void) log:(NSString *)msg;
-@property (readonly) NSNumber* idleTime;
-@property (readonly) NSString* applicationPath;
-@property (readonly) NSString* resourcePath;
-@property (readonly) NSString* documentsPath;
-@property (readonly) NSString* libraryPath;
-@property (readonly) NSString* homePath;
-@property (readonly) NSString* tempPath;
-@property (readonly) NSArray* droppedFiles;
-@property (readonly) NSMutableArray* notifications;
-@end
-
-@interface App : Command <AppExports>
-
-- (id) initWithWebView:(WebView *)view;
-- (void) addFiles: (NSArray*) files;
-@end

+ 0 - 185
legacy/v3.1_macgap/app/SH3/MacGap/Classes/Commands/App.m

@@ -1,185 +0,0 @@
-//
-//  App.m
-//  MG
-//
-//  Created by Tim Debo on 5/27/14.
-//
-//
-
-#import "App.h"
-#import "Event.h"
-
-@interface App ()
-@property (readwrite) NSString* applicationPath;
-@property (readwrite) NSString* resourcePath;
-@property (readwrite) NSString* documentsPath;
-@property (readwrite) NSString* libraryPath;
-@property (readwrite) NSString* homePath;
-@property (readwrite) NSString* tempPath;
-@property (readwrite) NSArray* droppedFiles;
-@property (readwrite) NSMutableArray* notifications;
-@end
-
-@implementation App
-
-@synthesize webView, applicationPath, resourcePath, libraryPath, homePath, tempPath, idleTime;
-
-- (id) initWithWebView:(WebView *) view{
-    self = [super init];
-    
-    if (self) {
-        NSArray *docPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
-        NSArray *libPaths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
-        self.webView = view;
-        self.applicationPath = [[NSBundle mainBundle] bundlePath];
-        self.resourcePath = [[NSBundle mainBundle] resourcePath];
-        self.documentsPath = [docPaths objectAtIndex:0];
-        self.libraryPath = [libPaths objectAtIndex:0];
-        self.homePath = NSHomeDirectory();
-        self.tempPath = NSTemporaryDirectory();
-        self.droppedFiles = nil;
-        self.notifications = [NSMutableArray arrayWithCapacity: 2];
-        
-        [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver: self
-                                                               selector: @selector(receiveSleepNotification:)
-                                                                   name: NSWorkspaceWillSleepNotification object: NULL];
-        [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver: self
-                                                               selector: @selector(receiveWakeNotification:)
-                                                                   name: NSWorkspaceDidWakeNotification object: NULL];
-        [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver: self
-                                                               selector: @selector(receiveActivateNotification:)
-                                                                   name: NSWorkspaceDidActivateApplicationNotification object: NULL];
-    }
-    
-    return self;
-}
-
-- (void) terminate {
-    [NSApp terminate:nil];
-}
-
-- (void) activate {
-    [[NSRunningApplication currentApplication] activateWithOptions:(NSApplicationActivateAllWindows | NSApplicationActivateIgnoringOtherApps)];
-    [[NSApplication sharedApplication].windows.firstObject makeKeyAndOrderFront:nil];
-}
-
-- (void) hide {
-    [NSApp hide:nil];
-}
-
-- (void) unhide {
-    [NSApp unhide:nil];
-}
-
-- (void)beep {
-    NSBeep();
-}
-
-- (void) bounce {
-    [NSApp requestUserAttention:NSInformationalRequest];
-}
-
-- (void) addFiles: (NSArray*) files
-{
-    self.droppedFiles = files;
-}
-- (void)setCustomUserAgent:(NSString *)userAgentString {
-    [self.webView setCustomUserAgent: userAgentString];
-}
-
-- (void) openURL:(NSString*)url {
-    [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:url]];
-}
-
-- (void) launch:(NSString *)name {
-    [[NSWorkspace sharedWorkspace] launchApplication:name];
-}
-
-- (void)receiveSleepNotification:(NSNotification*)note{
-    [Event triggerEvent:@"sleep" forWebView:self.webView];
-}
-
-- (void) receiveWakeNotification:(NSNotification*)note{
-    [Event triggerEvent:@"wake" forWebView:self.webView];
-}
-
-- (void) receiveActivateNotification:(NSNotification*)notification{
-    NSDictionary* userInfo = [notification userInfo];
-    NSRunningApplication* runningApplication = [userInfo objectForKey:NSWorkspaceApplicationKey];
-    if (runningApplication) {
-        NSMutableDictionary* applicationDidGetFocusDict = [[NSMutableDictionary alloc] initWithCapacity:2];
-        [applicationDidGetFocusDict setObject:runningApplication.localizedName
-                                       forKey:@"localizedName"];
-        [applicationDidGetFocusDict setObject:[runningApplication.bundleURL absoluteString]
-                                       forKey:@"bundleURL"];
-        
-        [Event triggerEvent:@"appActivated" withArgs:applicationDidGetFocusDict forWebView:self.webView];
-    }
-}
-
-- (void) notify:(NSDictionary*)aNotification {
-    NSString* type = [aNotification valueForKey:@"type"];
-    NSString* uid = [aNotification valueForKey:@"id"];
-
-    if([type isEqualToString:@"sheet"]) {
-        NSAlert *alert = [[NSAlert alloc] init];
-        [alert setMessageText:[aNotification valueForKey:@"title"]];
-        [alert setInformativeText:[aNotification valueForKey:@"content"]];
-        [alert beginSheetModalForWindow:[[NSApplication sharedApplication] mainWindow]
-                          modalDelegate:self
-                         didEndSelector:nil
-                            contextInfo:nil];
-        
-        
-    } else {
-        NSUserNotification *notification = [[NSUserNotification alloc] init];
-        
-        if(!uid) {
-            uid =[[NSUUID UUID] UUIDString];
-            
-        }
-        
-        [notification setTitle:[aNotification valueForKey:@"title"]];
-        [notification setInformativeText:[aNotification valueForKey:@"content"]];
-        [notification setSubtitle:[aNotification valueForKey:@"subtitle"]];
-        [notification setUserInfo:@{ @"id" : uid }];
-        
-        if([[aNotification valueForKey:@"sound"] boolValue] == YES || ![aNotification valueForKey:@"sound"] ) {
-            [notification setSoundName: NSUserNotificationDefaultSoundName];
-        }
-        [[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];
-        
-        [self.notifications addObject:@{ @"id" : uid, @"title" : [aNotification valueForKey: @"title"], @"sentOn" :[NSDate date] }];
-        
-    }
-}
-
-- (void) closeNotification:(NSString*)notificationId {
-    NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter];
-    for(NSUserNotification * deliveredNote in center.deliveredNotifications) {
-        if ([notificationId isEqualToString:@"*"] || [deliveredNote.userInfo[@"id"] isEqualToString:notificationId]) {
-            [center removeDeliveredNotification: deliveredNote];
-             //NSPredicate *predicate = [NSPredicate predicateWithFormat:@"id==%@", notificationId];
-             NSUInteger noteIdx = [self.notifications indexOfObjectPassingTest: ^BOOL(NSDictionary* obj, NSUInteger idx, BOOL *stop) {
-                                        return [[obj valueForKey:@"id"] isEqualToString:notificationId];
-                                  }];
-            if (noteIdx != NSNotFound)
-                [self.notifications removeObjectAtIndex:noteIdx];
-        }
-    }
-}
-
-/*
- To get the elapsed time since the previous input event—keyboard, mouse, or tablet—specify kCGAnyInputEventType.
- */
-- (NSNumber*) idleTime {
-    CFTimeInterval timeSinceLastEvent = CGEventSourceSecondsSinceLastEventType(kCGEventSourceStateHIDSystemState, kCGAnyInputEventType);
-    
-    return [NSNumber numberWithDouble:timeSinceLastEvent];
-}
-
-- (void)log:(NSString *)msg {
-    NSLog(@"%@", msg);
-}
-
-@end

+ 0 - 17
legacy/v3.1_macgap/app/SH3/MacGap/Classes/Commands/Clipboard.h

@@ -1,17 +0,0 @@
-//
-//  Clipboard.h
-//  MG
-//
-//  Created by Tim Debo on 5/28/14.
-//
-//
-
-#import "Command.h"
-@protocol ClipboardExports <JSExport>
-JSExportAs(copy, - (void) copy:(NSString*)text);
-- (NSString *) paste;
-@end
-
-@interface Clipboard : Command <ClipboardExports>
-
-@end

+ 0 - 30
legacy/v3.1_macgap/app/SH3/MacGap/Classes/Commands/Clipboard.m

@@ -1,30 +0,0 @@
-//
-//  Clipboard.m
-//  MG
-//
-//  Created by Tim Debo on 5/28/14.
-//
-//
-
-#import "Clipboard.h"
-
-@implementation Clipboard
-
-- (void) copy:(NSString*)text {
-    [[NSPasteboard generalPasteboard] clearContents];
-    [[NSPasteboard generalPasteboard] setString:text  forType:NSStringPboardType];
-}
-
-- (NSString *) paste {
-    NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
-    NSArray *classArray = [NSArray arrayWithObject:[NSString class]];
-    NSDictionary *options = [NSDictionary dictionary];
-    BOOL ok = [pasteboard canReadObjectForClasses:classArray options:options];
-    if (ok) {
-        NSArray *objectsToPaste = [pasteboard readObjectsForClasses:classArray options:options];
-        return (NSString *) [objectsToPaste objectAtIndex:0];
-    }
-    return @"";
-}
-
-@end

+ 0 - 27
legacy/v3.1_macgap/app/SH3/MacGap/Classes/Commands/Command.h

@@ -1,27 +0,0 @@
-//
-//  Command.h
-//  MG
-//
-//  Created by Tim Debo on 5/23/14.
-//
-//
-
-#import <Foundation/Foundation.h>
-#import <JavaScriptCore/JavaScriptCore.h>
-
-
-@class WindowController, WebView;
-
-@interface Command : NSObject
-{
-    JSContextRef jsContext;
-}
-+ (JSValue *)makeConstructor:(id)block inContext:(JSContext *)context;
-+ (JSValue *)constructor;
-- (NSString*) exportName;
-- (void) initializePlugin;
-- (id) initWithWindowController: (WindowController*)aWindowController;
-- (id) initWithContext:(JSContext*)aContext;
-@property (nonatomic, weak) WebView* webView;
-@property (nonatomic, weak) WindowController* windowController;
-@end

+ 0 - 58
legacy/v3.1_macgap/app/SH3/MacGap/Classes/Commands/Command.m

@@ -1,58 +0,0 @@
-//
-//  Command.m
-//  MG
-//
-//  Created by Tim Debo on 5/23/14.
-//
-//
-
-#import "Command.h"
-#import <WebKit/WebKit.h>
-#import "WindowController.h"
-
-@implementation Command
-@synthesize webView, windowController;
-+ (JSValue *)makeConstructor:(id)block inContext:(JSContext *)context {
-    JSValue *fun = [context evaluateScript:@"(function () { return this.__construct.apply(this, arguments); });"];
-    fun[@"prototype"][@"__construct"] = block;
-    return fun;
-}
-
-+ (JSValue *)constructor {
-    return [self makeConstructor:^{ return [self new]; } inContext:JSContext.currentContext];
-}
-
-- (NSString*) exportName {
-    return NSStringFromClass([self class]);
-}
-
-- (id) initWithWindowController:(WindowController *)aWindowController
-{
-    self = [super init];
-    if(self) {
-        self.windowController = aWindowController;
-        self.webView = aWindowController.webView;
-    }
-    
-    return self;
-
-}
-
-- (id) initWithContext:(JSContext*)context {
-    self = [super init];
-    if (!self)
-        return nil;
-    jsContext = [context JSGlobalContextRef];
-    JSGlobalContextRetain((JSGlobalContextRef)jsContext);
-    return self;
-}
-
-- (void)dealloc
-{
-    if (jsContext)
-        JSGlobalContextRelease((JSGlobalContextRef)jsContext);
-}
-
-- (void) initializePlugin {}
-
-@end

+ 0 - 23
legacy/v3.1_macgap/app/SH3/MacGap/Classes/Commands/Defaults.h

@@ -1,23 +0,0 @@
-//
-//  Defaults.h
-//  MG
-//
-//  Created by Tim Debo on 6/1/14.
-//
-//
-
-#import "Command.h"
-@protocol DefaultExports <JSExport>
-@property (readonly) NSDictionary* defaults;
-JSExportAs(get, - (JSValue*) get: (NSString*) key ofType: (NSString*) type);
-JSExportAs(set, - (void) setKey:(NSString*)key withValue: (JSValue*) value ofType: (NSString*) type);
-- (void) remove: (NSString*) key;
-@end
-
-@interface Defaults : Command <DefaultExports>
-
-- (void)defaultsChanged:(NSNotification *)notification;
-- (NSDictionary*) defaultsDictionary;
-
-
-@end

+ 0 - 150
legacy/v3.1_macgap/app/SH3/MacGap/Classes/Commands/Defaults.m

@@ -1,150 +0,0 @@
-//
-//  Defaults.m
-//  MG
-//
-//  Created by Tim Debo on 6/1/14.
-//
-//
-
-#import "Defaults.h"
-#import "WindowController.h"
-#import "Event.h"
-#import "JSON.h"
-
-typedef id (^ReturnType)();
-typedef void (^SetType)();
-
-@interface Defaults ()
-- (NSString*) addPrefix:(NSString*)key;
-
-@end
-
-@implementation Defaults
-@synthesize defaults;
-
-- (id) initWithWindowController:(WindowController *)aWindowController
-{
-    self = [super init];
-    if(self) {
-        self.windowController = aWindowController;
-        self.webView = aWindowController.webView;
- 
-        [[NSNotificationCenter defaultCenter] addObserver:self
-                                                 selector:@selector(defaultsChanged:)
-                                                     name:NSUserDefaultsDidChangeNotification
-                                                   object:nil];
-        
-    }
-    
-    return self;
-    
-}
-- (void)dealloc
-{
-    [[NSNotificationCenter defaultCenter] removeObserver: self];
-}
-
-- (JSValue*) defaults
-{
-     return [JSValue valueWithObject: [self defaultsDictionary] inContext: [JSContext currentContext] ];
-}
-
-- (JSValue*) get:(NSString *)key ofType:(NSString *)type
-{
-    if(!key || [key isKindOfClass:[NSNull class]])
-        return nil;
-    
-    if(!type || [type isKindOfClass:[NSNull class]]) {
-        type = @"string";
-    }
-    
-    NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
-    NSString* pfxKey = [self addPrefix:key];
-    NSDictionary *types = @{
-                            @"string" : ^{ return [prefs stringForKey:pfxKey];},
-                            @"int" : ^{ return [NSNumber numberWithInteger:[prefs integerForKey:pfxKey]]; },
-                            @"bool" : ^{ return [NSNumber numberWithBool:[prefs boolForKey:pfxKey]]; },
-                            @"float" : ^{ return [NSNumber numberWithFloat:[prefs floatForKey:pfxKey]]; },
-                            @"url" : ^{ return [[prefs URLForKey:pfxKey] absoluteString]; },
-                            @"object" : ^{ return [prefs dictionaryForKey:pfxKey]; }
-                            };
-    id returnVal = nil;
-    ReturnType theType = types[type];
-  
-    if(theType) {
-        returnVal = theType();
-    } else {
-        //nil for now but we really should raise a JS Exception for this..
-        return nil;
-    }
-    return [JSValue valueWithObject: returnVal inContext:[JSContext currentContext]];
-}
-
-- (void) setKey:(NSString*)key withValue: (JSValue*) value ofType: (NSString*) type
-{
-    if(!key || [key isKindOfClass:[NSNull class]])
-        return;
-    
-    if(!type || [type isKindOfClass:[NSNull class]]) {
-        type = @"string";
-    }
-    
-    NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
-    NSString* pfxKey = [self addPrefix:key];
-    
-    NSDictionary *types = @{
-                            @"string" : ^{ [prefs setObject: [value toString] forKey:pfxKey]; DebugNSLog(@"Set String: %@", value); },
-                            @"int" : ^{  [prefs setInteger: [value toInt32] forKey:pfxKey]; DebugNSLog(@"Set int: %@",value);},
-                            @"bool" : ^{  [prefs setBool: [value toBool] forKey:pfxKey]; DebugNSLog(@"Set bool: %@",value);},
-                            @"float" : ^{  [prefs setFloat: [[value toNumber] floatValue] forKey:pfxKey]; DebugNSLog(@"Set float: %@",value);},
-                            @"url" : ^{  [prefs setURL:[NSURL URLWithString: [value toString]] forKey:pfxKey]; DebugNSLog(@"Set url: %@",value);},
-                           
-                            };
-
-    ((SetType) types[type])();
-    
-}
-
-- (void) remove: (NSString*) key
-{
-    NSString* prefixedKey;
-    prefixedKey = [self addPrefix:key];
-    
-    [[NSUserDefaults standardUserDefaults] removeObjectForKey:prefixedKey];
-    [[NSUserDefaults standardUserDefaults] synchronize];
-}
-
-// Check we have a standard prefix for JS-modified keys, for security purposes.
-// If not, add it. This stops JavaScript from ever being able to modify keys
-// it did not create.
-- (NSString*) addPrefix:(NSString*)key {
-    NSString* prefix;
-    prefix = [kWebScriptNamespace stringByAppendingString:@"_"];
-    
-    if (![key hasPrefix:prefix]) {
-        key = [prefix stringByAppendingString:key];
-    }
-    return key;
-}
-
-- (void)defaultsChanged:(NSNotification *)notification {
-    NSDictionary* returnDict = [self defaultsDictionary];
-    [Event triggerEvent:@"userDefaultsChanged" withArgs:returnDict forWebView:self.webView];
-}
-
-- (NSDictionary*) defaultsDictionary {
-    NSString* prefix = [kWebScriptNamespace stringByAppendingString:@"_"];
-    NSMutableDictionary* returnDict = [[NSMutableDictionary alloc] init];
-    
-    // Get the user defaults.
-    NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];
-    [[defs dictionaryRepresentation] enumerateKeysAndObjectsUsingBlock:^( id key, id val, BOOL *stop) {
-        if([key hasPrefix: prefix]) {
-            [returnDict setObject: val forKey: key];
-        }
-    }];
-     
-    return returnDict;
-}
-
-@end

+ 0 - 22
legacy/v3.1_macgap/app/SH3/MacGap/Classes/Commands/Dialog.h

@@ -1,22 +0,0 @@
-//
-//  Dialog.h
-//  MG
-//
-//  Created by Tim Debo on 5/27/14.
-//
-//
-
-#import <Foundation/Foundation.h>
-#import "Command.h"
-#import <JavaScriptCore/JavaScriptCore.h>
-
-@protocol DialogExports <JSExport>
-- (void) openDialog:(JSValue *)args;
-- (void) saveDialog: (JSValue*)args;
-@end
-
-@interface Dialog : Command <DialogExports>
-
-@property (assign) JSContext* context;
-
-@end

+ 0 - 102
legacy/v3.1_macgap/app/SH3/MacGap/Classes/Commands/Dialog.m

@@ -1,102 +0,0 @@
-//
-//  Dialog.m
-//  MG
-//
-//  Created by Tim Debo on 5/27/14.
-//
-//
-
-#import "Dialog.h"
-#import "WindowController.h"
-
-@implementation Dialog
-@synthesize context;
-
-- (void) openDialog:(JSValue *)args
-{
-    
-    context = [JSContext currentContext];
-        
-    NSOpenPanel * openDlg = [NSOpenPanel openPanel];
-    
-    JSValue* mult = [args valueForProperty:@"multiple"];
-    JSValue* files = [args valueForProperty:@"files"];
-    JSValue* dirs = [args valueForProperty:@"directories"];
-    JSValue* cb = [args valueForProperty: @"callback"];
-    JSValue* allowedTypes = [args valueForProperty:@"allowedTypes"];
-    [openDlg setCanChooseFiles: [files toBool]];
-    [openDlg setCanChooseDirectories: [dirs toBool]];
-    [openDlg setAllowsMultipleSelection: [mult toBool]];
-    if(allowedTypes)
-        [openDlg setAllowedFileTypes: [allowedTypes toArray]];
-    [openDlg beginWithCompletionHandler:^(NSInteger result){
-      
-        if (result == NSFileHandlingPanelOKButton) {
-            
-            if(cb) {
-                NSArray* files = [[openDlg URLs] valueForKey:@"relativePath"];
-                [cb callWithArguments: @[files]];
-            }
-            
-        }
-    }];
-
-
-}
-
-- (void) saveDialog:(JSValue *)args
-{
-    context = [JSContext currentContext];
-    NSSavePanel * saveDlg = [NSSavePanel savePanel];
-    JSValue* title = [args valueForProperty:@"title"];
-    JSValue* prompt = [args valueForProperty:@"prompt"];
-    JSValue* message = [args valueForProperty:@"message"];
-    JSValue* filename = [args valueForProperty:@"filename"];
-    JSValue* directory = [args valueForProperty:@"directory"];
-    JSValue* createDirs = [args valueForProperty:@"createDirs"];
-    JSValue* allowedTypes = [args valueForProperty:@"allowedTypes"];
-    JSValue* cb = [args valueForProperty: @"callback"];
-    
-    if(title)
-        [saveDlg setTitle: [title toString]];
-    
-    if(prompt)
-        [saveDlg setPrompt: [prompt toString]];
-
-    
-    if(message)
-        [saveDlg setMessage: [message toString]];
-
-    
-    if(filename)
-        [saveDlg setNameFieldStringValue: [filename toString]];
-
-    if(directory)
-        [saveDlg setDirectoryURL: [NSURL URLWithString: [directory toString]]];
-    
-    if(createDirs)
-        [saveDlg setCanCreateDirectories: [createDirs toBool]];
-    
-    if(allowedTypes)
-        [saveDlg setAllowedFileTypes: [allowedTypes toArray]];
-    
-    [saveDlg beginSheetModalForWindow: self.windowController.window completionHandler:^(NSInteger result){
-        
-        if (result == NSFileHandlingPanelOKButton) {
-            
-            if(cb) {
-                NSDictionary* results = @{
-                                          @"directory" : [[saveDlg directoryURL] valueForKey:@"relativePath"],
-                                          @"filePath" : [[saveDlg URL] valueForKey:@"relativePath"],
-                                          @"filename" : [saveDlg nameFieldStringValue]
-                                          };
-                
-                [cb callWithArguments: @[results]];
-            }
-            
-        }
-    }];
-    
-}
-
-@end

+ 0 - 24
legacy/v3.1_macgap/app/SH3/MacGap/Classes/Commands/Dock.h

@@ -1,24 +0,0 @@
-//
-//  Dock.h
-//  MG
-//
-//  Created by Tim Debo on 5/22/14.
-//
-//
-#import <Foundation/Foundation.h>
-#import "Command.h"
-
-
-@protocol DockExports <JSExport>
-
-@property (readonly) NSString* badge;
-- (void) addBadge: (NSString*) badge;
-- (void) removeBadge;
-- (void) hideIcon;
-- (void) showIcon;
-@end
-
-@interface Dock : Command <DockExports>
-
-
-@end

+ 0 - 38
legacy/v3.1_macgap/app/SH3/MacGap/Classes/Commands/Dock.m

@@ -1,38 +0,0 @@
-//
-//  Dock.m
-//  MG
-//
-//  Created by Tim Debo on 5/22/14.
-//
-//
-
-#import "Dock.h"
-
-
-@implementation Dock
-
-
-- (JSValue *)badge {
-    NSDockTile *tile = [[NSApplication sharedApplication] dockTile];
-    return [JSValue valueWithObject:[tile badgeLabel] inContext:JSContext.currentContext];
-}
-
-- (void)addBadge:(NSString *)badge {
-    NSDockTile *tile = [[NSApplication sharedApplication] dockTile];
-    [tile setBadgeLabel:badge];
-}
-
-- (void)removeBadge {
-    NSDockTile *tile = [[NSApplication sharedApplication] dockTile];
-    [tile setBadgeLabel:nil];
-}
-
-- (void)hideIcon {
-    [NSApp setActivationPolicy:NSApplicationActivationPolicyAccessory];
-}
-
-- (void)showIcon {
-    [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
-}
-
-@end

+ 0 - 24
legacy/v3.1_macgap/app/SH3/MacGap/Classes/Commands/Event.h

@@ -1,24 +0,0 @@
-//
-//  Event.h
-//  MG
-//
-//  Created by Tim Debo on 5/23/14.
-//
-//
-
-#import <Foundation/Foundation.h>
-#import <JavaScriptCore/JavaScriptCore.h>
-#import "WindowController.h"
-
-@interface Event : NSObject
-
-//+ (void) triggerEvent:(NSString *)event forContext:(JSContext*) context;
-//+ (void) triggerEvent:(NSString *)event withArgs:(NSDictionary *)args forContext:(JSContext*) context;
-//+ (void) triggerEvent:(NSString *)event withArgs:(NSDictionary *)args forObject:(NSString *)objName forContext:(JSContext*) context;
-
-+ (void) triggerEvent:(NSString *)event forWebView:(WebView *)webView;
-+ (void) triggerEvent:(NSString *)event withArgs:(NSDictionary *)args forWebView:(WebView *)webView;
-+ (void) triggerEvent:(NSString *)event withArgs:(NSDictionary *)args forObject:(NSString *)objName forWebView:(WebView *)webView;
-+ (void) triggerDomEvent:(NSString *)event withArgs:(NSDictionary *)args forWebView:(WebView *)webView;
-
-@end

Some files were not shown because too many files changed in this diff