Tools for GNS3 GUI
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

0001-Initial-implementation-of-a-tool-system.patch 7.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. From d63b9271453f4f5a6d22bec9cc422ddbcbf6828e Mon Sep 17 00:00:00 2001
  2. From: Bernhard Ehlers <be@bernhard-ehlers.de>
  3. Date: Thu, 28 Dec 2017 15:17:11 +0100
  4. Subject: [PATCH 1/7] Initial implementation of a tool system
  5. ---
  6. gns3/graphics_view.py | 20 +++++++++++
  7. gns3/main_window.py | 21 ++++++++++++
  8. gns3/tool.py | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++
  9. 3 files changed, 134 insertions(+)
  10. create mode 100644 gns3/tool.py
  11. diff --git a/gns3/graphics_view.py b/gns3/graphics_view.py
  12. index d965a177..9d589949 100644
  13. --- a/gns3/graphics_view.py
  14. +++ b/gns3/graphics_view.py
  15. @@ -819,6 +819,17 @@ class GraphicsView(QtWidgets.QGraphicsView):
  16. show_in_file_manager_action.triggered.connect(self.showInFileManagerSlot)
  17. menu.addAction(show_in_file_manager_action)
  18. + tool_list = self._main_window.tools.contextTools(items)
  19. + if tool_list:
  20. + tool_menu_action = QtWidgets.QMenu("Tools", menu)
  21. + tool_menu_action.setIcon(QtGui.QIcon(':/icons/applications.svg'))
  22. + menu.addAction(tool_menu_action.menuAction())
  23. + for tool in tool_list:
  24. + tool_action = QtWidgets.QAction(tool.name(), tool_menu_action)
  25. + tool_action.setData(tool)
  26. + tool_action.triggered.connect(self.startToolSlot)
  27. + tool_menu_action.addAction(tool_action)
  28. +
  29. if sys.platform.startswith("win") and True in list(map(lambda item: isinstance(item, NodeItem) and hasattr(item.node(), "bringToFront"), items)):
  30. # Action: bring console or window to front (Windows only)
  31. bring_to_front_action = QtWidgets.QAction("Bring to front", menu)
  32. @@ -1625,3 +1636,12 @@ class GraphicsView(QtWidgets.QGraphicsView):
  33. self._main_window.uiDeviceMenu.setEnabled(True)
  34. else:
  35. self._main_window.uiDeviceMenu.setEnabled(False)
  36. +
  37. + def startToolSlot(self):
  38. + """
  39. + Slot called to start tool from the contextual menu.
  40. + """
  41. +
  42. + action = self.sender()
  43. + if action and action.data():
  44. + action.data().run(self._topology.project(), self.scene().selectedItems())
  45. diff --git a/gns3/main_window.py b/gns3/main_window.py
  46. index 0f87bcc2..46cecf59 100644
  47. --- a/gns3/main_window.py
  48. +++ b/gns3/main_window.py
  49. @@ -57,6 +57,7 @@ from .status_bar import StatusBarHandler
  50. from .registry.appliance import ApplianceError
  51. from .template_manager import TemplateManager
  52. from .appliance_manager import ApplianceManager
  53. +from .tool import ToolList
  54. log = logging.getLogger(__name__)
  55. @@ -109,6 +110,7 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
  56. self._project_dialog = None
  57. self.recent_file_actions = []
  58. self.recent_project_actions = []
  59. + self.tools = ToolList()
  60. self._start_time = time.time()
  61. local_config = LocalConfig.instance()
  62. #local_config.config_changed_signal.connect(self._localConfigChangedSlot)
  63. @@ -166,6 +168,16 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
  64. self.recent_project_actions_separator.setVisible(False)
  65. self.uiFileMenu.addActions(self.recent_project_actions)
  66. + # add tools to tools menu
  67. + tool_list = self.tools.menuTools()
  68. + if tool_list:
  69. + self.uiToolsMenu.addSeparator()
  70. + for tool in tool_list:
  71. + action = QtWidgets.QAction(tool.name(), self.uiToolsMenu)
  72. + action.setData(tool)
  73. + action.triggered.connect(self.startToolSlot)
  74. + self.uiToolsMenu.addAction(action)
  75. +
  76. # set the window icon
  77. self.setWindowIcon(QtGui.QIcon(":/images/gns3.ico"))
  78. @@ -472,6 +484,15 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
  79. (project_id, ) = action.data()
  80. Topology.instance().createLoadProject({"project_id": project_id})
  81. + def startToolSlot(self):
  82. + """
  83. + Slot called to start tool from the tools menu.
  84. + """
  85. +
  86. + action = self.sender()
  87. + if action and action.data():
  88. + action.data().run(Topology.instance().project(), self.uiGraphicsView.scene().selectedItems())
  89. +
  90. def loadPath(self, path):
  91. """Open a file and close the previous project"""
  92. diff --git a/gns3/tool.py b/gns3/tool.py
  93. new file mode 100644
  94. index 00000000..088867c2
  95. --- /dev/null
  96. +++ b/gns3/tool.py
  97. @@ -0,0 +1,93 @@
  98. +# -*- coding: utf-8 -*-
  99. +#
  100. +# Copyright (C) 2017 Bernhard Ehlers
  101. +#
  102. +# This program is free software: you can redistribute it and/or modify
  103. +# it under the terms of the GNU General Public License as published by
  104. +# the Free Software Foundation, either version 3 of the License, or
  105. +# (at your option) any later version.
  106. +#
  107. +# This program is distributed in the hope that it will be useful,
  108. +# but WITHOUT ANY WARRANTY; without even the implied warranty of
  109. +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  110. +# GNU General Public License for more details.
  111. +#
  112. +# You should have received a copy of the GNU General Public License
  113. +# along with this program. If not, see <http://www.gnu.org/licenses/>.
  114. +"""
  115. +Manage Tools
  116. +"""
  117. +
  118. +import os
  119. +import logging
  120. +import subprocess
  121. +
  122. +from .version import __version__
  123. +from .items.node_item import NodeItem
  124. +from .items.link_item import LinkItem
  125. +from .items.text_item import TextItem
  126. +from .items.drawing_item import DrawingItem
  127. +
  128. +log = logging.getLogger(__name__)
  129. +
  130. +
  131. +class Tool:
  132. + """ tool class """
  133. +
  134. + def __init__(self, name, path):
  135. + self._name = name
  136. + self._path = path
  137. +
  138. + def name(self):
  139. + """ tool name """
  140. + return self._name
  141. +
  142. + def run(self, project, item_list):
  143. + """ run tool """
  144. +
  145. + if not project:
  146. + return
  147. + args = [self._path, __version__, project.id()]
  148. + for item in item_list:
  149. + if isinstance(item, NodeItem):
  150. + args.append("nodes/" + item.node().node_id())
  151. + elif isinstance(item, LinkItem):
  152. + args.append("links/" + item.link().link_id())
  153. + elif isinstance(item, TextItem):
  154. + args.append("text_drawings/" + item.drawing_id())
  155. + elif isinstance(item, DrawingItem):
  156. + args.append("drawings/" + item.drawing_id())
  157. +
  158. + try:
  159. + subprocess.Popen(args, env=os.environ)
  160. + except (OSError, ValueError, subprocess.SubprocessError) as err:
  161. + log.error('could not start tool %s: %s', self._name, err)
  162. +
  163. +
  164. +class ToolList:
  165. + """ tool list """
  166. +
  167. + def __init__(self):
  168. + tool_path = os.path.join(os.path.expanduser('~'), 'GNS3', 'tools')
  169. + tools = []
  170. + try:
  171. + for entry in os.listdir(tool_path):
  172. + path = os.path.join(tool_path, entry)
  173. + if not path.lower().endswith(".json") and \
  174. + os.path.isfile(path) and os.access(path, os.X_OK):
  175. + name = os.path.splitext(entry)[0]
  176. + tools.append(Tool(name, path))
  177. + except OSError:
  178. + pass
  179. + tools.sort(key=lambda k: k.name().lower())
  180. + self._tools = tools
  181. +
  182. + def contextTools(self, items):
  183. + """ return context tool list """
  184. + if True in list(map(lambda item: isinstance(item, (DrawingItem, NodeItem)), items)):
  185. + return self._tools
  186. + return []
  187. +
  188. + def menuTools(self):
  189. + """ return menu tool list """
  190. + return self._tools
  191. --
  192. 2.15.1 (Apple Git-101)