222 lines
6.2 KiB
Python
222 lines
6.2 KiB
Python
|
# basictimerapp - a really simple timer application.
|
||
|
# This should be run using the command line:
|
||
|
# pythonwin /app demos\basictimerapp.py
|
||
|
import win32ui
|
||
|
import win32api
|
||
|
import win32con
|
||
|
import sys
|
||
|
from pywin.framework import app, cmdline, dlgappcore, cmdline
|
||
|
import timer
|
||
|
import time
|
||
|
import string
|
||
|
|
||
|
class TimerAppDialog(dlgappcore.AppDialog):
|
||
|
softspace=1
|
||
|
def __init__(self, appName = ""):
|
||
|
dlgappcore.AppDialog.__init__(self, win32ui.IDD_GENERAL_STATUS)
|
||
|
self.timerAppName = appName
|
||
|
self.argOff = 0
|
||
|
if len(self.timerAppName)==0:
|
||
|
if len(sys.argv)>1 and sys.argv[1][0]!='/':
|
||
|
self.timerAppName = sys.argv[1]
|
||
|
self.argOff = 1
|
||
|
|
||
|
def PreDoModal(self):
|
||
|
# sys.stderr = sys.stdout
|
||
|
pass
|
||
|
|
||
|
def ProcessArgs(self, args):
|
||
|
for arg in args:
|
||
|
if arg=="/now":
|
||
|
self.OnOK()
|
||
|
|
||
|
def OnInitDialog(self):
|
||
|
win32ui.SetProfileFileName('pytimer.ini')
|
||
|
self.title = win32ui.GetProfileVal(self.timerAppName, "Title", "Remote System Timer")
|
||
|
self.buildTimer = win32ui.GetProfileVal(self.timerAppName, "Timer", "EachMinuteIntervaler()")
|
||
|
self.doWork = win32ui.GetProfileVal(self.timerAppName, "Work", "DoDemoWork()")
|
||
|
# replace "\n" with real \n.
|
||
|
self.doWork = self.doWork.replace('\\n','\n')
|
||
|
dlgappcore.AppDialog.OnInitDialog(self)
|
||
|
|
||
|
self.SetWindowText(self.title)
|
||
|
self.prompt1 = self.GetDlgItem(win32ui.IDC_PROMPT1)
|
||
|
self.prompt2 = self.GetDlgItem(win32ui.IDC_PROMPT2)
|
||
|
self.prompt3 = self.GetDlgItem(win32ui.IDC_PROMPT3)
|
||
|
self.butOK = self.GetDlgItem(win32con.IDOK)
|
||
|
self.butCancel = self.GetDlgItem(win32con.IDCANCEL)
|
||
|
self.prompt1.SetWindowText("Python Timer App")
|
||
|
self.prompt2.SetWindowText("")
|
||
|
self.prompt3.SetWindowText("")
|
||
|
self.butOK.SetWindowText("Do it now")
|
||
|
self.butCancel.SetWindowText("Close")
|
||
|
|
||
|
self.timerManager = TimerManager(self)
|
||
|
self.ProcessArgs(sys.argv[self.argOff:])
|
||
|
self.timerManager.go()
|
||
|
return 1
|
||
|
|
||
|
def OnDestroy(self,msg):
|
||
|
dlgappcore.AppDialog.OnDestroy(self, msg)
|
||
|
self.timerManager.stop()
|
||
|
def OnOK(self):
|
||
|
# stop the timer, then restart after setting special boolean
|
||
|
self.timerManager.stop()
|
||
|
self.timerManager.bConnectNow = 1
|
||
|
self.timerManager.go()
|
||
|
return
|
||
|
# def OnCancel(self): default behaviour - cancel == close.
|
||
|
# return
|
||
|
|
||
|
class TimerManager:
|
||
|
def __init__(self, dlg):
|
||
|
self.dlg = dlg
|
||
|
self.timerId = None
|
||
|
self.intervaler = eval(self.dlg.buildTimer)
|
||
|
self.bConnectNow = 0
|
||
|
self.bHaveSetPrompt1 = 0
|
||
|
def CaptureOutput(self):
|
||
|
self.oldOut = sys.stdout
|
||
|
self.oldErr = sys.stderr
|
||
|
sys.stdout = sys.stderr = self
|
||
|
self.bHaveSetPrompt1 = 0
|
||
|
def ReleaseOutput(self):
|
||
|
sys.stdout = self.oldOut
|
||
|
sys.stderr = self.oldErr
|
||
|
def write(self, str):
|
||
|
s = str.strip()
|
||
|
if len(s):
|
||
|
if self.bHaveSetPrompt1:
|
||
|
dest = self.dlg.prompt3
|
||
|
else:
|
||
|
dest = self.dlg.prompt1
|
||
|
self.bHaveSetPrompt1 = 1
|
||
|
dest.SetWindowText(s)
|
||
|
def go(self):
|
||
|
self.OnTimer(None,None)
|
||
|
def stop(self):
|
||
|
if self.timerId: timer.kill_timer (self.timerId)
|
||
|
self.timerId = None
|
||
|
|
||
|
def OnTimer(self, id, timeVal):
|
||
|
if id: timer.kill_timer (id)
|
||
|
if self.intervaler.IsTime() or self.bConnectNow :
|
||
|
# do the work.
|
||
|
try:
|
||
|
self.dlg.SetWindowText(self.dlg.title + " - Working...")
|
||
|
self.dlg.butOK.EnableWindow(0)
|
||
|
self.dlg.butCancel.EnableWindow(0)
|
||
|
self.CaptureOutput()
|
||
|
try:
|
||
|
exec(self.dlg.doWork)
|
||
|
print("The last operation completed successfully.")
|
||
|
except:
|
||
|
t, v, tb = sys.exc_info()
|
||
|
str = "Failed: %s: %s" % (t, repr(v))
|
||
|
print(str)
|
||
|
self.oldErr.write(str)
|
||
|
tb = None # Prevent cycle
|
||
|
finally:
|
||
|
self.ReleaseOutput()
|
||
|
self.dlg.butOK.EnableWindow()
|
||
|
self.dlg.butCancel.EnableWindow()
|
||
|
self.dlg.SetWindowText(self.dlg.title)
|
||
|
else:
|
||
|
now = time.time()
|
||
|
nextTime = self.intervaler.GetNextTime()
|
||
|
if nextTime:
|
||
|
timeDiffSeconds = nextTime - now
|
||
|
timeDiffMinutes = int(timeDiffSeconds / 60)
|
||
|
timeDiffSeconds = timeDiffSeconds % 60
|
||
|
timeDiffHours = int(timeDiffMinutes / 60)
|
||
|
timeDiffMinutes = timeDiffMinutes % 60
|
||
|
self.dlg.prompt1.SetWindowText("Next connection due in %02d:%02d:%02d" % (timeDiffHours,timeDiffMinutes,timeDiffSeconds))
|
||
|
self.timerId = timer.set_timer (self.intervaler.GetWakeupInterval(), self.OnTimer)
|
||
|
self.bConnectNow = 0
|
||
|
|
||
|
class TimerIntervaler:
|
||
|
def __init__(self):
|
||
|
self.nextTime = None
|
||
|
self.wakeUpInterval = 2000
|
||
|
def GetWakeupInterval(self):
|
||
|
return self.wakeUpInterval
|
||
|
def GetNextTime(self):
|
||
|
return self.nextTime
|
||
|
def IsTime(self):
|
||
|
now = time.time()
|
||
|
if self.nextTime is None:
|
||
|
self.nextTime = self.SetFirstTime(now)
|
||
|
ret = 0
|
||
|
if now >= self.nextTime:
|
||
|
ret = 1
|
||
|
self.nextTime = self.SetNextTime(self.nextTime, now)
|
||
|
# do the work.
|
||
|
return ret
|
||
|
|
||
|
class EachAnyIntervaler(TimerIntervaler):
|
||
|
def __init__(self, timeAt, timePos, timeAdd, wakeUpInterval = None):
|
||
|
TimerIntervaler.__init__(self)
|
||
|
self.timeAt = timeAt
|
||
|
self.timePos = timePos
|
||
|
self.timeAdd = timeAdd
|
||
|
if wakeUpInterval:
|
||
|
self.wakeUpInterval = wakeUpInterval
|
||
|
def SetFirstTime(self, now):
|
||
|
timeTup = time.localtime(now)
|
||
|
lst = []
|
||
|
for item in timeTup:
|
||
|
lst.append(item)
|
||
|
bAdd = timeTup[self.timePos] > self.timeAt
|
||
|
lst[self.timePos] = self.timeAt
|
||
|
for pos in range(self.timePos+1, 6):
|
||
|
lst[pos]=0
|
||
|
ret = time.mktime(tuple(lst))
|
||
|
if (bAdd):
|
||
|
ret = ret + self.timeAdd
|
||
|
return ret;
|
||
|
|
||
|
def SetNextTime(self, lastTime, now):
|
||
|
return lastTime + self.timeAdd
|
||
|
|
||
|
class EachMinuteIntervaler(EachAnyIntervaler):
|
||
|
def __init__(self, at=0):
|
||
|
EachAnyIntervaler.__init__(self, at, 5, 60, 2000)
|
||
|
|
||
|
class EachHourIntervaler(EachAnyIntervaler):
|
||
|
def __init__(self, at=0):
|
||
|
EachAnyIntervaler.__init__(self, at, 4, 3600, 10000)
|
||
|
|
||
|
class EachDayIntervaler(EachAnyIntervaler):
|
||
|
def __init__(self,at=0):
|
||
|
EachAnyIntervaler.__init__(self, at, 3, 86400, 10000)
|
||
|
|
||
|
class TimerDialogApp(dlgappcore.DialogApp):
|
||
|
def CreateDialog(self):
|
||
|
return TimerAppDialog()
|
||
|
|
||
|
def DoDemoWork():
|
||
|
print("Doing the work...")
|
||
|
print("About to connect")
|
||
|
win32api.MessageBeep(win32con.MB_ICONASTERISK)
|
||
|
win32api.Sleep(2000)
|
||
|
print("Doing something else...")
|
||
|
win32api.MessageBeep(win32con.MB_ICONEXCLAMATION)
|
||
|
win32api.Sleep(2000)
|
||
|
print("More work.")
|
||
|
win32api.MessageBeep(win32con.MB_ICONHAND)
|
||
|
win32api.Sleep(2000)
|
||
|
print("The last bit.")
|
||
|
win32api.MessageBeep(win32con.MB_OK)
|
||
|
win32api.Sleep(2000)
|
||
|
|
||
|
app = TimerDialogApp()
|
||
|
|
||
|
def t():
|
||
|
t = TimerAppDialog("Test Dialog")
|
||
|
t.DoModal()
|
||
|
return t
|
||
|
|
||
|
if __name__=='__main__':
|
||
|
import demoutils
|
||
|
demoutils.NeedApp()
|