From 63cbc852ca4db3580429c78677c09e8538f16859 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D0=B0=D0=BC=D0=BE=D1=83=D0=BA=D0=B8=D0=BD=20=D0=90?= =?UTF-8?q?=D0=BB=D0=B5=D0=BA=D1=81=D0=B5=D0=B9?= Date: Wed, 12 May 2010 17:10:43 +0400 Subject: [PATCH] Add module progressbar --- pym/client/__init__.py | 1 + pym/client/progressbar.py | 228 ++++++++++++++++++++++++++++++++++++++ setup.py | 3 +- 3 files changed, 231 insertions(+), 1 deletion(-) create mode 100644 pym/client/__init__.py create mode 100644 pym/client/progressbar.py diff --git a/pym/client/__init__.py b/pym/client/__init__.py new file mode 100644 index 0000000..8d1c8b6 --- /dev/null +++ b/pym/client/__init__.py @@ -0,0 +1 @@ + diff --git a/pym/client/progressbar.py b/pym/client/progressbar.py new file mode 100644 index 0000000..355b3eb --- /dev/null +++ b/pym/client/progressbar.py @@ -0,0 +1,228 @@ +#-*- coding: utf-8 -*- + +# Copyright 2008-2010 Mir Calculate Ltd. http://www.calculate-linux.org +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import re +import subprocess +import time + +class NoneProgressBar: + """Abstract class of progress bar. It do nothing.""" + def __init__(self,title,dialog=None): + pass + + def openDialog(self,title,max=None): + """Create dialog with progress bar, prepare date""" + pass + + def shutdownDialog(self): + """Destroy dialog""" + pass + + def setValue(self,value): + """Set value of progress bar relative of maximum""" + pass + + def setMaximum(self,max): + """Set maximum value of progress bar""" + pass + + def setTitle(self,title): + """Set title of progress dialog""" + pass + +class GProgressBar(NoneProgressBar): + """GProgressBar uses Xdialog program for display progressbar.""" + def __init__(self,title,xdialog=None): + self.title = title + self.bgPID = 0 + self.value = 0 + self.pipein = None + if xdialog == None: + self.openDialog(self.title) + + def openDialog(self,title,max=None): + if max != None: + self.setMaximum(max) + + title = re.sub("<[^>]+>", "", title) + self.title = title + if os.system('which Xdialog &>/dev/null') == 0: + pipe = subprocess.Popen('/usr/bin/Xdialog --progress "%s" 6 80'\ + %(self.title), + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + close_fds=True, + env=os.environ, shell=True) + self.pipein = pipe.stdin + self._set(1) + pipe.stdout.close() + pipe.stderr.close() + + def shutdownDialog(self): + '''Принудительно уничтожить процесс dialog''' + if self.pipein: + self._set(100) + time.sleep(0.1) + self.pipein.close() + self.pipein = None + + def _set(self,value): + if self.pipein: + self.pipein.write("%02d\n"%value) + self.pipein.flush() + + def setValue(self,value): + '''Установить текущее значения для прогресса''' + if self.pipein and value <= self.max: + progress_value = int(value / self.kmax) + if progress_value > int(self.value / self.kmax) and progress_value < 100: + self._set(progress_value) + self.value = value + + def setMaximum(self,max): + '''Установить максимальное значения для прогресса''' + self.max = max + self.kmax = max / 100.0 + + def setTitle(self,title): + '''Установить описания прогресса''' + pass + +class KProgressBar(NoneProgressBar): + """KProgressBar uses kdialog program and dbus for display progressbar.""" + + suffixSet = 'org.freedesktop.DBus.Properties.Set \ +org.kde.kdialog.ProgressDialog' + execenv = {"HOME":"/root"} + max = 100 + kdialog = None + label = None + def __init__(self,title,kdialog=None): + self.title = title + self.value = 0 + if kdialog is None: + self.openDialog(self.title) + + def openDialog(self,title,max=None): + if max != None: + self.max = max + self.title = title + if os.system('which kdialog >/dev/null') == 0: + self.label ="LOGINKDIALOG=%d" % os.getpid() + env = {} + env.update(os.environ.items() + self.execenv.items() +\ + [tuple(self.label.split("="))]) + pipe = subprocess.Popen('/usr/bin/kdialog --progressbar "%s" %d'\ + %(" "*(len(title)+20), self.max), + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + close_fds=True, + env=env, shell=True) + pipe.stdin.close() + # wait for terminate kdialog, which say dbus dialog id + if pipe.poll() is None: + # ожидание в 5 сек + for t in range(500): + time.sleep(0.01) + if pipe.poll() != None: + break + + # waiting is ok + if pipe.poll() == 0: + self.kdialog = pipe.stdout.readline().strip() + while not "org.kde.kdialog" in self.kdialog: + s = pipe.stdout.readline() + # if bad result of kdialog then shutdown dialog + if s == "": + pipe.stdout.close() + pipe.stderr.close() + self.shutdownDialog() + break + self.kdialog = s.strip() + self.setTitle(self.title) + pipe.stdout.close() + pipe.stderr.close() + # waiting is failed + else: + pipe.stdout.close() + pipe.stderr.close() + self.shutdownDialog() + + def shutdownDialog(self): + '''Принудительно уничтожить процесс kdialog''' + self.kdialog = None + pipe = subprocess.Popen("/bin/ps axeo pid,cmd", + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + close_fds=True, shell=True) + if self.label != None: + for s in pipe.stdout.readlines(): + if self.label in s: + try: + os.kill( int(s.split()[0]), 9 ) + except (OSError,ValueError): + pass + self.label = None + + def setValue(self,value): + '''Установить текущее значения для прогресса''' + if self.kdialog and value <= self.max: + env = "" + if self.execenv: + env = " ".join(map(lambda x: '%s="%s"'%(x[0],x[1]),\ + self.execenv)) + " " + oldperc = int(self.value / self.kmax) + newperc = int(value / self.kmax) + if newperc > oldperc: + os.system(env + '/usr/bin/qdbus %s %s value %d >/dev/null'\ + %(self.kdialog,self.suffixSet, newperc)) + self.value = value + + def setMaximum(self,max): + '''Установить максимальное значения для прогресса''' + if self.kdialog and self.max == 0 and max != 0: + env = "" + if self.execenv: + env = " ".join(map(lambda x: '%s="%s"'%(x[0],x[1]),\ + self.execenv)) + " " + os.system(env + '/usr/bin/qdbus %s %s maximum %d >/dev/null'\ + %(self.kdialog,self.suffixSet, 100)) + self.max = max + self.kmax = max / 100.0 + + + def setTitle(self,title): + '''Установить описания прогресса''' + self.title = title + if self.kdialog: + env = "" + if self.execenv: + env = " ".join(map(lambda x: '%s="%s"'%(x[0],x[1]),\ + self.execenv)) + " " + os.system(env + '/usr/bin/qdbus %s setLabelText "%s" >/dev/null'\ + %(self.kdialog,self.title)) + +def ProgressBar(*args,**kwarg): + """Return instance of object for progress bar""" + if os.system('which kdialog &>/dev/null') == 0: + return KProgressBar(*args,**kwarg) + elif os.system('which Xdialog &>/dev/null') == 0: + return GProgressBar(*args,**kwarg) + return NoneProgressBar(*args,**kwarg) diff --git a/setup.py b/setup.py index 3af7c60..49c8477 100755 --- a/setup.py +++ b/setup.py @@ -32,7 +32,8 @@ setup( package_dir = {'calculate-lib': "."}, packages = ['calculate-lib.pym', 'calculate-lib.pym.format', - 'calculate-lib.pym.server'], + 'calculate-lib.pym.server', + 'calculate-lib.pym.client'], data_files = [("/usr/share/calculate-2.2/i18n",['i18n/cl_lib_ru.mo']), ("/var/calculate/remote",[])], )