TrayiconPlugin.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. import os
  2. import sys
  3. import atexit
  4. from Plugin import PluginManager
  5. from Config import config
  6. from Translate import Translate
  7. allow_reload = False # No source reload supported in this plugin
  8. plugin_dir = os.path.dirname(__file__)
  9. if "_" not in locals():
  10. _ = Translate(plugin_dir + "/languages/")
  11. @PluginManager.registerTo("Actions")
  12. class ActionsPlugin(object):
  13. def main(self):
  14. global notificationicon, winfolders
  15. from .lib import notificationicon, winfolders
  16. import gevent.threadpool
  17. import main
  18. self.main = main
  19. icon = notificationicon.NotificationIcon(
  20. os.path.join(os.path.dirname(os.path.abspath(__file__)), 'trayicon.ico'),
  21. "ZeroNet %s" % config.version
  22. )
  23. self.icon = icon
  24. self.console = False
  25. @atexit.register
  26. def hideIcon():
  27. try:
  28. icon.die()
  29. except Exception as err:
  30. print("Error removing trayicon: %s" % err)
  31. ui_ip = config.ui_ip if config.ui_ip != "*" else "127.0.0.1"
  32. if ":" in ui_ip:
  33. ui_ip = "[" + ui_ip + "]"
  34. icon.items = [
  35. (self.titleIp, False),
  36. (self.titleConnections, False),
  37. (self.titleTransfer, False),
  38. (self.titleConsole, self.toggleConsole),
  39. (self.titleAutorun, self.toggleAutorun),
  40. "--",
  41. (_["ZeroNet Twitter"], lambda: self.opensite("https://twitter.com/HelloZeroNet")),
  42. (_["ZeroNet Reddit"], lambda: self.opensite("http://www.reddit.com/r/zeronet/")),
  43. (_["ZeroNet Github"], lambda: self.opensite("https://github.com/HelloZeroNet/ZeroNet")),
  44. (_["Report bug/request feature"], lambda: self.opensite("https://github.com/HelloZeroNet/ZeroNet/issues")),
  45. "--",
  46. (_["!Open ZeroNet"], lambda: self.opensite("http://%s:%s/%s" % (ui_ip, config.ui_port, config.homepage))),
  47. "--",
  48. (_["Quit"], self.quit),
  49. ]
  50. if not notificationicon.hasConsole():
  51. del icon.items[3]
  52. icon.clicked = lambda: self.opensite("http://%s:%s/%s" % (ui_ip, config.ui_port, config.homepage))
  53. self.quit_servers_event = gevent.threadpool.ThreadResult(
  54. lambda res: gevent.spawn_later(0.1, self.quitServers), gevent.threadpool.get_hub(), lambda: True
  55. ) # Fix gevent thread switch error
  56. gevent.threadpool.start_new_thread(icon._run, ()) # Start in real thread (not gevent compatible)
  57. super(ActionsPlugin, self).main()
  58. icon._die = True
  59. def quit(self):
  60. self.icon.die()
  61. self.quit_servers_event.set(True)
  62. def quitServers(self):
  63. self.main.ui_server.stop()
  64. self.main.file_server.stop()
  65. def opensite(self, url):
  66. import webbrowser
  67. webbrowser.open(url, new=0)
  68. def titleIp(self):
  69. title = "!IP: %s " % ", ".join(self.main.file_server.ip_external_list)
  70. if any(self.main.file_server.port_opened):
  71. title += _["(active)"]
  72. else:
  73. title += _["(passive)"]
  74. return title
  75. def titleConnections(self):
  76. title = _["Connections: %s"] % len(self.main.file_server.connections)
  77. return title
  78. def titleTransfer(self):
  79. title = _["Received: %.2f MB | Sent: %.2f MB"] % (
  80. float(self.main.file_server.bytes_recv) / 1024 / 1024,
  81. float(self.main.file_server.bytes_sent) / 1024 / 1024
  82. )
  83. return title
  84. def titleConsole(self):
  85. translate = _["Show console window"]
  86. if self.console:
  87. return "+" + translate
  88. else:
  89. return translate
  90. def toggleConsole(self):
  91. if self.console:
  92. notificationicon.hideConsole()
  93. self.console = False
  94. else:
  95. notificationicon.showConsole()
  96. self.console = True
  97. def getAutorunPath(self):
  98. return "%s\\zeronet.cmd" % winfolders.get(winfolders.STARTUP)
  99. def formatAutorun(self):
  100. args = sys.argv[:]
  101. if not getattr(sys, 'frozen', False): # Not frozen
  102. args.insert(0, sys.executable)
  103. cwd = os.getcwd()
  104. else:
  105. cwd = os.path.dirname(sys.executable)
  106. ignored_args = [
  107. "--open_browser", "default_browser",
  108. "--dist_type", "bundle_win64"
  109. ]
  110. if sys.platform == 'win32':
  111. args = ['"%s"' % arg for arg in args if arg and arg not in ignored_args]
  112. cmd = " ".join(args)
  113. # Dont open browser on autorun
  114. cmd = cmd.replace("start.py", "zeronet.py").strip()
  115. cmd += ' --open_browser ""'
  116. return "\r\n".join([
  117. '@echo off',
  118. 'chcp 65001 > nul',
  119. 'set PYTHONIOENCODING=utf-8',
  120. 'cd /D \"%s\"' % cwd,
  121. 'start "" %s' % cmd
  122. ])
  123. def isAutorunEnabled(self):
  124. path = self.getAutorunPath()
  125. return os.path.isfile(path) and open(path, "rb").read().decode("utf8") == self.formatAutorun()
  126. def titleAutorun(self):
  127. translate = _["Start ZeroNet when Windows starts"]
  128. if self.isAutorunEnabled():
  129. return "+" + translate
  130. else:
  131. return translate
  132. def toggleAutorun(self):
  133. if self.isAutorunEnabled():
  134. os.unlink(self.getAutorunPath())
  135. else:
  136. open(self.getAutorunPath(), "wb").write(self.formatAutorun().encode("utf8"))