Entropy/Repository Manager:
- enable basic commands interactivity (half done) testing git-svn-id: http://svn.sabayonlinux.org/projects/entropy/trunk@2473 cd1c1023-2f26-0410-ae45-c471fc1f0318
This commit is contained in:
@@ -21143,10 +21143,11 @@ class SystemManagerExecutorServerRepositoryInterface:
|
||||
|
||||
cmd = ["emerge", "--sync"]
|
||||
try:
|
||||
p = self.subprocess.Popen(cmd, stdout = stdout_err, stderr = stdout_err)
|
||||
p = self.subprocess.Popen(cmd, stdout = stdout_err, stderr = stdout_err, stdin = self._get_stdin(queue_id))
|
||||
self._set_processing_pid(queue_id, p.pid)
|
||||
rc = p.wait()
|
||||
finally:
|
||||
stdout_err.write('\n\n Stdin: %s' % (self._get_stdin(queue_id),))
|
||||
stdout_err.write("\n### Done ###\n")
|
||||
stdout_err.flush()
|
||||
stdout_err.close()
|
||||
@@ -21175,7 +21176,8 @@ class SystemManagerExecutorServerRepositoryInterface:
|
||||
if cflags:
|
||||
cmd += ['export CFLAGS="']+custom_use.strip().split()+['"','&&']
|
||||
cmd += [etpConst['spm']['exec']]+atoms
|
||||
if pretend: cmd.append(etpConst['spm']['pretend_cmd'])
|
||||
if pretend:
|
||||
cmd.append(etpConst['spm']['pretend_cmd'])
|
||||
if verbose:
|
||||
cmd.append(etpConst['spm']['verbose_cmd'])
|
||||
if oneshot:
|
||||
@@ -21193,10 +21195,11 @@ class SystemManagerExecutorServerRepositoryInterface:
|
||||
stdout_err.flush()
|
||||
|
||||
try:
|
||||
p = self.subprocess.Popen(' '.join(cmd), stdout = stdout_err, stderr = stdout_err, shell = True)
|
||||
p = self.subprocess.Popen(' '.join(cmd), stdout = stdout_err, stderr = stdout_err, stdin = self._get_stdin(queue_id), shell = True)
|
||||
self._set_processing_pid(queue_id, p.pid)
|
||||
rc = p.wait()
|
||||
finally:
|
||||
stdout_err.write('\n\n Stdin: %s' % (self._get_stdin(queue_id),))
|
||||
stdout_err.write("\n### Done ###\n")
|
||||
stdout_err.flush()
|
||||
stdout_err.close()
|
||||
@@ -21224,10 +21227,11 @@ class SystemManagerExecutorServerRepositoryInterface:
|
||||
stdout_err.flush()
|
||||
|
||||
try:
|
||||
p = self.subprocess.Popen(' '.join(cmd), stdout = stdout_err, stderr = stdout_err, shell = True)
|
||||
p = self.subprocess.Popen(' '.join(cmd), stdout = stdout_err, stderr = stdout_err, stdin = self._get_stdin(queue_id), shell = True)
|
||||
self._set_processing_pid(queue_id, p.pid)
|
||||
rc = p.wait()
|
||||
finally:
|
||||
stdout_err.write('\n\n Stdin: %s' % (self._get_stdin(queue_id),))
|
||||
stdout_err.write("\n### Done ###\n")
|
||||
stdout_err.flush()
|
||||
stdout_err.close()
|
||||
@@ -21349,10 +21353,11 @@ class SystemManagerExecutorServerRepositoryInterface:
|
||||
stdout_err.flush()
|
||||
|
||||
try:
|
||||
p = self.subprocess.Popen(cmd, stdout = stdout_err, stderr = stdout_err)
|
||||
p = self.subprocess.Popen(cmd, stdout = stdout_err, stderr = stdout_err, stdin = self._get_stdin(queue_id))
|
||||
self._set_processing_pid(queue_id, p.pid)
|
||||
rc = p.wait()
|
||||
finally:
|
||||
stdout_err.write('\n\n Stdin: %s' % (self._get_stdin(queue_id),))
|
||||
stdout_err.write("\n### Done ###\n")
|
||||
stdout_err.flush()
|
||||
stdout_err.close()
|
||||
@@ -21375,10 +21380,11 @@ class SystemManagerExecutorServerRepositoryInterface:
|
||||
stdout_err.flush()
|
||||
|
||||
try:
|
||||
p = self.subprocess.Popen(cmd, stdout = stdout_err, stderr = stdout_err, shell = True)
|
||||
p = self.subprocess.Popen(cmd, stdout = stdout_err, stderr = stdout_err, stdin = self._get_stdin(queue_id), shell = True)
|
||||
self._set_processing_pid(queue_id, p.pid)
|
||||
rc = p.wait()
|
||||
finally:
|
||||
stdout_err.write('Stdin: %s\n' % (self._get_stdin(queue_id),))
|
||||
stdout_err.write("\n### Done ###\n")
|
||||
stdout_err.flush()
|
||||
stdout_err.close()
|
||||
@@ -21410,6 +21416,7 @@ class SystemManagerExecutorServerRepositoryInterface:
|
||||
do_copy = do_copy
|
||||
)
|
||||
finally:
|
||||
stdout_err.write('\n\n Stdin: %s' % (self._get_stdin(queue_id),))
|
||||
stdout_err.write("\n### Done ###\n")
|
||||
self.SystemManagerExecutor.SystemInterface.Entropy.updateProgress = old_updprogress
|
||||
stdout_err.flush()
|
||||
@@ -21462,6 +21469,7 @@ class SystemManagerExecutorServerRepositoryInterface:
|
||||
dbconn.closeDB()
|
||||
|
||||
finally:
|
||||
stdout_err.write('\n\n Stdin: %s' % (self._get_stdin(queue_id),))
|
||||
stdout_err.write("\n### Done ###\n")
|
||||
self.SystemManagerExecutor.SystemInterface.Entropy.updateProgress = old_updprogress
|
||||
stdout_err.flush()
|
||||
@@ -21567,6 +21575,7 @@ class SystemManagerExecutorServerRepositoryInterface:
|
||||
self.entropyTools.printTraceback(f = stdout_err)
|
||||
return False,str(e)
|
||||
finally:
|
||||
stdout_err.write('\n\n Stdin: %s' % (self._get_stdin(queue_id),))
|
||||
stdout_err.write("\n### Done ###\n")
|
||||
Entropy.updateProgress = old_updprogress
|
||||
Entropy.ClientService.updateProgress = old_client_updprogress
|
||||
@@ -21598,6 +21607,7 @@ class SystemManagerExecutorServerRepositoryInterface:
|
||||
self.entropyTools.printTraceback(f = stdout_err)
|
||||
return False,str(e)
|
||||
finally:
|
||||
stdout_err.write('\n\n Stdin: %s' % (self._get_stdin(queue_id),))
|
||||
stdout_err.write("\n### Done ###\n")
|
||||
Entropy.updateProgress = old_updprogress
|
||||
Entropy.ClientService.updateProgress = old_client_updprogress
|
||||
@@ -21629,6 +21639,7 @@ class SystemManagerExecutorServerRepositoryInterface:
|
||||
self.entropyTools.printTraceback(f = stdout_err)
|
||||
return False,str(e)
|
||||
finally:
|
||||
stdout_err.write('\n\n Stdin: %s' % (self._get_stdin(queue_id),))
|
||||
stdout_err.write("\n### Done ###\n")
|
||||
Entropy.updateProgress = old_updprogress
|
||||
Entropy.ClientService.updateProgress = old_client_updprogress
|
||||
@@ -21664,6 +21675,7 @@ class SystemManagerExecutorServerRepositoryInterface:
|
||||
else:
|
||||
data = Entropy.verify_remote_packages([], ask = False, repo = repoid)
|
||||
finally:
|
||||
stdout_err.write('\n\n Stdin: %s' % (self._get_stdin(queue_id),))
|
||||
stdout_err.write("\n### Done ###\n")
|
||||
Entropy.updateProgress = old_updprogress
|
||||
Entropy.ClientService.updateProgress = old_client_updprogress
|
||||
@@ -21693,6 +21705,7 @@ class SystemManagerExecutorServerRepositoryInterface:
|
||||
dbconn = Entropy.openServerDatabase(repo = repoid, do_cache = False, ask_treeupdates = False, read_only = True)
|
||||
dbconn.closeDB()
|
||||
finally:
|
||||
stdout_err.write('\n\n Stdin: %s' % (self._get_stdin(queue_id),))
|
||||
stdout_err.write("\n### Done ###\n")
|
||||
Entropy.updateProgress = old_updprogress
|
||||
Entropy.ClientService.updateProgress = old_client_updprogress
|
||||
@@ -21775,6 +21788,7 @@ class SystemManagerExecutorServerRepositoryInterface:
|
||||
|
||||
finally:
|
||||
|
||||
stdout_err.write('\n\n Stdin: %s' % (self._get_stdin(queue_id),))
|
||||
stdout_err.write("\n### Done ###\n")
|
||||
Entropy.updateProgress = old_updprogress
|
||||
Entropy.ClientService.updateProgress = old_client_updprogress
|
||||
@@ -21886,6 +21900,7 @@ class SystemManagerExecutorServerRepositoryInterface:
|
||||
|
||||
finally:
|
||||
|
||||
stdout_err.write('\n\n Stdin: %s' % (self._get_stdin(queue_id),))
|
||||
stdout_err.write("\n### Done ###\n")
|
||||
Entropy.updateProgress = old_updprogress
|
||||
Entropy.ClientService.updateProgress = old_client_updprogress
|
||||
@@ -21907,6 +21922,12 @@ class SystemManagerExecutorServerRepositoryInterface:
|
||||
data[myid] = self.SystemManagerExecutor.SystemInterface.Entropy.SpmService.get_glsa_id_information(myid)
|
||||
return True,data
|
||||
|
||||
def _get_stdin(self, queue_id):
|
||||
mystdin = None
|
||||
std_data = self.SystemManagerExecutor.SystemInterface.ManagerStdInOut.get(queue_id)
|
||||
if std_data != None: mystdin = std_data[0]
|
||||
return mystdin
|
||||
|
||||
def _file_updateProgress(self, f, *myargs, **mykwargs):
|
||||
|
||||
f.flush()
|
||||
@@ -22345,7 +22366,7 @@ class SystemManagerRepositoryCommands(SocketCommandsSkel):
|
||||
'cflags': cflags,
|
||||
}
|
||||
|
||||
queue_id = self.HostInterface.add_to_queue(cmd, ' '.join(myargs), uid, gid, 'compile_atoms', [atoms[:]], add_dict.copy(), False, False)
|
||||
queue_id = self.HostInterface.add_to_queue(cmd, ' '.join(myargs), uid, gid, 'compile_atoms', [atoms[:]], add_dict.copy(), False, False, interactive = True)
|
||||
if queue_id < 0: return False, queue_id
|
||||
return True, queue_id
|
||||
|
||||
@@ -22387,7 +22408,7 @@ class SystemManagerRepositoryCommands(SocketCommandsSkel):
|
||||
'nocolor': nocolor,
|
||||
}
|
||||
|
||||
queue_id = self.HostInterface.add_to_queue(cmd, ' '.join(myargs), uid, gid, 'spm_remove_atoms', [atoms[:]], add_dict.copy(), False, False)
|
||||
queue_id = self.HostInterface.add_to_queue(cmd, ' '.join(myargs), uid, gid, 'spm_remove_atoms', [atoms[:]], add_dict.copy(), False, False, interactive = True)
|
||||
if queue_id < 0: return False, queue_id
|
||||
return True, queue_id
|
||||
|
||||
@@ -22494,7 +22515,7 @@ class SystemManagerRepositoryCommands(SocketCommandsSkel):
|
||||
gid = userdata.get('gid')
|
||||
command = ' '.join(myargs)
|
||||
|
||||
queue_id = self.HostInterface.add_to_queue(cmd, command, uid, gid, 'run_custom_shell_command', [command], {}, False, False)
|
||||
queue_id = self.HostInterface.add_to_queue(cmd, command, uid, gid, 'run_custom_shell_command', [command], {}, False, False, interactive = True)
|
||||
if queue_id < 0: return False, queue_id
|
||||
return True, queue_id
|
||||
|
||||
@@ -22677,7 +22698,7 @@ class SystemManagerRepositoryCommands(SocketCommandsSkel):
|
||||
uid = userdata.get('uid')
|
||||
gid = userdata.get('gid')
|
||||
|
||||
queue_id = self.HostInterface.add_to_queue(cmd, ' '.join(myargs), uid, gid, 'run_entropy_treeupdates', [myargs[0]], {}, False, False)
|
||||
queue_id = self.HostInterface.add_to_queue(cmd, ' '.join(myargs), uid, gid, 'run_entropy_treeupdates', [myargs[0]], {}, False, False, interactive = True)
|
||||
if queue_id < 0: return False, queue_id
|
||||
return True, queue_id
|
||||
|
||||
@@ -22709,7 +22730,7 @@ class SystemManagerRepositoryCommands(SocketCommandsSkel):
|
||||
uid = userdata.get('uid')
|
||||
gid = userdata.get('gid')
|
||||
|
||||
queue_id = self.HostInterface.add_to_queue(cmd, '<raw data>', uid, gid, 'run_entropy_mirror_updates', [mydict], {}, False, False)
|
||||
queue_id = self.HostInterface.add_to_queue(cmd, '<raw data>', uid, gid, 'run_entropy_mirror_updates', [mydict], {}, False, False, interactive = True)
|
||||
if queue_id < 0: return False, queue_id
|
||||
return True, queue_id
|
||||
|
||||
@@ -22750,7 +22771,11 @@ class SystemManagerRepositoryCommands(SocketCommandsSkel):
|
||||
uid = userdata.get('uid')
|
||||
gid = userdata.get('gid')
|
||||
|
||||
queue_id = self.HostInterface.add_to_queue(cmd, ' '.join(myargs), uid, gid, 'run_entropy_database_updates', [to_add,to_remove,to_inject], {}, False, True)
|
||||
queue_id = self.HostInterface.add_to_queue(
|
||||
cmd, ' '.join(myargs), uid, gid,
|
||||
'run_entropy_database_updates', [to_add,to_remove,to_inject],
|
||||
{}, False, True, interactive = True
|
||||
)
|
||||
if queue_id < 0: return False, queue_id
|
||||
return True, queue_id
|
||||
|
||||
@@ -22871,7 +22896,10 @@ class SystemManagerServerInterface(SocketHostInterface):
|
||||
def __init__(self, HostInterface):
|
||||
|
||||
SocketCommandsSkel.__init__(self, HostInterface, inst_name = "systemsrv")
|
||||
self.raw_commands = ['systemsrv:add_to_pinboard']
|
||||
self.raw_commands = [
|
||||
'systemsrv:add_to_pinboard',
|
||||
'systemsrv:write_to_running_command_pipe'
|
||||
]
|
||||
|
||||
self.valid_commands = {
|
||||
'systemsrv:get_queue': {
|
||||
@@ -22994,6 +23022,16 @@ class SystemManagerServerInterface(SocketHostInterface):
|
||||
'syntax': "<SESSION_ID> systemsrv:set_pinboard_items_done <pinboard identifier 1> <pinboard identifier 2> <...> <status (True/False)>",
|
||||
'from': str(self),
|
||||
},
|
||||
'systemsrv:write_to_running_command_pipe': {
|
||||
'auth': True,
|
||||
'built_in': False,
|
||||
'cb': self.docmd_write_to_running_command_pipe,
|
||||
'args': ["myargs"],
|
||||
'as_user': False,
|
||||
'desc': "write text to stdin of a running command",
|
||||
'syntax': "<SESSION_ID> systemsrv:write_to_running_command_pipe <queue_id> <txt ...>",
|
||||
'from': str(self),
|
||||
},
|
||||
}
|
||||
|
||||
def docmd_get_queue(self, myargs):
|
||||
@@ -23207,6 +23245,37 @@ class SystemManagerServerInterface(SocketHostInterface):
|
||||
self.HostInterface.set_pinboard_item_status(pinboard_id, status)
|
||||
return True,'ok'
|
||||
|
||||
def docmd_write_to_running_command_pipe(self, myargs):
|
||||
|
||||
if len(myargs) < 2:
|
||||
return False, 'wrong arguments'
|
||||
|
||||
try:
|
||||
queue_id = int(myargs[0])
|
||||
except ValueError:
|
||||
return False,'invalid queue id'
|
||||
|
||||
txt = ' '.join(myargs[1:])
|
||||
item, key = self.HostInterface.get_item_by_queue_id(queue_id)
|
||||
if key != self.HostInterface.processing_queue_keys:
|
||||
return False,'not running'
|
||||
mypipe = self.HostInterface.ManagerQueueStdInOut.get(queue_id)
|
||||
if mypipe == None:
|
||||
return False,'pipe not available'
|
||||
try:
|
||||
w_fd = mypipe[1]
|
||||
except (IndexError, ValueError,):
|
||||
return False,'pipe vanished'
|
||||
if not isinstance(w_fd,int):
|
||||
return False,'stdout fd not an int'
|
||||
try:
|
||||
os.write(w_fd,txt)
|
||||
except OSError, e:
|
||||
return False,'OSError: %s' % (e,)
|
||||
|
||||
return True,'ok'
|
||||
|
||||
|
||||
class FakeServiceInterface:
|
||||
def __init__(self, *args, **kwargs):
|
||||
pass
|
||||
@@ -23232,7 +23301,7 @@ class SystemManagerServerInterface(SocketHostInterface):
|
||||
STDOUT_STORAGE_DIR = os.path.join(etpConst['dumpstoragedir'],'system_manager_stdout')
|
||||
def __init__(self, EntropyInterface, do_ssl = False, stdout_logging = True, fork_requests = False, entropy_interface_kwargs = {}, **kwargs):
|
||||
|
||||
nocolor()
|
||||
#nocolor()
|
||||
self.queue_loaded = False
|
||||
import entropyTools, dumpTools, copy
|
||||
self.entropyTools, self.dumpTools, self.copy = entropyTools, dumpTools, copy
|
||||
@@ -23267,6 +23336,7 @@ class SystemManagerServerInterface(SocketHostInterface):
|
||||
self.removable_queue_keys = ['processed','errored','queue']
|
||||
self.processing_queue_keys = ['processing']
|
||||
self.dict_queue_keys = ['queue','processing','processed','errored']
|
||||
self.ManagerQueueStdInOut = {}
|
||||
self.ManagerQueue = {
|
||||
'queue': {},
|
||||
'queue_order': [],
|
||||
@@ -23446,7 +23516,7 @@ class SystemManagerServerInterface(SocketHostInterface):
|
||||
return True
|
||||
|
||||
|
||||
def add_to_queue(self, command_name, command_text, user_id, group_id, function, args, kwargs, do_parallel, extended_result):
|
||||
def add_to_queue(self, command_name, command_text, user_id, group_id, function, args, kwargs, do_parallel, extended_result, interactive = False):
|
||||
|
||||
if function not in self.SystemExecutor.available_commands:
|
||||
return -1
|
||||
@@ -23454,6 +23524,8 @@ class SystemManagerServerInterface(SocketHostInterface):
|
||||
self.queue_lock_acquire()
|
||||
try:
|
||||
queue_id = self.generate_unique_queue_id()
|
||||
if interactive:
|
||||
self.ManagerQueueStdInOut[queue_id] = os.pipe()
|
||||
myqueue_dict = {
|
||||
'queue_id': queue_id,
|
||||
'command_name': command_name,
|
||||
@@ -23469,6 +23541,7 @@ class SystemManagerServerInterface(SocketHostInterface):
|
||||
'kill': False,
|
||||
'processing_pid': None,
|
||||
'do_parallel': do_parallel,
|
||||
'interactive': False,
|
||||
}
|
||||
if extended_result:
|
||||
myqueue_dict['extended_result'] = None
|
||||
@@ -23493,7 +23566,7 @@ class SystemManagerServerInterface(SocketHostInterface):
|
||||
except KeyError:
|
||||
continue
|
||||
if item:
|
||||
self.flush_item(item)
|
||||
self.flush_item(item, queue_id)
|
||||
if queue_id in self.ManagerQueue[key+"_order"]:
|
||||
self.ManagerQueue[key+"_order"].remove(queue_id)
|
||||
removed = True
|
||||
@@ -23526,14 +23599,19 @@ class SystemManagerServerInterface(SocketHostInterface):
|
||||
finally:
|
||||
self.queue_lock_release()
|
||||
|
||||
def flush_item(self, item):
|
||||
def flush_item(self, item, queue_id):
|
||||
if not isinstance(item,dict):
|
||||
return False
|
||||
if item.has_key('stdout'):
|
||||
stdout = item['stdout']
|
||||
if (os.path.isfile(stdout) and os.access(stdout,os.W_OK)):
|
||||
os.remove(stdout)
|
||||
return True
|
||||
if item.has_key('interactive'):
|
||||
if item['interactive'] and (queue_id in self.ManagerQueueStdInOut):
|
||||
stdin, stdout = self.ManagerQueueStdInOut.pop(queue_id)
|
||||
os.close(stdin)
|
||||
os.close(stdout)
|
||||
return True
|
||||
|
||||
def assign_unique_stdout_file(self, queue_id):
|
||||
stdout = os.path.join(self.STDOUT_STORAGE_DIR,"%d.%s" % (queue_id,"stdout",))
|
||||
@@ -23826,6 +23904,15 @@ class SystemManagerClientCommands(EntropySocketClientCommands):
|
||||
)
|
||||
return self.do_generic_handler(cmd, session_id)
|
||||
|
||||
def write_to_running_command_pipe(self, session_id, queue_id, txt):
|
||||
cmd = "%s %s %s %s" % (
|
||||
session_id,
|
||||
'systemsrv:write_to_running_command_pipe',
|
||||
queue_id,
|
||||
txt,
|
||||
)
|
||||
return self.do_generic_handler(cmd, session_id)
|
||||
|
||||
class SystemManagerRepositoryClientCommands(SystemManagerClientCommands):
|
||||
|
||||
import dumpTools
|
||||
@@ -24216,6 +24303,15 @@ class SystemManagerMethodsInterface:
|
||||
'call': self.set_pinboard_items_done,
|
||||
'private': True,
|
||||
},
|
||||
'write_to_running_command_pipe': {
|
||||
'desc': _("Write to a remote running command stdin"),
|
||||
'params': [
|
||||
('queue_id',int,_('Queue Identifier'),True,),
|
||||
('txt',basestring,_('Text'),True,),
|
||||
],
|
||||
'call': self.write_to_running_command_pipe,
|
||||
'private': True,
|
||||
},
|
||||
}
|
||||
|
||||
def get_available_commands(self):
|
||||
@@ -24257,6 +24353,9 @@ class SystemManagerMethodsInterface:
|
||||
def set_pinboard_items_done(self, pinboard_ids, done_status):
|
||||
return self.Manager.do_cmd(True, "set_pinboard_items_done", [pinboard_ids,done_status], {})
|
||||
|
||||
def write_to_running_command_pipe(self, queue_id, txt):
|
||||
return self.Manager.do_cmd(True, "write_to_running_command_pipe", [queue_id, txt], {})
|
||||
|
||||
class SystemManagerRepositoryMethodsInterface(SystemManagerMethodsInterface):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
||||
@@ -1,298 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
'''
|
||||
# DESCRIPTION:
|
||||
# enzyme helper classes
|
||||
|
||||
Copyright (C) http://excess.org/urwid
|
||||
Thanks to Urwid developers, stuff taken from here too:
|
||||
http://excess.org/urwid/browser/urwid/trunk/dialog.py?format=txt
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
'''
|
||||
import urwid
|
||||
from entropyConstants import *
|
||||
from entropy_i18n import _
|
||||
|
||||
class ManagerSettings:
|
||||
|
||||
def __init__(self):
|
||||
self.Widgets = None
|
||||
self.process_spawned = False
|
||||
self.menu_enabled = False
|
||||
self.last_rc = None
|
||||
self.output_buffer = ''
|
||||
self.screen = None
|
||||
self.mainFrame = None
|
||||
self.mainBody = None
|
||||
self.menuBar = None
|
||||
self.statusBar = None
|
||||
self.programWidget = None
|
||||
self.outputWidget = None
|
||||
self.pinboardWidget = None
|
||||
self.output = None
|
||||
self.output_row = 1
|
||||
self.max_x, self.max_y = 0,0
|
||||
self.welcome_text = _("(CTRL+E Menu | CTRL+X Exit)")
|
||||
self.header_txt = ''
|
||||
self.inFocus = 0
|
||||
self.focusOptions = [0,1]
|
||||
self.focusInfo = {
|
||||
0: "Application",
|
||||
1: "Terminal"
|
||||
}
|
||||
self.auth_data = {}
|
||||
self.menu_keys_calls = {}
|
||||
|
||||
|
||||
class PasswordEdit(urwid.Edit):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
urwid.Edit.__init__(self, *args, **kwargs)
|
||||
self._clean_edit_text = ''
|
||||
|
||||
def set_edit_text(self, text):
|
||||
"""Set the edit text for this widget."""
|
||||
self.highlight = None
|
||||
self._clean_edit_text = text
|
||||
text = '*'*len(text)
|
||||
self.edit_text = text
|
||||
if self.edit_pos > len(text):
|
||||
self.edit_pos = len(text)
|
||||
self._invalidate()
|
||||
|
||||
def insert_text(self, text):
|
||||
"""Insert text at the cursor position and update cursor."""
|
||||
p = self.edit_pos
|
||||
self.set_edit_text( self._clean_edit_text[:p] + text +
|
||||
self._clean_edit_text[p:] )
|
||||
self.set_edit_pos( self.edit_pos + len(text))
|
||||
|
||||
def get_edit_text(self):
|
||||
return self._clean_edit_text
|
||||
|
||||
class SimpleWidgets:
|
||||
|
||||
class QuestionWidget(urwid.WidgetWrap):
|
||||
"""
|
||||
Creates a BoxWidget that displays a message
|
||||
|
||||
Attributes:
|
||||
|
||||
b_pressed -- Contains the label of the last button pressed or None if no
|
||||
button has been pressed.
|
||||
edit_text -- After a button is pressed, this contains the text the user
|
||||
has entered in the edit field
|
||||
"""
|
||||
|
||||
b_pressed = None
|
||||
edit_text = None
|
||||
_edit_widget = None
|
||||
_mode = None
|
||||
|
||||
def __init__(self, msg, buttons, attr, width, height, body):
|
||||
"""
|
||||
msg -- content of the message widget, one of:
|
||||
plain string -- string is displayed
|
||||
(attr, markup2) -- markup2 is given attribute attr
|
||||
[markupA, markupB, ... ] -- list items joined together
|
||||
buttons -- a list of strings with the button labels
|
||||
attr -- a tuple (background, button, active_button) of attributes
|
||||
width -- width of the message widget
|
||||
height -- height of the message widget
|
||||
body -- widget displayed beneath the message widget
|
||||
"""
|
||||
|
||||
self._blank = urwid.Text("")
|
||||
#Text widget containing the message:
|
||||
msg_widget = urwid.Padding(urwid.Text(msg), 'center', width - 4)
|
||||
|
||||
#GridFlow widget containing all the buttons:
|
||||
button_widgets = []
|
||||
|
||||
for button in buttons:
|
||||
button_widgets.append(urwid.AttrWrap(urwid.Button(button, self._action), attr[1], attr[2]))
|
||||
|
||||
button_grid = urwid.GridFlow(button_widgets, 12, 2, 1, 'center')
|
||||
|
||||
#Combine message widget and button widget:
|
||||
widget_list = [msg_widget, self._blank, button_grid]
|
||||
self._combined = urwid.AttrWrap(urwid.Filler(urwid.Pile(widget_list, 2)), attr[0])
|
||||
|
||||
#Place the dialog widget on top of body:
|
||||
overlay = urwid.Overlay(self._combined, body, 'center', width, 'middle', height)
|
||||
|
||||
urwid.WidgetWrap.__init__(self, overlay)
|
||||
|
||||
def _action(self, button):
|
||||
"""
|
||||
Function called when a button is pressed.
|
||||
Should not be called manually.
|
||||
"""
|
||||
|
||||
self.b_pressed = button.get_label()
|
||||
if self._edit_widget:
|
||||
self.edit_text = self._edit_widget.get_edit_text()
|
||||
|
||||
class MenuWidget(urwid.WidgetWrap):
|
||||
|
||||
class SelText(urwid.Text):
|
||||
"""
|
||||
A selectable text widget. See urwid.Text.
|
||||
"""
|
||||
|
||||
def selectable(self):
|
||||
return True
|
||||
|
||||
def keypress(self, size, key):
|
||||
"""
|
||||
Don't handle any keys.
|
||||
"""
|
||||
return key
|
||||
|
||||
"""
|
||||
Creates a popup menu on top of another BoxWidget.
|
||||
|
||||
Attributes:
|
||||
|
||||
selected -- Contains the item the user has selected by pressing <RETURN>,
|
||||
or None if nothing has been selected.
|
||||
"""
|
||||
|
||||
selected = None
|
||||
|
||||
def __init__(self, menu_list, attr, pos, body):
|
||||
"""
|
||||
menu_list -- a list of strings with the menu entries
|
||||
attr -- a tuple (background, active_item) of attributes
|
||||
pos -- a tuple (x, y), position of the menu widget
|
||||
body -- widget displayed beneath the message widget
|
||||
"""
|
||||
|
||||
content = [urwid.AttrWrap(self.SelText(" " + w), None, attr[1])
|
||||
for w in menu_list]
|
||||
|
||||
#Calculate width and height of the menu widget:
|
||||
height = len(menu_list)
|
||||
width = 0
|
||||
for entry in menu_list:
|
||||
if len(entry) > width:
|
||||
width = len(entry)
|
||||
|
||||
#Create the ListBox widget and put it on top of body:
|
||||
self._listbox = urwid.AttrWrap(urwid.ListBox(content), attr[0])
|
||||
overlay = urwid.Overlay(self._listbox, body, ('fixed left', pos[0]),
|
||||
width + 2, ('fixed top', pos[1]), height)
|
||||
|
||||
urwid.WidgetWrap.__init__(self, overlay)
|
||||
|
||||
|
||||
def keypress(self, size, key):
|
||||
"""
|
||||
<RETURN> key selects an item, other keys will be passed to
|
||||
the ListBox widget.
|
||||
"""
|
||||
|
||||
if key == "enter":
|
||||
(widget, foo) = self._listbox.get_focus()
|
||||
(text, foo) = widget.get_text()
|
||||
self.selected = text[1:] #Get rid of the leading space...
|
||||
else:
|
||||
return self._listbox.keypress(size, key)
|
||||
|
||||
class InputDialogWidget(urwid.WidgetWrap):
|
||||
|
||||
b_pressed = None
|
||||
def __init__(self, title, input_parameters, attr, width, body, cancel = True):
|
||||
|
||||
self.labels = {
|
||||
_('Ok'): 'ok',
|
||||
_('Cancel'): 'cancel',
|
||||
}
|
||||
height = 6
|
||||
self.button_values = ['ok','cancel']
|
||||
self.input_text_is_valid = False
|
||||
self.input_data = {}
|
||||
self.edit_widgets = []
|
||||
self.input_parameters = input_parameters[:]
|
||||
self.identifiers = {}
|
||||
self.do_cancel = cancel
|
||||
for identifier,widget_text,callback, password in self.input_parameters:
|
||||
if password:
|
||||
myw = PasswordEdit(caption = widget_text+": ")
|
||||
else:
|
||||
myw = urwid.Edit(caption = widget_text+": ")
|
||||
self.identifiers[identifier] = (myw,callback,widget_text,)
|
||||
self.edit_widgets.append(myw)
|
||||
height += 1
|
||||
|
||||
# blank line
|
||||
self._blank = urwid.Text("")
|
||||
self._title = urwid.Text(title)
|
||||
# buttons
|
||||
button_widgets = []
|
||||
button_widgets.append(urwid.AttrWrap(urwid.Button(_('Ok'), self._action), attr[1], attr[2]))
|
||||
if self.do_cancel:
|
||||
button_widgets.append(urwid.AttrWrap(urwid.Button(_('Cancel'), self._action), attr[1], attr[2]))
|
||||
# button grid
|
||||
button_grid = urwid.GridFlow(button_widgets, 12, 2, 1, 'center')
|
||||
|
||||
#Combine message widget and button widget:
|
||||
widget_list = [self._title,self._blank]
|
||||
widget_list += self.edit_widgets
|
||||
widget_list += [self._blank, button_grid]
|
||||
|
||||
self._combined = urwid.Filler(urwid.Pile(widget_list, 2))
|
||||
self._combined = urwid.Padding(self._combined, 'center', width - 4)
|
||||
self._combined = urwid.AttrWrap(self._combined, attr[0])
|
||||
|
||||
#Place the dialog widget on top of body:
|
||||
overlay = urwid.Overlay(self._combined, body, 'center', width+4, 'middle', height+1)
|
||||
urwid.WidgetWrap.__init__(self, overlay)
|
||||
|
||||
def _action(self, button):
|
||||
"""
|
||||
Function called when a button is pressed.
|
||||
Should not be called manually.
|
||||
"""
|
||||
|
||||
got_valid = True
|
||||
b_pressed = button.get_label()
|
||||
self.b_pressed = None
|
||||
# update input_data
|
||||
for identifier in self.identifiers:
|
||||
self.input_data[identifier] = None
|
||||
myw, cb, widget_text = self.identifiers[identifier]
|
||||
result = myw.get_edit_text()
|
||||
valid = cb(result)
|
||||
if valid:
|
||||
self.input_data[identifier] = result
|
||||
else:
|
||||
got_valid = False
|
||||
self.input_text_is_valid = got_valid
|
||||
self.b_pressed = self.labels.get(b_pressed)
|
||||
|
||||
def __init__(self, interface):
|
||||
self.Manager = interface.Manager
|
||||
self.Interface = interface
|
||||
|
||||
def Dialog(self, message, options):
|
||||
return self.QuestionWidget(message, options, ('menu', 'bg', 'bgf'), 30, 5, self.Manager.mainFrame)
|
||||
|
||||
def InputDialog(self, title, input_parameters, show_cancel = True):
|
||||
return self.InputDialogWidget(title, input_parameters, ('menu', 'bg', 'bgf'), 40, self.Manager.mainFrame, cancel = show_cancel)
|
||||
|
||||
def Menu(self, options, position):
|
||||
return self.MenuWidget(options, ('menu', 'menuf'), position, self.Manager.mainFrame)
|
||||
|
||||
Reference in New Issue
Block a user