Just remembered another task
[doneit] / src / doneit_glade.py
1 #!/usr/bin/python
2
3
4 from __future__ import with_statement
5
6
7 import sys
8 import gc
9 import os
10 import threading
11 import warnings
12
13 import gtk
14 import gtk.glade
15
16 try:
17         import hildon
18 except ImportError:
19         hildon = None
20
21 import gtk_toolbox
22
23
24 class DoneIt(object):
25
26         __pretty_app_name__ = "DoneIt"
27         __app_name__ = "doneit"
28         __version__ = "0.3.0"
29         __app_magic__ = 0xdeadbeef
30
31         _glade_files = [
32                 '/usr/lib/doneit/doneit.glade',
33                 os.path.join(os.path.dirname(__file__), "doneit.glade"),
34                 os.path.join(os.path.dirname(__file__), "../lib/doneit.glade"),
35         ]
36
37         _user_data = os.path.expanduser("~/.%s/" % __app_name__)
38         _user_settings = "%s/settings.ini" % _user_data
39
40         def __init__(self):
41                 self._todoUIs = []
42                 self._todoUI = None
43                 self._osso = None
44                 self._deviceIsOnline = True
45                 self._connection = None
46
47                 for path in self._glade_files:
48                         if os.path.isfile(path):
49                                 self._widgetTree = gtk.glade.XML(path)
50                                 break
51                 else:
52                         self.display_error_message("Cannot find doneit.glade")
53                         gtk.main_quit()
54                 try:
55                         os.makedirs(self._user_data)
56                 except OSError, e:
57                         if e.errno != 17:
58                                 raise
59
60                 self._clipboard = gtk.clipboard_get()
61                 self.__window = self._widgetTree.get_widget("mainWindow")
62                 self.__errorDisplay = gtk_toolbox.ErrorDisplay(self._widgetTree)
63
64                 self._app = None
65                 self._isFullScreen = False
66                 if hildon is not None:
67                         self._app = hildon.Program()
68                         self.__window = hildon.Window()
69                         self._widgetTree.get_widget("mainLayout").reparent(self.__window)
70                         self._app.add_window(self.__window)
71                         self._widgetTree.get_widget("usernameentry").set_property('hildon-input-mode', 7)
72                         self._widgetTree.get_widget("passwordentry").set_property('hildon-input-mode', 7|(1 << 29))
73                         self._widgetTree.get_widget("projectsCombo").get_child().set_property('hildon-input-mode', (1 << 4))
74
75                         gtkMenu = self._widgetTree.get_widget("mainMenubar")
76                         menu = gtk.Menu()
77                         for child in gtkMenu.get_children():
78                                 child.reparent(menu)
79                         self.__window.set_menu(menu)
80                         gtkMenu.destroy()
81
82                         self.__window.connect("key-press-event", self._on_key_press)
83                         self.__window.connect("window-state-event", self._on_window_state_change)
84                 else:
85                         pass # warnings.warn("No Hildon", UserWarning, 2)
86
87                 callbackMapping = {
88                         "on_doneit_quit": self._on_close,
89                         "on_paste": self._on_paste,
90                         "on_about": self._on_about_activate,
91                 }
92                 self._widgetTree.signal_autoconnect(callbackMapping)
93
94                 if self.__window:
95                         if hildon is None:
96                                 self.__window.set_title("%s" % self.__pretty_app_name__)
97                         self.__window.connect("destroy", self._on_close)
98                         self.__window.show_all()
99
100                 backgroundSetup = threading.Thread(target=self._idle_setup)
101                 backgroundSetup.setDaemon(True)
102                 backgroundSetup.start()
103
104         def _idle_setup(self):
105                 # Barebones UI handlers
106                 import gtk_null
107                 gtk.gdk.threads_enter()
108                 try:
109                         self._todoUIs = [
110                                 gtk_null.GtkNull(self._widgetTree),
111                         ]
112                 finally:
113                         gtk.gdk.threads_leave()
114
115                 # Setup maemo specifics
116                 try:
117                         import osso
118                 except ImportError:
119                         osso = None
120                 self._osso = None
121                 if osso is not None:
122                         self._osso = osso.Context(DoneIt.__app_name__, DoneIt.__version__, False)
123                         device = osso.DeviceState(self._osso)
124                         device.set_device_state_callback(self._on_device_state_change, 0)
125                 else:
126                         pass # warnings.warn("No OSSO", UserWarning, 2)
127
128                 try:
129                         import conic
130                 except ImportError:
131                         conic = None
132                 self._connection = None
133                 if conic is not None:
134                         self._connection = conic.Connection()
135                         self._connection.connect("connection-event", self._on_connection_change, self.__app_magic__)
136                         self._connection.request_connection(conic.CONNECT_FLAG_NONE)
137                 else:
138                         pass # warnings.warn("No Internet Connectivity API ", UserWarning)
139
140                 # Setup costly backends
141                 import gtk_rtmilk
142                 gtk.gdk.threads_enter()
143                 try:
144                         self._todoUIs.extend([
145                                 gtk_rtmilk.GtkRtMilk(self._widgetTree),
146                         ])
147                         self._todoUI = self._todoUIs[1]
148                         self._todoUI.enable()
149                 finally:
150                         gtk.gdk.threads_leave()
151
152         def display_error_message(self, msg):
153                 error_dialog = gtk.MessageDialog(None, 0, gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE, msg)
154
155                 def close(dialog, response, editor):
156                         editor.about_dialog = None
157                         dialog.destroy()
158                 error_dialog.connect("response", close, self)
159                 error_dialog.run()
160
161         def _on_device_state_change(self, shutdown, save_unsaved_data, memory_low, system_inactivity, message, userData):
162                 """
163                 For system_inactivity, we have no background tasks to pause
164
165                 @note Hildon specific
166                 """
167                 if memory_low:
168                         gc.collect()
169
170                 if save_unsaved_data or shutdown:
171                         pass
172
173         def _on_connection_change(self, connection, event, magicIdentifier):
174                 """
175                 @note Hildon specific
176                 """
177                 import conic
178
179                 status = event.get_status()
180                 error = event.get_error()
181                 iap_id = event.get_iap_id()
182                 bearer = event.get_bearer_type()
183
184                 if status == conic.STATUS_CONNECTED:
185                         self._deviceIsOnline = True
186                 elif status == conic.STATUS_DISCONNECTED:
187                         self._deviceIsOnline = False
188
189         def _on_window_state_change(self, widget, event, *args):
190                 """
191                 @note Hildon specific
192                 """
193                 if event.new_window_state & gtk.gdk.WINDOW_STATE_FULLSCREEN:
194                         self._isFullScreen = True
195                 else:
196                         self._isFullScreen = False
197
198         def _on_close(self, *args, **kwds):
199                 if self._osso is not None:
200                         self._osso.close()
201
202                 try:
203                         pass
204                 finally:
205                         gtk.main_quit()
206
207         def _on_paste(self, *args):
208                 pass
209
210         def _on_key_press(self, widget, event, *args):
211                 """
212                 @note Hildon specific
213                 """
214                 if event.keyval == gtk.keysyms.F6:
215                         if self._isFullScreen:
216                                 self.__window.unfullscreen()
217                         else:
218                                 self.__window.fullscreen()
219
220         def _on_about_activate(self, *args):
221                 dlg = gtk.AboutDialog()
222                 dlg.set_name(self.__pretty_app_name__)
223                 dlg.set_version(self.__version__)
224                 dlg.set_copyright("Copyright 2008 - LGPL")
225                 dlg.set_comments("")
226                 dlg.set_website("")
227                 dlg.set_authors([""])
228                 dlg.run()
229                 dlg.destroy()
230
231
232 def run_doctest():
233         import doctest
234
235         failureCount, testCount = doctest.testmod()
236         if not failureCount:
237                 print "Tests Successful"
238                 sys.exit(0)
239         else:
240                 sys.exit(1)
241
242
243 def run_doneit():
244         gtk.gdk.threads_init()
245
246         if hildon is not None:
247                 gtk.set_application_name(DoneIt.__pretty_app_name__)
248         handle = DoneIt()
249         gtk.main()
250
251
252 class DummyOptions(object):
253
254         def __init__(self):
255                 self.test = False
256
257
258 if __name__ == "__main__":
259         if len(sys.argv) > 1:
260                 try:
261                         import optparse
262                 except ImportError:
263                         optparse = None
264
265                 if optparse is not None:
266                         parser = optparse.OptionParser()
267                         parser.add_option("-t", "--test", action="store_true", dest="test", help="Run tests")
268                         (commandOptions, commandArgs) = parser.parse_args()
269         else:
270                 commandOptions = DummyOptions()
271                 commandArgs = []
272
273         if commandOptions.test:
274                 run_doctest()
275         else:
276                 run_doneit()