#-*- coding: utf-8 -*- # Copyright 2008-2010 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) or 1.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, env=os.environ, 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) or 1.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)