ui.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. # -*- coding: utf-8 -*-
  2. import os
  3. import wx, wx.html
  4. import wx.lib.buttons as buttons
  5. import common_operations as co
  6. class Frame(wx.Frame):
  7. ID_HOSTS_TEXT = wx.NewId()
  8. def __init__(self,
  9. parent=None, id=wx.ID_ANY, title="SwitchHost!", pos=wx.DefaultPosition,
  10. size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE,
  11. cls_TaskBarIcon=None
  12. ):
  13. wx.Frame.__init__(self, parent, id, title, pos, size, style)
  14. self.SetIcon(co.GetMondrianIcon())
  15. self.taskbar_icon = cls_TaskBarIcon(self)
  16. # self.Bind(wx.EVT_CLOSE, self.OnClose)
  17. self.SetSizeHintsSz(wx.DefaultSize, wx.DefaultSize)
  18. self.m_menubar1 = wx.MenuBar(0)
  19. self.m_menu1 = wx.Menu()
  20. self.m_menuItem_new = wx.MenuItem(self.m_menu1, wx.ID_NEW, u"新建(&N)", wx.EmptyString, wx.ITEM_NORMAL)
  21. self.m_menu1.AppendItem(self.m_menuItem_new)
  22. self.m_menu1.AppendSeparator()
  23. self.m_menuItem_exit = wx.MenuItem(self.m_menu1, wx.ID_EXIT, u"退出(&X)", wx.EmptyString, wx.ITEM_NORMAL)
  24. self.m_menu1.AppendItem(self.m_menuItem_exit)
  25. self.m_menubar1.Append(self.m_menu1, u"文件(&F)")
  26. self.m_menu2 = wx.Menu()
  27. self.m_menuItem_about = wx.MenuItem(self.m_menu2, wx.ID_ABOUT, u"关于(&A)", wx.EmptyString, wx.ITEM_NORMAL)
  28. self.m_menu2.AppendItem(self.m_menuItem_about)
  29. self.m_menubar1.Append(self.m_menu2, u"帮助(&H)")
  30. self.SetMenuBar(self.m_menubar1)
  31. bSizer1 = wx.BoxSizer(wx.VERTICAL)
  32. self.m_panel1 = wx.Panel(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL)
  33. bSizer4 = wx.BoxSizer(wx.HORIZONTAL)
  34. bSizer5 = wx.BoxSizer(wx.VERTICAL)
  35. self.m_list = wx.ListCtrl(self.m_panel1, wx.ID_ANY, wx.DefaultPosition, wx.Size(160, 320),
  36. wx.LC_REPORT)
  37. self.m_list.Hide()
  38. bSizer5.Add(self.m_list, 0, wx.ALL | wx.EXPAND, 5)
  39. self.m_tree = wx.TreeCtrl(self.m_panel1, wx.ID_ANY, wx.DefaultPosition, wx.Size(160, 320))
  40. self.tree_root = self.m_tree.AddRoot(u"hosts")
  41. self.tree_local = self.m_tree.AppendItem(self.tree_root, u"本地方案")
  42. self.tree_online = self.m_tree.AppendItem(self.tree_root, u"在线方案")
  43. self.m_tree.ExpandAll()
  44. bSizer5.Add(self.m_tree, 0, wx.ALL | wx.EXPAND, 5)
  45. bSizer61 = wx.BoxSizer(wx.HORIZONTAL)
  46. self.m_btn_add = buttons.GenBitmapTextButton(self.m_panel1, wx.ID_ADD, co.GetMondrianBitmap(fn="add"), u"添加")
  47. bSizer61.Add(self.m_btn_add, 0, wx.ALL, 5)
  48. self.m_btn_del = buttons.GenBitmapTextButton(self.m_panel1, wx.ID_DELETE, co.GetMondrianBitmap(fn="delete"), u"删除")
  49. bSizer61.Add(self.m_btn_del, 0, wx.ALL, 5)
  50. bSizer5.Add(bSizer61, 1, wx.EXPAND, 5)
  51. bSizer4.Add(bSizer5, 0, wx.EXPAND, 5)
  52. bSizer6 = wx.BoxSizer(wx.VERTICAL)
  53. self.m_textCtrl_content = wx.TextCtrl(self.m_panel1, self.ID_HOSTS_TEXT, wx.EmptyString, wx.DefaultPosition,
  54. wx.DefaultSize,
  55. wx.TE_MULTILINE|wx.TE_RICH2|wx.TE_PROCESS_TAB|wx.HSCROLL)
  56. self.m_textCtrl_content.SetMaxLength(0)
  57. bSizer6.Add(self.m_textCtrl_content, 1, wx.ALL | wx.EXPAND, 5)
  58. bSizer7 = wx.BoxSizer(wx.HORIZONTAL)
  59. self.m_panel3 = wx.Panel(self.m_panel1, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL)
  60. bSizer71 = wx.BoxSizer(wx.HORIZONTAL)
  61. # self.m_btn_save = buttons.GenBitmapTextButton(self.m_panel3, wx.ID_SAVE, co.GetMondrianBitmap(fn="disk"), u"保存")
  62. # bSizer71.Add(self.m_btn_save, 0, wx.ALL, 0)
  63. self.m_panel3.SetSizer(bSizer71)
  64. self.m_panel3.Layout()
  65. bSizer71.Fit(self.m_panel3)
  66. bSizer7.Add(self.m_panel3, 1, wx.EXPAND | wx.ALL, 5)
  67. self.m_btn_apply = buttons.GenBitmapTextButton(self.m_panel1, wx.ID_APPLY, co.GetMondrianBitmap(fn="accept"), u"应用")
  68. # self.m_btn_apply = wx.Button(self.m_panel1, wx.ID_APPLY, u"应用", wx.DefaultPosition, wx.DefaultSize, 0)
  69. bSizer7.Add(self.m_btn_apply, 0, wx.ALL, 5)
  70. if cls_TaskBarIcon and os.name == "nt":
  71. # ubuntu 10.04 下点击这个图标时会报错,图标的菜单无法正常工作
  72. # ubuntu 11.04 下这个图标总是无法显示
  73. # 由于跨平台问题,暂时决定只在 windows 下显示快捷的任务栏图标
  74. # 参见:http://stackoverflow.com/questions/7144756/wx-taskbaricon-on-ubuntu-11-04
  75. self.m_btn_exit = buttons.GenBitmapTextButton(self.m_panel1, wx.ID_CLOSE, co.GetMondrianBitmap(fn="door"), u"隐藏")
  76. # self.m_btn_exit = wx.Button(self.m_panel1, wx.ID_CLOSE, u"隐藏", wx.DefaultPosition, wx.DefaultSize, 0)
  77. bSizer7.Add(self.m_btn_exit, 0, wx.ALL, 5)
  78. bSizer6.Add(bSizer7, 0, wx.EXPAND, 5)
  79. bSizer4.Add(bSizer6, 1, wx.EXPAND, 5)
  80. self.m_panel1.SetSizer(bSizer4)
  81. self.m_panel1.Layout()
  82. bSizer4.Fit(self.m_panel1)
  83. bSizer1.Add(self.m_panel1, 1, wx.EXPAND | wx.ALL, 0)
  84. self.SetSizer(bSizer1)
  85. self.Layout()
  86. self.Centre(wx.BOTH)
  87. self.font_bold = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
  88. self.font_bold.SetWeight(wx.BOLD)
  89. self.font_normal = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
  90. self.font_normal.SetWeight(wx.NORMAL)
  91. self.font_mono = wx.Font(10, wx.ROMAN, wx.NORMAL, wx.NORMAL, faceName="Courier New")
  92. def alert(self, title, msg):
  93. dlg = wx.MessageDialog(None, msg, title, wx.OK | wx.ICON_WARNING)
  94. dlg.ShowModal()
  95. dlg.Destroy()
  96. class AboutHtml(wx.html.HtmlWindow):
  97. def __init__(self, parent, id=-1, size=(480, 360)):
  98. wx.html.HtmlWindow.__init__(self, parent, id, size=size)
  99. if "gtk2" in wx.PlatformInfo:
  100. self.SetStandardFonts()
  101. def OnLinkClicked(self, link):
  102. wx.LaunchDefaultBrowser(link.GetHref())
  103. class AboutBox(wx.Dialog):
  104. u"""关于对话框
  105. 参考自:http://wiki.wxpython.org/wxPython%20by%20Example
  106. """
  107. def __init__(self, version=None, latest_stable_version=None):
  108. wx.Dialog.__init__(self, None, -1, u"关于",
  109. style=wx.DEFAULT_DIALOG_STYLE|wx.THICK_FRAME|wx.TAB_TRAVERSAL
  110. )
  111. update_version = u"正在检查新版本..."
  112. if latest_stable_version:
  113. cv = self.compareVersion(version, latest_stable_version)
  114. if cv < 0:
  115. update_version = u"更新的稳定版 v%s 已经发布!" % latest_stable_version
  116. else:
  117. update_version = u"当前版本已是最新版。"
  118. hwin = AboutHtml(self)
  119. hwin.SetPage(u"""
  120. <font size="9" color="#44474D"><b>SwitchHost!</b></font><br />
  121. <font size="3" color="#44474D">%(version)s</font><br /><br />
  122. <font size="3" color="#909090"><i>%(update_version)s</i></font><br />
  123. <p>
  124. 本程序用于在多个 hosts 之间快速切换。
  125. </p>
  126. <p>
  127. 源码:<a href="https://github.com/oldj/SwitchHosts">https://github.com/oldj/SwitchHosts</a><br />
  128. 作者:<a href="http://oldj.net">oldj</a>
  129. </p>
  130. """ % {
  131. "version": version,
  132. "update_version": update_version,
  133. })
  134. btn = hwin.FindWindowById(wx.ID_OK)
  135. irep = hwin.GetInternalRepresentation()
  136. hwin.SetSize((irep.GetWidth() + 25, irep.GetHeight() + 30))
  137. self.SetClientSize(hwin.GetSize())
  138. self.CenterOnParent(wx.BOTH)
  139. self.SetFocus()
  140. def compareVersion(self, v1, v2):
  141. u"""比较两个版本的大小
  142. 版本的格式形如:0.1.5.3456
  143. 如果 v1 > v2,则返回 1
  144. 如果 v1 = v2,则返回 0
  145. 如果 v1 < v2,则返回 -1
  146. """
  147. a1 = v1.split(".")
  148. a2 = v2.split(".")
  149. try:
  150. a1 = [int(i) for i in a1]
  151. a2 = [int(i) for i in a2]
  152. except Exception:
  153. return 0
  154. len1 = len(a1)
  155. len2 = len(a2)
  156. l = min(len1, len2)
  157. for i in range(l):
  158. if a1[i] > a2[i]:
  159. return 1
  160. elif a1[i] < a2[i]:
  161. return -1
  162. if len1 > len2:
  163. return 1
  164. elif len1 < len2:
  165. return -1
  166. else:
  167. return 0
  168. class Dlg_addHosts(wx.Dialog):
  169. def __init__( self, parent ):
  170. wx.Dialog.__init__(self, parent, id=wx.ID_ANY, title=wx.EmptyString, pos=wx.DefaultPosition,
  171. size=wx.Size(400, 200), style=wx.DEFAULT_DIALOG_STYLE)
  172. self.SetSizeHintsSz(wx.DefaultSize, wx.DefaultSize)
  173. bSizer9 = wx.BoxSizer(wx.VERTICAL)
  174. self.m_panel9 = wx.Panel(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL)
  175. bSizer10 = wx.BoxSizer(wx.VERTICAL)
  176. bSizer231 = wx.BoxSizer(wx.HORIZONTAL)
  177. self.m_radioBtn_local = wx.RadioButton(self.m_panel9, wx.ID_ANY, u"本地方案", wx.DefaultPosition, wx.DefaultSize, 0)
  178. self.m_radioBtn_local.SetValue(True)
  179. bSizer231.Add(self.m_radioBtn_local, 0, wx.ALL, 5)
  180. self.m_radioBtn_online = wx.RadioButton(self.m_panel9, wx.ID_ANY, u"在线方案", wx.DefaultPosition, wx.DefaultSize,
  181. 0)
  182. bSizer231.Add(self.m_radioBtn_online, 0, wx.ALL, 5)
  183. bSizer10.Add(bSizer231, 1, wx.EXPAND, 5)
  184. bSizer111 = wx.BoxSizer(wx.HORIZONTAL)
  185. self.m_staticText21 = wx.StaticText(self.m_panel9, wx.ID_ANY, u"方案名:", wx.DefaultPosition, wx.Size(60, -1), 0)
  186. self.m_staticText21.Wrap(-1)
  187. bSizer111.Add(self.m_staticText21, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
  188. self.m_textCtrl_title = wx.TextCtrl(self.m_panel9, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize
  189. , 0)
  190. self.m_textCtrl_title.SetMaxLength(32)
  191. self.m_textCtrl_title.SetToolTipString(u"在这儿输入方案名称。")
  192. bSizer111.Add(self.m_textCtrl_title, 1, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
  193. bSizer10.Add(bSizer111, 1, wx.EXPAND, 5)
  194. bSizer1612 = wx.BoxSizer(wx.HORIZONTAL)
  195. self.m_staticText512 = wx.StaticText(self.m_panel9, wx.ID_ANY, u"URL:", wx.DefaultPosition, wx.Size(60, -1), 0)
  196. self.m_staticText512.Wrap(-1)
  197. bSizer1612.Add(self.m_staticText512, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
  198. self.m_textCtrl_url = wx.TextCtrl(self.m_panel9, wx.ID_ANY, u"http://", wx.DefaultPosition, wx.DefaultSize, 0)
  199. self.m_textCtrl_url.SetMaxLength(1024)
  200. self.m_textCtrl_url.Enable(False)
  201. self.m_textCtrl_url.SetToolTipString(u"在这儿输入方案的url地址,如:\nhttp://192.168.1.100/hosts/sample.hosts 。")
  202. bSizer1612.Add(self.m_textCtrl_url, 1, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
  203. bSizer10.Add(bSizer1612, 1, wx.EXPAND, 5)
  204. self.m_panel9.SetSizer(bSizer10)
  205. self.m_panel9.Layout()
  206. bSizer10.Fit(self.m_panel9)
  207. bSizer9.Add(self.m_panel9, 2, wx.EXPAND | wx.ALL, 5)
  208. self.m_staticline211 = wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL)
  209. bSizer9.Add(self.m_staticline211, 0, wx.EXPAND | wx.ALL, 5)
  210. m_sdbSizer1 = wx.StdDialogButtonSizer()
  211. self.m_sdbSizer1OK = wx.Button(self, wx.ID_OK)
  212. m_sdbSizer1.AddButton(self.m_sdbSizer1OK)
  213. self.m_sdbSizer1Cancel = wx.Button(self, wx.ID_CANCEL)
  214. m_sdbSizer1.AddButton(self.m_sdbSizer1Cancel)
  215. m_sdbSizer1.Realize();
  216. bSizer9.Add(m_sdbSizer1, 1, wx.EXPAND, 5)
  217. self.SetSizer(bSizer9)
  218. self.Layout()
  219. self.Centre(wx.BOTH)
  220. self.__binds()
  221. def __del__( self ):
  222. pass
  223. def __binds(self):
  224. self.Bind(wx.EVT_RADIOBUTTON, self.switchToLocal, self.m_radioBtn_local)
  225. self.Bind(wx.EVT_RADIOBUTTON, self.switchToOnline, self.m_radioBtn_online)
  226. def switchToLocal(self, event):
  227. # print("local!")
  228. self.m_textCtrl_url.Enabled = False
  229. def switchToOnline(self, event):
  230. # print("online!")
  231. self.m_textCtrl_url.Enabled = True