1# Boa:Dialog:DlgJobVisual
2# -*- coding: utf-8 -*-
3#
4# Copyright (C) 2018 Jens Goepfert
5#
6
7import time
8
9import wx
10
11from .WxVisualJobHandler import WxVisualJobHandler, EVT_JOB_UPDATE
12
13[wxID_DLGJOBVISUAL, wxID_DLGJOBVISUALCMDABORT, wxID_DLGJOBVISUALGAUGE,
14 wxID_DLGJOBVISUALSTELAPSEDDIV, wxID_DLGJOBVISUALSTELAPSEDLABEL,
15 wxID_DLGJOBVISUALSTELAPSEDVALUE, wxID_DLGJOBVISUALSTINFO,
16 wxID_DLGJOBVISUALSTREMAININGDIV, wxID_DLGJOBVISUALSTREMAININGLABEL,
17 wxID_DLGJOBVISUALSTREMAININGVALUE,
18] = [wx.NewId() for _init_ctrls in range(10)]
19
20
21class DlgJobVisual(wx.Dialog, WxVisualJobHandler):
22
23    def _init_coll_szMain_Items(self, parent):
24        # generated method, don't edit
25
26        parent.Add(self.stInfo, 0, border=8, flag=wx.ALL)
27        parent.Add(self.gauge, 0, border=8, flag=wx.EXPAND | wx.ALL)
28        parent.Add(self.szTiming, 0, border=8, flag=wx.EXPAND | wx.ALL)
29        parent.Add(self.cmdAbort, 0, border=8,
30              flag=wx.ALL | wx.ALIGN_CENTER_HORIZONTAL)
31
32    def _init_coll_szTiming_Items(self, parent):
33        # generated method, don't edit
34
35        parent.Add(self.stElapsedLabel, 0, border=0, flag=wx.ALIGN_RIGHT)
36        parent.Add(self.stElapsedDiv, 0, border=4,
37              flag=wx.RIGHT | wx.LEFT)
38        parent.Add(self.stElapsedValue, 0, border=8, flag=wx.LEFT)
39        parent.Add(self.stRemainingLabel, 0, border=0,
40              flag=wx.ALIGN_RIGHT)
41        parent.Add(self.stRemainingDiv, 0, border=4,
42              flag=wx.RIGHT | wx.LEFT)
43        parent.Add(self.stRemainingValue, 0, border=8, flag=wx.LEFT)
44
45    def _init_sizers(self):
46        # generated method, don't edit
47        self.szMain = wx.BoxSizer(orient=wx.VERTICAL)
48
49        self.szTiming = wx.FlexGridSizer(cols=3, hgap=0, rows=2, vgap=8)
50
51        self._init_coll_szMain_Items(self.szMain)
52        self._init_coll_szTiming_Items(self.szTiming)
53
54        self.SetSizer(self.szMain)
55
56    def _init_ctrls(self, prnt):
57        # generated method, don't edit
58        wx.Dialog.__init__(self, id=wxID_DLGJOBVISUAL, name=u'DlgJobVisual',
59              parent=prnt, pos=wx.Point(-1, -1), size=wx.Size(-1, -1),
60              style=wx.DEFAULT_DIALOG_STYLE, title='')
61        self.SetClientSize(wx.Size(400, 250))
62        self.SetSizeHints(350, -1, -1, -1)
63
64        self.stInfo = wx.StaticText(id=wxID_DLGJOBVISUALSTINFO, label=u'Info',
65              name=u'stInfo', parent=self, pos=wx.Point(-1, -1),
66              size=wx.Size(-1, -1), style=0)
67
68        self.gauge = wx.Gauge(id=wxID_DLGJOBVISUALGAUGE, name=u'gauge',
69              parent=self, pos=wx.Point(-1, -1), range=100,
70              size=wx.Size(-1, -1), style=wx.GA_HORIZONTAL)
71
72        self.stElapsedLabel = wx.StaticText(id=wxID_DLGJOBVISUALSTELAPSEDLABEL,
73              label=_(u'Elapsed time'), name=u'stElapsedLabel', parent=self,
74              pos=wx.Point(-1, -1), size=wx.Size(-1, -1), style=wx.ALIGN_RIGHT)
75
76        self.stElapsedDiv = wx.StaticText(id=wxID_DLGJOBVISUALSTELAPSEDDIV,
77              label=u':', name=u'stElapsedDiv', parent=self,
78              pos=wx.Point(-1, -1), size=wx.Size(-1, -1), style=0)
79
80        self.stElapsedValue = wx.StaticText(id=wxID_DLGJOBVISUALSTELAPSEDVALUE,
81              label=u'0:00:00', name=u'stElapsedValue', parent=self,
82              pos=wx.Point(-1, -1), size=wx.Size(-1, -1), style=0)
83
84        self.stRemainingLabel = wx.StaticText(id=wxID_DLGJOBVISUALSTREMAININGLABEL,
85              label=_(u'Remaining time'), name=u'stRemainingLabel', parent=self,
86              pos=wx.Point(-1, -1), size=wx.Size(-1, -1), style=0)
87
88        self.stRemainingDiv = wx.StaticText(id=wxID_DLGJOBVISUALSTREMAININGDIV,
89              label=u':', name=u'stRemainingDiv', parent=self,
90              pos=wx.Point(-1, -1), size=wx.Size(-1, -1), style=0)
91
92        self.stRemainingValue = wx.StaticText(id=wxID_DLGJOBVISUALSTREMAININGVALUE,
93              label=u'0:00:00', name=u'stRemainingValue', parent=self,
94              pos=wx.Point(-1, -1), size=wx.Size(-1, -1), style=0)
95
96        self.cmdAbort = wx.Button(id=wxID_DLGJOBVISUALCMDABORT,
97              label=_(u'&Cancel'), name=u'cmdAbort', parent=self,
98              pos=wx.Point(-1, -1), size=wx.Size(-1, -1), style=0)
99        self.cmdAbort.Show(False)
100        self.cmdAbort.Bind(wx.EVT_BUTTON, self.__OnCancel,
101              id=wxID_DLGJOBVISUALCMDABORT)
102
103        self._init_sizers()
104
105    def __init__(self, parent, job):
106        self._init_ctrls(parent)
107        WxVisualJobHandler.__init__(self)
108        self.SetTitle(job.GetName())
109
110        if self.cmdAbort.IsShown():
111            self.__state = "Continue"
112        else:
113            self.__state = "Uncancelable"
114
115        self.__job = job
116        self.__delay = 3
117        self.__maximum = 100
118        self.__display_estimated = 0
119        self.__last_timeupdate = 0
120        self.__ctdelay = 0
121        self.__timeStart = time.time()
122
123        self.Bind(wx.EVT_CLOSE, self.__OnClose)
124        self.Bind(EVT_JOB_UPDATE, self.__OnJobUpdate)
125
126    def __OnCancel(self, event):
127        if self.__state == "Finished":
128            event.Skip()
129        else:
130            self.__state = "Canceled"
131#            self.DisableAbort()
132#            self.DisableSkip()
133
134            self.__timeStop = time.time()
135
136    def __OnClose(self, event):
137        if self.__state == "Uncancelable":
138            event.Veto()
139        elif self.__state == "Finished":
140            event.Skip()
141        else:
142            self.__state = "Canceled"
143#            self.DisableAbort()
144#            self.DisableSkip()
145            self.__timeStop = time.time()
146
147    def __Pulse(self, newmsg):
148        self.gauge.Pulse()
149        self.__UpdateMessage(newmsg)
150
151        if 1:  # self.__elapsed or self.__remaining or self.__estimated:
152            elapsed = time.time() - self.__timeStart
153
154            self.__SetTimeLabel(elapsed, self.stElapsedValue)
155#            self.__SetTimeLabel(-1, self.stEstimated)
156            self.__SetTimeLabel(-1, self.stRemainingValue)
157
158    def __Update(self, value, msg):
159        if value <= self.__maximum:
160            self.gauge.SetValue(value)
161        self.__UpdateMessage(msg)
162
163#        if (self.__elapsed or self.__remaining or self.__estimated) and (value != 0):
164        if value != 0:
165            elapsed = time.time() - self.__timeStart
166            if self.__last_timeupdate < elapsed or value == self.__maximum:
167                self.__last_timeupdate = elapsed
168                estimated = (elapsed * self.__maximum) / value
169                if estimated > self.__display_estimated and self.__ctdelay >= 0:
170                    self.__ctdelay += 1
171                elif estimated < self.__display_estimated and self.__ctdelay <= 0:
172                    self.__ctdelay -= 1
173                else:
174                    self.__ctdelay = 0
175
176                if self.__ctdelay >= self.__delay \
177                or self.__ctdelay <= (self.__delay * -1) \
178                or value == self.__maximum \
179                or elapsed > self.__display_estimated \
180                or (elapsed > 0 and elapsed < 4):
181                    self.__display_estimated = estimated
182                    self.__ctdelay = 0
183
184            display_remaining = self.__display_estimated - elapsed
185            if display_remaining < 0:
186                display_remaining = 0;
187
188            self.__SetTimeLabel(elapsed, self.stElapsedValue)
189#            self.__SetTimeLabel(m_display_estimated, self.stEstimated)
190            self.__SetTimeLabel(display_remaining, self.stRemainingValue)
191
192    def __UpdateMessage(self, newmsg):
193        if newmsg and newmsg != self.stInfo.GetLabel():
194            self.stInfo.SetLabel(newmsg)
195
196    def __SetTimeLabel(self, val, staticText):
197        if val != -1:
198            hours = val // 3600
199            minutes = (val % 3600) // 60
200            seconds = val % 60
201            s = "%d:%02d:%02d" % (hours, minutes, seconds)
202        else:
203            s = _("Unknown")
204
205        if s != staticText.GetLabel():
206            staticText.SetLabel(s)
207
208    def __OnJobUpdate(self, event):
209        if event.IsBegin():
210            self.__timeStart = time.time()
211#            self.__dlg = wx.ProgressDialog(self.__job.GetName(),
212#                                           self.__job.GetInfo(),
213#                                           maximum=self.__job.GetMaxProgress(),
214#                                           parent=self,
215#                                           style = wx.PD_APP_MODAL | wx.PD_ELAPSED_TIME | wx.PD_REMAINING_TIME)# | wx.PD_AUTO_HIDE)
216            self.SetInitialSize(self.GetEffectiveMinSize())
217            self.CenterOnParent()
218            self.ShowModal()
219        if event.IsDone():
220            self.__state = "Finished"
221            self.Close()
222        if event.IsUpdate():
223            if "name" in event.GetFields():
224                self.SetTitle(self.__job.GetName())
225#            if "info" in event.GetFields():
226#                self.stInfo.SetLabel(self.__job.GetInfo())
227#            if "progress" in event.GetFields():
228#                self.gauge.SetValue(self.__job.GetProgress())
229            if "maxProgress" in event.GetFields():
230                maximum = self.__job.GetMaxProgress()
231                if maximum > 0:
232                    self.__maximum = maximum
233                    self.gauge.SetRange(maximum)
234
235            self.__Update(self.__job.GetProgress(),
236                          self.__job.GetInfo())
237
238