Przeglądaj źródła

Initial nemo application

master
Dirk Alders 4 lat temu
rodzic
commit
f9797139b9
5 zmienionych plików z 327 dodań i 0 usunięć
  1. 17
    0
      .project
  2. 8
    0
      .pydevproject
  3. BIN
      icon.png
  4. 219
    0
      nemo.py
  5. 83
    0
      nemo.wxg

+ 17
- 0
.project Wyświetl plik

@@ -0,0 +1,17 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<projectDescription>
3
+	<name>nemo</name>
4
+	<comment></comment>
5
+	<projects>
6
+	</projects>
7
+	<buildSpec>
8
+		<buildCommand>
9
+			<name>org.python.pydev.PyDevBuilder</name>
10
+			<arguments>
11
+			</arguments>
12
+		</buildCommand>
13
+	</buildSpec>
14
+	<natures>
15
+		<nature>org.python.pydev.pythonNature</nature>
16
+	</natures>
17
+</projectDescription>

+ 8
- 0
.pydevproject Wyświetl plik

@@ -0,0 +1,8 @@
1
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
+<?eclipse-pydev version="1.0"?><pydev_project>
3
+<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
4
+<path>/${PROJECT_DIR_NAME}</path>
5
+</pydev_pathproperty>
6
+<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property>
7
+<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
8
+</pydev_project>

BIN
icon.png Wyświetl plik


+ 219
- 0
nemo.py Wyświetl plik

@@ -0,0 +1,219 @@
1
+#!/usr/bin/env python3
2
+# -*- coding: UTF-8 -*-
3
+#
4
+# generated by wxGlade 0.6.8 on Sun Mar  9 14:56:37 2014
5
+#
6
+
7
+application_name = u'NeMo'
8
+application_version = u'0.1.0'
9
+
10
+import json
11
+import os
12
+import subprocess
13
+import wx
14
+
15
+# begin wxGlade: dependencies
16
+import gettext
17
+# end wxGlade
18
+
19
+# begin wxGlade: extracode
20
+# end wxGlade
21
+
22
+
23
+class NeMo(wx.Frame):
24
+    def __init__(self, *args, **kwds):
25
+        # begin wxGlade: NeMo.__init__
26
+        kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE
27
+        wx.Frame.__init__(self, *args, **kwds)
28
+        self.SetSize((900, 480))
29
+        self.text_ctrl_stdout = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_MULTILINE | wx.TE_READONLY)
30
+        self.text_ctrl_stderr = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_MULTILINE | wx.TE_READONLY)
31
+
32
+        self.__set_properties()
33
+        self.__do_layout()
34
+        # end wxGlade
35
+
36
+    def __set_properties(self):
37
+        # begin wxGlade: NeMo.__set_properties
38
+        self.SetTitle(_("NeMo"))
39
+        self.text_ctrl_stdout.SetFont(wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
40
+        self.text_ctrl_stderr.SetForegroundColour(wx.Colour(255, 0, 0))
41
+        self.text_ctrl_stderr.SetFont(wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
42
+        # end wxGlade
43
+        self.SetTitle(_("%s - V%s" % (application_name, application_version)))
44
+
45
+    def __do_layout(self):
46
+        # begin wxGlade: NeMo.__do_layout
47
+        main_sizer = wx.BoxSizer(wx.HORIZONTAL)
48
+        output_sizer = wx.BoxSizer(wx.VERTICAL)
49
+        stderr_sizer = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, _("stderr")), wx.HORIZONTAL)
50
+        stdout_sizer = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, _("stdout")), wx.HORIZONTAL)
51
+        action_sizer = wx.BoxSizer(wx.VERTICAL)
52
+        action_sizer.Add((0, 0), 0, 0, 0)
53
+        action_sizer.Add((0, 0), 0, 0, 0)
54
+        main_sizer.Add(action_sizer, 1, wx.EXPAND, 0)
55
+        stdout_sizer.Add(self.text_ctrl_stdout, 1, wx.EXPAND, 0)
56
+        output_sizer.Add(stdout_sizer, 1, wx.EXPAND, 0)
57
+        stderr_sizer.Add(self.text_ctrl_stderr, 1, wx.EXPAND, 0)
58
+        output_sizer.Add(stderr_sizer, 1, wx.EXPAND, 0)
59
+        main_sizer.Add(output_sizer, 3, wx.EXPAND, 0)
60
+        self.SetSizer(main_sizer)
61
+        self.Layout()
62
+        self.Centre()
63
+        # end wxGlade
64
+        self.action_sizer = action_sizer
65
+
66
+    def AddStaBu(self, stabu):
67
+        self.action_sizer.Add(stabu, 0, wx.EXPAND, 0)
68
+        self.Layout()
69
+# end of class NeMo
70
+
71
+
72
+class StaBu(wx.BoxSizer):
73
+    SSH_FS = 'ssh'
74
+    WEB_DAV = 'dav'
75
+    FTP_FS = 'ftp'
76
+
77
+    def __init__(self, wx_frame, stdout, stderr, **kwargs):
78
+        self.wx_frame = wx_frame
79
+        self.stdout = stdout
80
+        self.stderr = stderr
81
+
82
+        for key in ['name', 'prot', 'remote_host', 'remote_path', 'local_path', 'user', 'port']:
83
+            setattr(self, key, kwargs[key])
84
+        for key, value in [('password', None), ]:
85
+            setattr(self, key, kwargs.get(key, value))
86
+
87
+        wx.BoxSizer.__init__(self, wx.HORIZONTAL)
88
+        self.button = wx.Button(wx_frame, wx.ID_ANY, _(self.name))
89
+        self.panel = wx.Panel(wx_frame, wx.ID_ANY)
90
+        if kwargs.get('hidden', False):
91
+            self.button.Hide()
92
+            self.panel.Hide()
93
+        elif kwargs.get('disabled', False):
94
+            self.button.Disable()
95
+        self.Add(self.button, 3, 0, 0)
96
+        self.Add(self.panel, 1, wx.EXPAND, 0)
97
+        wx_frame.Bind(wx.EVT_BUTTON, self.mount_pressed, self.button)
98
+        self.panel.Bind(wx.EVT_LEFT_UP, self.open_pressed)
99
+        wx_frame.Bind(wx.EVT_IDLE, self.panel_update, None)
100
+        wx_frame.AddStaBu(self)
101
+
102
+    def set_password(self):
103
+        if self.password == None:
104
+            box = wx.PasswordEntryDialog(self.wx_frame, 'Please enter password for %(name)s:' % self.__dict__, 'Password')
105
+            if box.ShowModal() == wx.ID_OK:
106
+                self.password = box.GetValue()
107
+            box.Destroy()
108
+
109
+    def error_msg(self, msg):
110
+        self.stderr.write('nemo-file (%s): ' % self.name)
111
+        self.stderr.write(msg)
112
+
113
+    def panel_update(self, event):
114
+        if self.is_mounted():
115
+            #self.button_open.SetBackgroundColour('green')
116
+            self.panel.SetBackgroundColour('green')
117
+        else:
118
+            #self.button_open.SetBackgroundColour('red')
119
+            self.panel.SetBackgroundColour('red')
120
+        event.Skip()
121
+
122
+    def mount_pressed(self, event):
123
+        if self.is_mounted():
124
+            self.umount()
125
+        else:
126
+            self.mount()
127
+        event.Skip()
128
+
129
+    def open_pressed(self, event):
130
+        for prog in ['nautilus', 'dolphin', 'nemo', 'thunar']:
131
+            try:
132
+                subprocess.Popen([prog, self.local_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
133
+            except OSError:
134
+                pass
135
+            else:
136
+                break
137
+        event.Skip()
138
+
139
+    def check_prot(self):
140
+        test_cmd = self.mount_cmd(True)
141
+        if test_cmd == None:
142
+            self.__ok__ = False
143
+            self.error_msg('Protocol not supported!\n')
144
+        #TODO: try to execute test_cmd to get info that progs are installed
145
+
146
+    def is_mounted(self):
147
+        p = subprocess.Popen(["mount"], stdout=subprocess.PIPE)
148
+        out, err = p.communicate()
149
+        self.stderr.write(err or '')
150
+        if self.local_path in out.decode('utf-8'):
151
+            return True
152
+        else:
153
+            return False
154
+
155
+    def umount(self):
156
+        self.stdout.write('umounting %s\n' % (self.local_path))
157
+        p = subprocess.Popen(['fusermount', '-u', self.local_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
158
+        out, err = p.communicate()
159
+        if not self.is_mounted():
160
+            self.stdout.write('SUCCESS.\n')
161
+        else:
162
+            self.stdout.write('FAILED.\n')
163
+        self.stdout.write(out or '')
164
+        self.stderr.write(err or '')
165
+
166
+    def mount(self):
167
+        cmd = self.mount_cmd()
168
+        self.stdout.write('mounting %(name)s to %(local_path)s\n' % self.__dict__)
169
+        if cmd != None:
170
+            p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
171
+            out, err = p.communicate()
172
+            out = out.decode('utf-8')
173
+            err = err.decode('utf-8')
174
+            if self.password != None:
175
+                out = out.replace(self.password, u'*****')
176
+                err = err.replace(self.password, u'*****')
177
+            if self.is_mounted():
178
+                self.stdout.write('SUCCESS.\n')
179
+            else:
180
+                self.stdout.write('FAILED.\n')
181
+                self.password = None
182
+            self.stdout.write(out or '')
183
+            self.stderr.write(err or '')
184
+        else:
185
+            self.stdout.write('FAILED.\n')
186
+
187
+    def mount_cmd(self, test_cmd=False):
188
+        if self.prot == self.SSH_FS:
189
+            if test_cmd:
190
+                return ['sshfs', '--version']
191
+            return ['sshfs', '%(user)s@%(remote_host)s:%(remote_path)s' % self.__dict__, self.local_path]
192
+        elif self.prot == self.WEB_DAV:
193
+            if test_cmd:
194
+                return ['wdfs', '--version']
195
+            self.set_password()
196
+            return ['wdfs', '-o', 'accept_sslcert,username=%(user)s,password=%(password)s' % self.__dict__, self.remote_host + self.remote_path, self.local_path]
197
+        elif self.prot == self.FTP_FS:
198
+            if test_cmd:
199
+                return ['curlftpfs', '--version']
200
+            self.set_password()
201
+            return ['curlftpfs', 'ftp://%(user)s:%(password)s@%(remote_host)s:%(port)s%(remote_path)s' % self.__dict__, self.local_path]
202
+        else:
203
+            return None
204
+
205
+
206
+if __name__ == "__main__":
207
+    gettext.install("app")  # replace with the appropriate catalog name
208
+    app = wx.App(0)
209
+    nemo_frame = NeMo(None, wx.ID_ANY, "")
210
+    #
211
+    
212
+    with open(os.path.abspath(os.path.join(os.path.expanduser('~'), '.nemo.json')), 'r') as fh:
213
+        config = json.load(fh)
214
+    for entry in config:
215
+        StaBu(nemo_frame, nemo_frame.text_ctrl_stdout, nemo_frame.text_ctrl_stderr, **entry)
216
+    #
217
+    app.SetTopWindow(nemo_frame)
218
+    nemo_frame.Show()
219
+    app.MainLoop()

+ 83
- 0
nemo.wxg Wyświetl plik

@@ -0,0 +1,83 @@
1
+<?xml version="1.0"?>
2
+<!-- generated by wxGlade 0.6.8 on Tue Mar 11 21:21:15 2014 -->
3
+
4
+<application path="nemo.py" name="" class="" option="0" language="python" top_window="nemo_frame" encoding="UTF-8" use_gettext="1" overwrite="0" use_new_namespace="1" for_version="2.8" is_template="0" indent_amount="4" indent_symbol="space" source_extension=".cpp" header_extension=".h">
5
+    <object class="NeMo" name="nemo_frame" base="EditFrame">
6
+        <style>wxDEFAULT_FRAME_STYLE</style>
7
+        <title>NeMo</title>
8
+        <centered>1</centered>
9
+        <size>900, 480</size>
10
+        <object class="wxBoxSizer" name="main_sizer" base="EditBoxSizer">
11
+            <orient>wxHORIZONTAL</orient>
12
+            <object class="sizeritem">
13
+                <flag>wxEXPAND</flag>
14
+                <border>0</border>
15
+                <option>1</option>
16
+                <object class="wxBoxSizer" name="action_sizer" base="EditBoxSizer">
17
+                    <orient>wxVERTICAL</orient>
18
+                    <object class="sizerslot" />
19
+                    <object class="sizerslot" />
20
+                </object>
21
+            </object>
22
+            <object class="sizeritem">
23
+                <flag>wxEXPAND</flag>
24
+                <border>0</border>
25
+                <option>3</option>
26
+                <object class="wxBoxSizer" name="output_sizer" base="EditBoxSizer">
27
+                    <orient>wxVERTICAL</orient>
28
+                    <object class="sizeritem">
29
+                        <flag>wxEXPAND</flag>
30
+                        <border>0</border>
31
+                        <option>1</option>
32
+                        <object class="wxStaticBoxSizer" name="stdout_sizer" base="EditStaticBoxSizer">
33
+                            <orient>wxHORIZONTAL</orient>
34
+                            <label>stdout</label>
35
+                            <object class="sizeritem">
36
+                                <flag>wxEXPAND</flag>
37
+                                <border>0</border>
38
+                                <option>1</option>
39
+                                <object class="wxTextCtrl" name="text_ctrl_stdout" base="EditTextCtrl">
40
+                                    <style>wxTE_MULTILINE|wxTE_READONLY</style>
41
+                                    <font>
42
+                                        <size>10</size>
43
+                                        <family>default</family>
44
+                                        <style>normal</style>
45
+                                        <weight>bold</weight>
46
+                                        <underlined>0</underlined>
47
+                                        <face></face>
48
+                                    </font>
49
+                                </object>
50
+                            </object>
51
+                        </object>
52
+                    </object>
53
+                    <object class="sizeritem">
54
+                        <flag>wxEXPAND</flag>
55
+                        <border>0</border>
56
+                        <option>1</option>
57
+                        <object class="wxStaticBoxSizer" name="stderr_sizer" base="EditStaticBoxSizer">
58
+                            <orient>wxHORIZONTAL</orient>
59
+                            <label>stderr</label>
60
+                            <object class="sizeritem">
61
+                                <flag>wxEXPAND</flag>
62
+                                <border>0</border>
63
+                                <option>1</option>
64
+                                <object class="wxTextCtrl" name="text_ctrl_stderr" base="EditTextCtrl">
65
+                                    <foreground>#ff0000</foreground>
66
+                                    <style>wxTE_MULTILINE|wxTE_READONLY</style>
67
+                                    <font>
68
+                                        <size>10</size>
69
+                                        <family>default</family>
70
+                                        <style>normal</style>
71
+                                        <weight>bold</weight>
72
+                                        <underlined>0</underlined>
73
+                                        <face></face>
74
+                                    </font>
75
+                                </object>
76
+                            </object>
77
+                        </object>
78
+                    </object>
79
+                </object>
80
+            </object>
81
+        </object>
82
+    </object>
83
+</application>

Ładowanie…
Anuluj
Zapisz