def createConfigurationInterface(self, parent): values = {'lon':self.lon, 'lat':self.lat, 'daytmp':self.daytmp, 'nighttmp':self.nighttmp, 'program':self.program, 'smooth':self.smooth, 'mode':self.mode, 'gamma':self.gamma, 'auto':self.auto} self.conf = FluxConfig(self,values) self.conf.setWindowTitle('Widget configuration') page = parent.addPage(self.conf,'Configuration') page.setIcon(KIcon(ICON_PLASMOID)) self.connect(parent, SIGNAL('okClicked()'), self.configAccepted)
class FluxApplet(plasmascript.Applet): #constructor def __init__(self, parent, args=None): plasmascript.Applet.__init__(self, parent) self.parent = parent #done once when initiating def init(self): self.button = Plasma.IconWidget(self.parent) self.iconStopped = KIcon(ICON_STOPPED) self.iconRunning = KIcon(ICON_RUNNING) self.iconUnknown = KIcon(ICON_UNKNOWN) self.pid = None self.subp = None self.waiting = False self.setHasConfigurationInterface(True) #set size of Plasmoid self.resize(50, 50) self.setAspectRatioMode(Plasma.KeepAspectRatio) self.setBackgroundHints(Plasma.Applet.DefaultBackground) self.theme = Plasma.Svg(self) self.theme.setImagePath(THEME) self.layout = QGraphicsGridLayout(self.applet) self.layout.setContentsMargins(3,3,3,3) self.setMinimumSize(10,10) #set timer interval self.timer = self.startTimer(REFRESH) self.button.setIcon(self.iconUnknown) QObject.connect(self.button, SIGNAL('clicked()'), self.toggle) self.appletDestroyed.connect(self.destroy) self.cfgfile = '.plasma-flux.cfg' strFile = os.path.join(os.path.expanduser('~'), self.cfgfile) if os.path.exists(strFile): cfgParser = ConfigParser() cfgFile = open(strFile) cfgParser.readfp(cfgFile) try: self.lon = cfgParser.getfloat('settings', 'lon') self.lat = cfgParser.getfloat('settings', 'lat') self.nighttmp = cfgParser.getint('settings', 'nighttmp') self.daytmp = cfgParser.getint('settings', 'daytmp') self.smooth = cfgParser.getboolean('settings', 'smooth') self.program = cfgParser.get('settings', 'program') self.mode = cfgParser.get('settings', 'mode') self.gamma = cfgParser.get('settings', 'gamma') self.auto = cfgParser.getboolean('settings', 'auto') cfgFile.close() except: self.defaultOptions() else: self.defaultOptions() self.updateStatus() if self.auto and self.checkStatus() == 'Stopped': print('Auto-starting %s' % self.program) self.toggle() def defaultOptions(self): self.lon = float(DEFAULT_LONGITUDE) self.lat = float(DEFAULT_LATITUDE) self.nighttmp = int(DEFAULT_NIGHT) self.daytmp = int(DEFAULT_DAY) self.smooth = True self.program = str(DEFAULT_PROGRAM) self.mode = str(DEFAULT_MODE) self.gamma = '1.00:1.00:1.00' self.auto = False #done when timer is resetted def timerEvent(self, event): #call draw method self.update() #parse the status def checkStatus(self): self.updateStatus() if self.pid: if self.pid.isdigit(): return 'Running' else: return 'Unknown' else: return 'Stopped' #get the pid def updateStatus(self): self.pid = commands.getoutput('pidof %s' % FLUX) if not self.pid: self.pid = commands.getoutput('pidof %s' % REDSHIFT) if not self.waiting: self.waiting = True if self.subp: if not self.pid: retcode = os.waitpid(int(self.subp.pid), os.WNOHANG) if retcode[1]: stderr = self.subp.stderr.read() stdout = self.subp.stdout.read() QMessageBox.critical(self.parent, 'An error has occurred', '%s exited abnormally, probably due to wrong configuration.\nPlease report this to the developer:\n===================================================\n\nExit code:\n(%d, %s)\n\nstderr:\n%s\n\nstdout:\n%s\n===================================================' % (self.program, retcode[1], os.WEXITSTATUS(self.subp.pid), stderr, stdout)) #self.subp.stderr.close() #self.subp.stdout.close() self.subp = None self.waiting = False def toggle(self): status = self.checkStatus() if status == 'Stopped': if self.program == 'f.lux': self.startXflux() elif self.program == 'Redshift': self.startRedshift() elif status == 'Running': self.stopProgram() else: print('Unknown status') #May be more than one instance running? self.killProgram() self.toggle() def startXflux(self): print('Starting f.lux with latitude %.1f, longitude %.1f, temperature %d' % (self.lat, self.lon, self.nighttmp)) self.subp = Popen('%s -l %.1f -g %.1f -k %d -nofork' % (FLUX, self.lat, self.lon, self.nighttmp), shell=True, stdout=PIPE, stderr=PIPE) def startRedshift(self): print('Starting Redshift with latitude %.1f, longitude %.1f, day temperature %d, night temperature %d, gamma ramp %s, smooth transition = %s' % (self.lat, self.lon, self.daytmp, self.nighttmp, self.gamma, ('yes' if self.smooth else 'no'))) self.subp = Popen('%s -l %.1f:%.1f -t %d:%d -g %s -m %s %s' %(REDSHIFT, self.lat, self.lon, self.daytmp, self.nighttmp, self.gamma, self.mode, ('-r' if not self.smooth else '')), shell=True, stdout=PIPE, stderr=PIPE) def stopProgram(self): print('Stopping') import signal #Popen('kill %s' % self.pid, shell=True) '''if commands.getoutput('pidof %s' % FLUX): #xflux if self.subp: self.subp.send_signal(signal.SIGTERM) else: os.kill(int(self.pid), signal.SIGTERM) elif commands.getoutput('pidof %s ' % REDSHIFT): #redshift if self.subp: self.subp.send_signal(signal.SIGUSR1) else: os.kill(int(self.pid), signal.SIGUSR1)''' if self.subp: self.subp.send_signal(signal.SIGTERM) elif self.pid: os.kill(int(self.pid), signal.SIGTERM) def killProgram(self): print('Killing processes: %s' % self.pid) Popen('kill -9 %s' % self.pid, shell=True) #draw method def paintInterface(self, painter, option, rect): if self.checkStatus() == 'Running': self.button.setIcon(self.iconRunning) elif self.checkStatus() == 'Stopped': self.button.setIcon(self.iconStopped) else: self.button.setIcon(self.iconUnknown) self.layout.addItem(self.button, 0, 0) #create config interface def createConfigurationInterface(self, parent): values = {'lon':self.lon, 'lat':self.lat, 'daytmp':self.daytmp, 'nighttmp':self.nighttmp, 'program':self.program, 'smooth':self.smooth, 'mode':self.mode, 'gamma':self.gamma, 'auto':self.auto} self.conf = FluxConfig(self,values) self.conf.setWindowTitle('Widget configuration') page = parent.addPage(self.conf,'Configuration') page.setIcon(KIcon(ICON_PLASMOID)) self.connect(parent, SIGNAL('okClicked()'), self.configAccepted) #self.connect(parent, SIGNAL('cancelClicked()'), self.configDenied) def configAccepted(self): self.lon = self.conf.getLongitude() self.lat = self.conf.getLatitude() self.nighttmp = self.conf.getNightTemperature() self.daytmp = self.conf.getDayTemperature() self.smooth = self.conf.getSmooth() self.program = self.conf.getProgram() self.mode = self.conf.getMode() self.gamma = self.conf.getGamma() self.auto = self.conf.getAutoLaunch() cfgParser = ConfigParser() cfgParser.read(self.cfgfile) if not cfgParser.has_section('settings'): cfgParser.add_section('settings') cfgParser.set('settings', 'lat', self.lat) cfgParser.set('settings','lon', self.lon) cfgParser.set('settings','nighttmp', self.nighttmp) cfgParser.set('settings','daytmp', self.daytmp) cfgParser.set('settings','smooth', self.smooth) cfgParser.set('settings','program', self.program) cfgParser.set('settings','mode', self.mode) cfgParser.set('settings', 'gamma', self.gamma) cfgParser.set('settings', 'auto', self.auto) strFile = os.path.join(os.path.expanduser('~'),self.cfgfile) cfgFile = open(strFile,'w') cfgParser.write(cfgFile) cfgFile.close() def destroy(self): self.killTimer(self.timer) self.stopProgram()