source: trunk/papywizard/controller/shootController.py @ 988

Revision 988, 12.6 KB checked in by fma, 5 years ago (diff)

Added name to shooting thread

  • Property svn:keywords set to Id
Line 
1# -*- coding: utf-8 -*-
2
3""" Panohead remote control.
4
5License
6=======
7
8 - B{papywizard} (U{http://trac.gbiloba.org/papywizard}) is Copyright:
9  - (C) 2007-2008 Frédéric Mantegazza
10
11This software is governed by the B{CeCILL} license under French law and
12abiding by the rules of distribution of free software.  You can  use,
13modify and/or redistribute the software under the terms of the CeCILL
14license as circulated by CEA, CNRS and INRIA at the following URL
15U{http://www.cecill.info}.
16
17As a counterpart to the access to the source code and  rights to copy,
18modify and redistribute granted by the license, users are provided only
19with a limited warranty  and the software's author,  the holder of the
20economic rights,  and the successive licensors  have only  limited
21liability.
22
23In this respect, the user's attention is drawn to the risks associated
24with loading,  using,  modifying and/or developing or reproducing the
25software by the user in light of its specific status of free software,
26that may mean  that it is complicated to manipulate,  and  that  also
27therefore means  that it is reserved for developers  and  experienced
28professionals having in-depth computer knowledge. Users are therefore
29encouraged to load and test the software's suitability as regards their
30requirements in conditions enabling the security of their systems and/or
31data to be ensured and,  more generally, to use and operate it in the
32same conditions as regards security.
33
34The fact that you are presently reading this means that you have had
35knowledge of the CeCILL license and that you accept its terms.
36
37Module purpose
38==============
39
40Graphical toolkit controller
41
42Implements
43==========
44
45- ShootController
46
47@author: Frédéric Mantegazza
48@copyright: (C) 2007-2008 Frédéric Mantegazza
49@license: CeCILL
50"""
51
52__revision__ = "$Id$"
53
54import os.path
55import time
56import threading
57
58import pygtk
59pygtk.require("2.0")
60import gtk
61import gobject
62
63from papywizard.common.loggingServices import Logger
64from papywizard.common.configManager import ConfigManager
65from papywizard.controller.abstractController import AbstractController
66from papywizard.controller.spy import Spy
67from papywizard.view.shootingArea import MosaicArea, PresetArea
68
69
70class ShootController(AbstractController):
71    """ Shoot controller object.
72    """
73    def _init(self):
74        self._gladeFile = "shootDialog.glade"
75        self._signalDict = {"on_manualShootCheckbutton_toggled": self.__onManualShootCheckbuttonToggled,
76                            "on_dataFileEnableCheckbutton_toggled": self.__onDataFileEnableCheckbuttonToggled,
77                            "on_startButton_clicked": self.__onStartButtonClicked,
78                            "on_pauseResumeButton_clicked": self.__onPauseResumeButtonClicked,
79                            "on_stopButton_clicked": self.__onStopButtonClicked,
80                            "on_doneButton_clicked": self.__onDoneButtonClicked,
81                        }
82
83        self.__keyPressedDict = {'Return': False,
84                                 'Escape': False
85                             }
86        self.__key = {'Return': gtk.keysyms.Return,
87                      'Escape': gtk.keysyms.Escape
88                      }
89
90    def _retreiveWidgets(self):
91        super(ShootController, self)._retreiveWidgets()
92
93        vbox = self.wTree.get_widget("vbox")
94        drawingarea = self.wTree.get_widget("drawingarea")
95        drawingarea.destroy()
96        if self._model.mode == 'mosaic':
97            self.shootingArea = MosaicArea()
98        else:
99            self.shootingArea = PresetArea()
100        vbox.pack_start(self.shootingArea)
101        vbox.reorder_child(self.shootingArea, 0)
102        if self._model.mode == 'mosaic':
103
104            # todo: give args in shootingArea.__init__()
105            self.shootingArea.init(self._model.mosaic.yawStart, self._model.mosaic.yawEnd,
106                                   self._model.mosaic.pitchStart, self._model.mosaic.pitchEnd,
107                                   self._model.mosaic.yawFov, self._model.mosaic.pitchFov,
108                                   self._model.camera.getYawFov(self._model.cameraOrientation),
109                                   self._model.camera.getPitchFov(self._model.cameraOrientation),
110                                   self._model.mosaic.yawRealOverlap, self._model.mosaic.pitchRealOverlap)
111        else:
112            self.shootingArea.init(440., 220., # visible fov
113                                    16.,  16.) # camera fov
114        self.shootingArea.show()
115        self.progressbar = self.wTree.get_widget("progressbar")
116        self.manualShootCheckbutton = self.wTree.get_widget("manualShootCheckbutton")
117        self.dataFileEnableCheckbutton = self.wTree.get_widget("dataFileEnableCheckbutton")
118        self.startButton = self.wTree.get_widget("startButton")
119        self.pauseResumeButton = self.wTree.get_widget("pauseResumeButton")
120        self.pauseResumeLabel = self.wTree.get_widget("pauseResumeLabel")
121        self.stopButton = self.wTree.get_widget("stopButton")
122        self.doneButton = self.wTree.get_widget("doneButton")
123
124        self.pauseResumeButton.set_sensitive(False)
125        self.stopButton.set_sensitive(False)
126
127    def _connectSignals(self):
128        super(ShootController, self)._connectSignals()
129
130        self.dialog.connect("key-press-event", self.__onKeyPressed)
131        self.dialog.connect("key-release-event", self.__onKeyReleased)
132        self.dialog.connect("delete-event", self.__onDelete)
133
134        self._model.newPictSignal.connect(self.__addPicture)
135
136    # Callbacks
137    def __onDelete(self, widget, event):
138        Logger().trace("ShootController.__onDelete()")
139        self.__stopShooting()
140
141    def __onKeyPressed(self, widget, event, *args):
142
143        # 'Return' key
144        if event.keyval == self.__key['Return']:
145            if not self.__keyPressedDict['Return']:
146                Logger().debug("shootController.__onKeyPressed(): 'Return' key pressed")
147                self.__keyPressedDict['Return'] = True
148
149                # Pressing 'Return' while not shooting starts shooting
150                if not self._model.isShooting():
151                    Logger().debug("shootController.__onKeyPressed(): start shooting")
152                    self.__startShooting()
153
154                # Pressing 'Return' while shooting...
155                else:
156
157                    # ...and not paused pauses shooting
158                    if not self._model.isPaused():
159                        Logger().debug("shootController.__onKeyPressed(): pause shooting")
160                        self.__pauseShooting()
161
162                    #... and paused resumes shooting
163                    else:
164                        Logger().debug("shootController.__onKeyPressed(): resume shooting")
165                        self.__resumeShooting()
166                return True
167
168        # 'Escape' key
169        elif event.keyval == self.__key['Escape']:
170           if not self.__keyPressedDict['Escape']:
171               Logger().debug("shootController.__onKeyPressed(): 'Escape' key pressed")
172               self.__keyPressedDict['Escape'] = True
173
174               # Pressing 'Escape' while not shooting exit shoot dialog
175               if not self._model.isShooting():
176                   Logger().debug("shootController.__onKeyPressed(): close shooting dialog")
177                   self.dialog.response(0)
178
179               # Pressing 'Escape' while shooting stops shooting
180               else:
181                   Logger().debug("shootController.__onKeyPressed(): stop shooting")
182                   self.__stopShooting()
183               return True
184
185        else:
186            Logger().warning("MainController.__onKeyPressed(): unbind '%s' key" % event.keyval)
187
188    def __onKeyReleased(self, widget, event, *args):
189
190        # 'Return' key
191        if event.keyval == self.__key['Return']:
192            if self.__keyPressedDict['Return']:
193                Logger().debug("MainController.__onKeyReleased(): 'Return' key released")
194                self.__keyPressedDict['Return'] = False
195            return True
196
197        # 'Escape' key
198        if event.keyval == self.__key['Escape']:
199            if self.__keyPressedDict['Escape']:
200                Logger().debug("MainController.__onKeyReleased(): 'Escape' key released")
201                self.__keyPressedDict['Escape'] = False
202            return True
203
204        else:
205            Logger().warning("MainController.__onKeyReleased(): unbind '%s' key" % event.keyval)
206
207    def __onManualShootCheckbuttonToggled(self, widget):
208        Logger().trace("ShootController.____onManualShootCheckbuttonToggled()")
209        switch = self.manualShootCheckbutton.get_active()
210        self._model.setManualShoot(switch)
211
212    def __onDataFileEnableCheckbuttonToggled(self, widget):
213        Logger().trace("ShootController.__onDataFileEnableCheckbuttonToggled()")
214        switch = self.dataFileEnableCheckbutton.get_active()
215        ConfigManager().setBoolean('Data', 'DATA_FILE_ENABLE', self.dataFileEnableCheckbutton.get_active())
216
217    def __onStartButtonClicked(self, widget):
218        Logger().trace("ShootController.__startButtonClicked()")
219        self.__startShooting()
220
221    def __onPauseResumeButtonClicked(self, widget):
222        Logger().trace("ShootController.__pauseResumeButtonClicked()")
223        if self._model.isShooting(): # Should always be true here, but...
224            if not self._model.isPaused():
225                self.__pauseShooting()
226            else:
227                self.__resumeShooting()
228
229    def __onStopButtonClicked(self, widget):
230        Logger().trace("ShootController.__stopButtonClicked()")
231        self.__stopShooting()
232
233    def __onDoneButtonClicked(self, widget):
234        Logger().trace("ShootController.__onDoneButtonClicked()")
235        self.dialog.response(0)
236
237    def __addPicture(self, yaw, pitch, status):
238        Logger().trace("ShootController.__addPicture()")
239        self.shootingArea.add_pict(yaw, pitch, status)
240
241    # Real work
242    def __startShooting(self):
243        def monitorShooting():
244            Logger().trace("ShootController.__startShooting().monitorShooting()")
245
246            # Check if model paused (manual shoot mode)
247            if self._model.isPaused():
248                self.pauseResumeLabel.set_text(_("Resume"))
249            else:
250                self.pauseResumeLabel.set_text(_("Pause"))
251
252            # Check end of shooting
253            if not self._model.isShooting():
254                Logger().debug("monitorShooting(): model not shooting anymore")
255
256                # Check status
257                #if self._model.error:
258                    #messageDialog = gtk.MessageDialog(flags=gtk.DIALOG_MODAL, type=gtk.MESSAGE_ERROR, buttons=gtk.BUTTONS_CLOSE,
259                                                      #message_format="Internal error while shooting")
260                    #messageDialog.format_secondary_text("Please report bug (include logs)")
261                    #messageDialog.run()
262                    #messageDialog.destroy()
263
264                self.dataFileEnableCheckbutton.set_sensitive(True)
265                self.startButton.set_sensitive(True)
266                self.pauseResumeLabel.set_text(_("Pause"))
267                self.pauseResumeButton.set_sensitive(False)
268                self.stopButton.set_sensitive(False)
269                self.doneButton.set_sensitive(True)
270                self.refreshView()
271                thread.join()
272                Logger().debug("ShootController.__startShooting().monitorShooting(): model thread over")
273
274                return False # Stop execution by Gtk timeout
275
276            self.refreshView() # Can conflict with Spy?
277
278            return True
279
280        self.shootingArea.clear()
281        self.dataFileEnableCheckbutton.set_sensitive(False)
282        self.startButton.set_sensitive(False)
283        self.pauseResumeButton.set_sensitive(True)
284        self.stopButton.set_sensitive(True)
285        self.doneButton.set_sensitive(False)
286
287        thread = threading.Thread(target=self._model.start, name="Shooting")
288        thread.start()
289        #self._model.startEvent.wait() # Does not work under Nokia
290        time.sleep(0.2)
291
292        # Monitor shooting process
293        gobject.timeout_add(200, monitorShooting)
294
295    def __pauseShooting(self):
296        self._model.pause()
297        #self.pauseResumeLabel.set_text(_("Resume"))
298
299    def __resumeShooting(self):
300        self._model.resume()
301        #self.pauseResumeLabel.set_text(_("Pause"))
302
303    def __stopShooting(self):
304        self._model.stop()
305
306        # Wait for shooting really stops
307        # todo: use condition
308        while self._model.isShooting():
309            time.sleep(0.1)
310
311    def refreshView(self):
312        self.progressbar.set_fraction(self._model.progress)
313        self.progressbar.set_text(self._model.sequence)
314        self.dataFileEnableCheckbutton.set_active(ConfigManager().getBoolean('Data', 'DATA_FILE_ENABLE'))
Note: See TracBrowser for help on using the repository browser.