Merge branch 'master' of git://tinc-vpn.org/tinc into 1.1
[tinc] / gui / tinc-gui
1 #!/usr/bin/python
2
3 import wx
4 import sys
5 import Tinc
6 from wx.lib.mixins.listctrl import ColumnSorterMixin
7 from wx.lib.mixins.listctrl import ListCtrlAutoWidthMixin
8
9 del sys.argv[0]
10 net = None
11 controlcookie = None
12
13 while len(sys.argv) >= 2:
14         if sys.argv[0] in ('-n', '--net'):
15                 net = sys.argv[1]
16         elif sys.argv[0] in ('--controlcookie'):
17                 controlcookie = sys.argv[1]
18         else:
19                 print('Unknown option ' + sys.argv[0])
20                 sys.exit(1)
21
22         del sys.argv[0]
23         del sys.argv[0]
24
25 vpn = Tinc.VPN(net, controlcookie)
26 vpn.connect()
27
28 class SuperListCtrl(wx.ListCtrl, ColumnSorterMixin, ListCtrlAutoWidthMixin):
29     def __init__(self, parent, style):
30         wx.ListCtrl.__init__(self, parent, -1, style=wx.LC_REPORT | wx.LC_HRULES | wx.LC_VRULES)
31         ListCtrlAutoWidthMixin.__init__(self)
32         ColumnSorterMixin.__init__(self, 14)
33
34     def GetListCtrl(self):
35         return self
36
37
38 class SettingsPage(wx.Panel):
39         def OnDebugLevel(self, event):
40                 vpn.debug(self.debug.GetValue())
41
42         def __init__(self, parent, id):
43                 wx.Panel.__init__(self, parent, id)
44                 grid = wx.FlexGridSizer(cols = 2)
45                 grid.AddGrowableCol(0, 1)
46
47                 namelabel = wx.StaticText(self, -1, 'Name:')
48                 self.name = wx.TextCtrl(self, -1, vpn.name)
49                 grid.Add(namelabel)
50                 grid.Add(self.name)
51
52                 portlabel = wx.StaticText(self, -1, 'Port:')
53                 self.port = wx.TextCtrl(self, -1, vpn.port)
54                 grid.Add(portlabel)
55                 grid.Add(self.port)
56
57                 debuglabel = wx.StaticText(self, -1, 'Debug level:')
58                 self.debug = wx.SpinCtrl(self, min = 0, max = 5, initial = vpn.debug())
59                 self.debug.Bind(wx.EVT_SPINCTRL, self.OnDebugLevel)
60                 grid.Add(debuglabel)
61                 grid.Add(self.debug)
62
63                 modelabel = wx.StaticText(self, -1, 'Mode:')
64                 self.mode = wx.ComboBox(self, -1, style = wx.CB_READONLY, value = 'Router', choices = ['Router', 'Switch', 'Hub'])
65                 grid.Add(modelabel)
66                 grid.Add(self.mode)
67
68                 self.SetSizer(grid)
69
70 class ConnectionsPage(wx.Panel):
71         def __init__(self, parent, id):
72                 wx.Panel.__init__(self, parent, id)
73                 self.list = wx.ListCtrl(self, id, style=wx.LC_REPORT | wx.LC_HRULES | wx.LC_VRULES)
74                 self.list.InsertColumn(0, 'Name')
75                 self.list.InsertColumn(1, 'Address')
76                 self.list.InsertColumn(2, 'Port')
77                 self.list.InsertColumn(3, 'Options')
78                 self.list.InsertColumn(4, 'Weight')
79
80                 hbox = wx.BoxSizer(wx.HORIZONTAL)
81                 hbox.Add(self.list, 1, wx.EXPAND)
82                 self.SetSizer(hbox)
83                 self.refresh()
84
85         class ContextMenu(wx.Menu):
86                 def __init__(self, item):
87                         wx.Menu.__init__(self)
88
89                         self.item = item
90
91                         disconnect = wx.MenuItem(self, -1, 'Disconnect')
92                         self.AppendItem(disconnect)
93                         self.Bind(wx.EVT_MENU, self.OnDisconnect, id=disconnect.GetId())
94
95                 def OnDisconnect(self, event):
96                         print('Disconnecting ' + self.item[0])
97                         vpn.disconnect(self.item[0])
98
99         def OnContext(self, event):
100                 print('Context menu!')
101                 i = event.GetIndex()
102                 print(i)
103                 self.PopupMenu(self.ContextMenu(self.list.itemDataMap[event.GetIndex()]), event.GetPosition())
104
105         def refresh(self):
106                 self.list.itemDataMap = {}
107                 i = 0
108
109                 for key, connection in vpn.connections.items():
110                         if self.list.GetItemCount() <= i:
111                                 self.list.InsertStringItem(i, connection.name)
112                         else:
113                                 self.list.SetStringItem(i, 0, connection.name)
114                         self.list.SetStringItem(i, 1, connection.address)
115                         self.list.SetStringItem(i, 2, connection.port)
116                         self.list.SetStringItem(i, 3, str(connection.options))
117                         self.list.SetStringItem(i, 4, str(connection.weight))
118                         self.list.itemDataMap[i] = (connection.name, connection.address, connection.port, connection.options, connection.weight)
119                         self.list.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.OnContext)
120                         i += 1
121
122                 while self.list.GetItemCount() > i:
123                         self.list.DeleteItem(self.list.GetItemCount() - 1)
124
125
126 class NodesPage(wx.Panel):
127         def __init__(self, parent, id):
128                 wx.Panel.__init__(self, parent, id)
129                 self.list = SuperListCtrl(self, id)
130                 self.list.InsertColumn( 0, 'Name')
131                 self.list.InsertColumn( 1, 'Address')
132                 self.list.InsertColumn( 2, 'Port')
133                 self.list.InsertColumn( 3, 'Cipher')
134                 self.list.InsertColumn( 4, 'Digest')
135                 self.list.InsertColumn( 5, 'MACLength')
136                 self.list.InsertColumn( 6, 'Compression')
137                 self.list.InsertColumn( 7, 'Options')
138                 self.list.InsertColumn( 8, 'Status')
139                 self.list.InsertColumn( 9, 'Nexthop')
140                 self.list.InsertColumn(10, 'Via')
141                 self.list.InsertColumn(11, 'Distance')
142                 self.list.InsertColumn(12, 'PMTU')
143                 self.list.InsertColumn(13, 'Min MTU')
144                 self.list.InsertColumn(14, 'Max MTU')
145
146                 hbox = wx.BoxSizer(wx.HORIZONTAL)
147                 hbox.Add(self.list, 1, wx.EXPAND)
148                 self.SetSizer(hbox)
149                 self.refresh()
150
151         def refresh(self):
152                 self.list.itemDataMap = {}
153                 i = 0
154
155                 for key, node in vpn.nodes.items():
156                         if self.list.GetItemCount() <= i:
157                                 self.list.InsertStringItem(i, node.name)
158                         else:
159                                 self.list.SetStringItem(i,  0, node.name)
160                         self.list.SetStringItem(i,  1, node.address)
161                         self.list.SetStringItem(i,  2, node.port)
162                         self.list.SetStringItem(i,  3, str(node.cipher))
163                         self.list.SetStringItem(i,  4, str(node.digest))
164                         self.list.SetStringItem(i,  5, str(node.maclength))
165                         self.list.SetStringItem(i,  6, str(node.compression))
166                         self.list.SetStringItem(i,  7, str(node.options))
167                         self.list.SetStringItem(i,  8, str(node.status))
168                         self.list.SetStringItem(i,  9, node.nexthop)
169                         self.list.SetStringItem(i, 10, node.via)
170                         self.list.SetStringItem(i, 11, str(node.distance))
171                         self.list.SetStringItem(i, 12, str(node.pmtu))
172                         self.list.SetStringItem(i, 13, str(node.minmtu))
173                         self.list.SetStringItem(i, 14, str(node.maxmtu))
174                         self.list.itemDataMap[i] = (node.name, node.address, node.port, node.cipher, node.digest, node.maclength, node.compression, node.options, node.status, node.nexthop, node.via, node.distance, node.pmtu, node.minmtu, node.maxmtu)
175                         self.list.SetItemData(i, i)
176                         i += 1
177
178                 while self.list.GetItemCount() > i:
179                         self.list.DeleteItem(self.list.GetItemCount() - 1)
180
181 class EdgesPage(wx.Panel):
182         def __init__(self, parent, id):
183                 wx.Panel.__init__(self, parent, id)
184                 self.list = wx.ListCtrl(self, id, style=wx.LC_REPORT | wx.LC_HRULES | wx.LC_VRULES)
185                 self.list.InsertColumn(0, 'From')
186                 self.list.InsertColumn(1, 'To')
187                 self.list.InsertColumn(2, 'Address')
188                 self.list.InsertColumn(3, 'Port')
189                 self.list.InsertColumn(4, 'Options')
190                 self.list.InsertColumn(5, 'Weight')
191
192                 hbox = wx.BoxSizer(wx.HORIZONTAL)
193                 hbox.Add(self.list, 1, wx.EXPAND)
194                 self.SetSizer(hbox)
195                 self.refresh()
196
197         def refresh(self):
198                 self.list.itemDataMap = {}
199                 i = 0
200
201                 for key, edge in vpn.edges.items():
202                         if self.list.GetItemCount() <= i:
203                                 self.list.InsertStringItem(i, edge.fr)
204                         else:
205                                 self.list.SetStringItem(i, 0, edge.fr)
206                         self.list.SetStringItem(i, 1, edge.to)
207                         self.list.SetStringItem(i, 2, edge.address)
208                         self.list.SetStringItem(i, 3, edge.port)
209                         self.list.SetStringItem(i, 4, str(edge.options))
210                         self.list.SetStringItem(i, 5, str(edge.weight))
211                         self.list.itemDataMap[i] = (edge.fr, edge.to, edge.address, edge.port, edge.options, edge.weight)
212                         i += 1
213
214                 while self.list.GetItemCount() > i:
215                         self.list.DeleteItem(self.list.GetItemCount() - 1)
216
217 class SubnetsPage(wx.Panel):
218         def __init__(self, parent, id):
219                 wx.Panel.__init__(self, parent, id)
220                 self.list = SuperListCtrl(self, id)
221                 self.list.InsertColumn(0, 'Subnet', wx.LIST_FORMAT_RIGHT)
222                 self.list.InsertColumn(1, 'Weight', wx.LIST_FORMAT_RIGHT)
223                 self.list.InsertColumn(2, 'Owner')
224                 hbox = wx.BoxSizer(wx.HORIZONTAL)
225                 hbox.Add(self.list, 1, wx.EXPAND)
226                 self.SetSizer(hbox)
227                 self.refresh()
228
229         def refresh(self):
230                 self.list.itemDataMap = {}
231                 i = 0
232
233                 for key, subnet in vpn.subnets.items():
234                         if self.list.GetItemCount() <= i:
235                                 self.list.InsertStringItem(i, subnet.address + '/' + subnet.prefixlen)
236                         else:
237                                 self.list.SetStringItem(i, 0, subnet.address + '/' + subnet.prefixlen)
238                         self.list.SetStringItem(i, 1, subnet.weight)
239                         self.list.SetStringItem(i, 2, subnet.owner)
240                         self.list.itemDataMap[i] = (subnet.address + '/' + subnet.prefixlen, subnet.weight, subnet.owner)
241                         i = i + 1
242
243                 while self.list.GetItemCount() > i:
244                         self.list.DeleteItem(self.list.GetItemCount() - 1)
245
246 class StatusPage(wx.Panel):
247         def __init__(self, parent, id):
248                 wx.Panel.__init__(self, parent, id)
249
250 class GraphPage(wx.Window):
251         def __init__(self, parent, id):
252                 wx.Window.__init__(self, parent, id)
253
254 class NetPage(wx.Notebook):
255         def __init__(self, parent, id):
256                 wx.Notebook.__init__(self, parent)
257                 self.settings = SettingsPage(self, id)
258                 self.connections = ConnectionsPage(self, id)
259                 self.nodes = NodesPage(self, id)
260                 self.edges = EdgesPage(self, id)
261                 self.subnets = SubnetsPage(self, id)
262                 self.graph = GraphPage(self, id)
263                 self.status = StatusPage(self, id)
264
265                 self.AddPage(self.settings, 'Settings')
266                 #self.AddPage(self.status, 'Status')
267                 self.AddPage(self.connections, 'Connections')
268                 self.AddPage(self.nodes, 'Nodes')
269                 self.AddPage(self.edges, 'Edges')
270                 self.AddPage(self.subnets, 'Subnets')
271                 #self.AddPage(self.graph, 'Graph')
272                 
273
274 class MainWindow(wx.Frame):
275         def OnQuit(self, event):
276                 self.Close(True)
277
278         def OnTimer(self, event):
279                 vpn.refresh()
280                 self.np.nodes.refresh()
281                 self.np.subnets.refresh()
282                 self.np.edges.refresh()
283                 self.np.connections.refresh()
284
285         def __init__(self, parent, id, title):
286                 wx.Frame.__init__(self, parent, id, title)
287
288                 menubar = wx.MenuBar()
289                 file = wx.Menu()
290                 file.Append(1, '&Quit\tCtrl-X', 'Quit tinc GUI')
291                 menubar.Append(file, '&File')
292
293                 #nb = wx.Notebook(self, -1)
294                 #nb.SetPadding((0, 0))
295                 self.np = NetPage(self, -1)
296                 #nb.AddPage(np, 'VPN')
297                 
298                 self.timer = wx.Timer(self, -1)
299                 self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)
300                 self.timer.Start(1000)
301                 self.Bind(wx.EVT_MENU, self.OnQuit, id=1)
302                 self.SetMenuBar(menubar)
303                 self.Show()
304
305 app = wx.App()
306 mw = MainWindow(None, -1, 'Tinc GUI')
307
308 #def OnTaskBarIcon(event):
309 #       mw.Raise()
310 #
311 #icon = wx.Icon("tincgui.ico", wx.BITMAP_TYPE_PNG)
312 #taskbaricon = wx.TaskBarIcon()
313 #taskbaricon.SetIcon(icon, 'Tinc GUI')
314 #wx.EVT_TASKBAR_RIGHT_UP(taskbaricon, OnTaskBarIcon)
315
316 app.MainLoop()
317 vpn.close()