diff --git a/.project b/.project
new file mode 100644
index 0000000..1c6dd94
--- /dev/null
+++ b/.project
@@ -0,0 +1,17 @@
+
+
+ nemo
+
+
+
+
+
+ org.python.pydev.PyDevBuilder
+
+
+
+
+
+ org.python.pydev.pythonNature
+
+
diff --git a/.pydevproject b/.pydevproject
new file mode 100644
index 0000000..037bd25
--- /dev/null
+++ b/.pydevproject
@@ -0,0 +1,8 @@
+
+
+
+/${PROJECT_DIR_NAME}
+
+python 2.7
+Default
+
diff --git a/icon.png b/icon.png
new file mode 100644
index 0000000..676fca1
Binary files /dev/null and b/icon.png differ
diff --git a/nemo.py b/nemo.py
new file mode 100755
index 0000000..390ced1
--- /dev/null
+++ b/nemo.py
@@ -0,0 +1,219 @@
+#!/usr/bin/env python3
+# -*- coding: UTF-8 -*-
+#
+# generated by wxGlade 0.6.8 on Sun Mar 9 14:56:37 2014
+#
+
+application_name = u'NeMo'
+application_version = u'0.1.0'
+
+import json
+import os
+import subprocess
+import wx
+
+# begin wxGlade: dependencies
+import gettext
+# end wxGlade
+
+# begin wxGlade: extracode
+# end wxGlade
+
+
+class NeMo(wx.Frame):
+ def __init__(self, *args, **kwds):
+ # begin wxGlade: NeMo.__init__
+ kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE
+ wx.Frame.__init__(self, *args, **kwds)
+ self.SetSize((900, 480))
+ self.text_ctrl_stdout = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_MULTILINE | wx.TE_READONLY)
+ self.text_ctrl_stderr = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_MULTILINE | wx.TE_READONLY)
+
+ self.__set_properties()
+ self.__do_layout()
+ # end wxGlade
+
+ def __set_properties(self):
+ # begin wxGlade: NeMo.__set_properties
+ self.SetTitle(_("NeMo"))
+ self.text_ctrl_stdout.SetFont(wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
+ self.text_ctrl_stderr.SetForegroundColour(wx.Colour(255, 0, 0))
+ self.text_ctrl_stderr.SetFont(wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
+ # end wxGlade
+ self.SetTitle(_("%s - V%s" % (application_name, application_version)))
+
+ def __do_layout(self):
+ # begin wxGlade: NeMo.__do_layout
+ main_sizer = wx.BoxSizer(wx.HORIZONTAL)
+ output_sizer = wx.BoxSizer(wx.VERTICAL)
+ stderr_sizer = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, _("stderr")), wx.HORIZONTAL)
+ stdout_sizer = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, _("stdout")), wx.HORIZONTAL)
+ action_sizer = wx.BoxSizer(wx.VERTICAL)
+ action_sizer.Add((0, 0), 0, 0, 0)
+ action_sizer.Add((0, 0), 0, 0, 0)
+ main_sizer.Add(action_sizer, 1, wx.EXPAND, 0)
+ stdout_sizer.Add(self.text_ctrl_stdout, 1, wx.EXPAND, 0)
+ output_sizer.Add(stdout_sizer, 1, wx.EXPAND, 0)
+ stderr_sizer.Add(self.text_ctrl_stderr, 1, wx.EXPAND, 0)
+ output_sizer.Add(stderr_sizer, 1, wx.EXPAND, 0)
+ main_sizer.Add(output_sizer, 3, wx.EXPAND, 0)
+ self.SetSizer(main_sizer)
+ self.Layout()
+ self.Centre()
+ # end wxGlade
+ self.action_sizer = action_sizer
+
+ def AddStaBu(self, stabu):
+ self.action_sizer.Add(stabu, 0, wx.EXPAND, 0)
+ self.Layout()
+# end of class NeMo
+
+
+class StaBu(wx.BoxSizer):
+ SSH_FS = 'ssh'
+ WEB_DAV = 'dav'
+ FTP_FS = 'ftp'
+
+ def __init__(self, wx_frame, stdout, stderr, **kwargs):
+ self.wx_frame = wx_frame
+ self.stdout = stdout
+ self.stderr = stderr
+
+ for key in ['name', 'prot', 'remote_host', 'remote_path', 'local_path', 'user', 'port']:
+ setattr(self, key, kwargs[key])
+ for key, value in [('password', None), ]:
+ setattr(self, key, kwargs.get(key, value))
+
+ wx.BoxSizer.__init__(self, wx.HORIZONTAL)
+ self.button = wx.Button(wx_frame, wx.ID_ANY, _(self.name))
+ self.panel = wx.Panel(wx_frame, wx.ID_ANY)
+ if kwargs.get('hidden', False):
+ self.button.Hide()
+ self.panel.Hide()
+ elif kwargs.get('disabled', False):
+ self.button.Disable()
+ self.Add(self.button, 3, 0, 0)
+ self.Add(self.panel, 1, wx.EXPAND, 0)
+ wx_frame.Bind(wx.EVT_BUTTON, self.mount_pressed, self.button)
+ self.panel.Bind(wx.EVT_LEFT_UP, self.open_pressed)
+ wx_frame.Bind(wx.EVT_IDLE, self.panel_update, None)
+ wx_frame.AddStaBu(self)
+
+ def set_password(self):
+ if self.password == None:
+ box = wx.PasswordEntryDialog(self.wx_frame, 'Please enter password for %(name)s:' % self.__dict__, 'Password')
+ if box.ShowModal() == wx.ID_OK:
+ self.password = box.GetValue()
+ box.Destroy()
+
+ def error_msg(self, msg):
+ self.stderr.write('nemo-file (%s): ' % self.name)
+ self.stderr.write(msg)
+
+ def panel_update(self, event):
+ if self.is_mounted():
+ #self.button_open.SetBackgroundColour('green')
+ self.panel.SetBackgroundColour('green')
+ else:
+ #self.button_open.SetBackgroundColour('red')
+ self.panel.SetBackgroundColour('red')
+ event.Skip()
+
+ def mount_pressed(self, event):
+ if self.is_mounted():
+ self.umount()
+ else:
+ self.mount()
+ event.Skip()
+
+ def open_pressed(self, event):
+ for prog in ['nautilus', 'dolphin', 'nemo', 'thunar']:
+ try:
+ subprocess.Popen([prog, self.local_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ except OSError:
+ pass
+ else:
+ break
+ event.Skip()
+
+ def check_prot(self):
+ test_cmd = self.mount_cmd(True)
+ if test_cmd == None:
+ self.__ok__ = False
+ self.error_msg('Protocol not supported!\n')
+ #TODO: try to execute test_cmd to get info that progs are installed
+
+ def is_mounted(self):
+ p = subprocess.Popen(["mount"], stdout=subprocess.PIPE)
+ out, err = p.communicate()
+ self.stderr.write(err or '')
+ if self.local_path in out.decode('utf-8'):
+ return True
+ else:
+ return False
+
+ def umount(self):
+ self.stdout.write('umounting %s\n' % (self.local_path))
+ p = subprocess.Popen(['fusermount', '-u', self.local_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ out, err = p.communicate()
+ if not self.is_mounted():
+ self.stdout.write('SUCCESS.\n')
+ else:
+ self.stdout.write('FAILED.\n')
+ self.stdout.write(out or '')
+ self.stderr.write(err or '')
+
+ def mount(self):
+ cmd = self.mount_cmd()
+ self.stdout.write('mounting %(name)s to %(local_path)s\n' % self.__dict__)
+ if cmd != None:
+ p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ out, err = p.communicate()
+ out = out.decode('utf-8')
+ err = err.decode('utf-8')
+ if self.password != None:
+ out = out.replace(self.password, u'*****')
+ err = err.replace(self.password, u'*****')
+ if self.is_mounted():
+ self.stdout.write('SUCCESS.\n')
+ else:
+ self.stdout.write('FAILED.\n')
+ self.password = None
+ self.stdout.write(out or '')
+ self.stderr.write(err or '')
+ else:
+ self.stdout.write('FAILED.\n')
+
+ def mount_cmd(self, test_cmd=False):
+ if self.prot == self.SSH_FS:
+ if test_cmd:
+ return ['sshfs', '--version']
+ return ['sshfs', '%(user)s@%(remote_host)s:%(remote_path)s' % self.__dict__, self.local_path]
+ elif self.prot == self.WEB_DAV:
+ if test_cmd:
+ return ['wdfs', '--version']
+ self.set_password()
+ return ['wdfs', '-o', 'accept_sslcert,username=%(user)s,password=%(password)s' % self.__dict__, self.remote_host + self.remote_path, self.local_path]
+ elif self.prot == self.FTP_FS:
+ if test_cmd:
+ return ['curlftpfs', '--version']
+ self.set_password()
+ return ['curlftpfs', 'ftp://%(user)s:%(password)s@%(remote_host)s:%(port)s%(remote_path)s' % self.__dict__, self.local_path]
+ else:
+ return None
+
+
+if __name__ == "__main__":
+ gettext.install("app") # replace with the appropriate catalog name
+ app = wx.App(0)
+ nemo_frame = NeMo(None, wx.ID_ANY, "")
+ #
+
+ with open(os.path.abspath(os.path.join(os.path.expanduser('~'), '.nemo.json')), 'r') as fh:
+ config = json.load(fh)
+ for entry in config:
+ StaBu(nemo_frame, nemo_frame.text_ctrl_stdout, nemo_frame.text_ctrl_stderr, **entry)
+ #
+ app.SetTopWindow(nemo_frame)
+ nemo_frame.Show()
+ app.MainLoop()
diff --git a/nemo.wxg b/nemo.wxg
new file mode 100644
index 0000000..b6e801a
--- /dev/null
+++ b/nemo.wxg
@@ -0,0 +1,83 @@
+
+
+
+
+
+