Doing some minor lint cleanup
[multilist] / src / multilist_gtk.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 """
5 This file is part of Multilist.
6
7 Multilist is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 Multilist is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Multilist.  If not, see <http://www.gnu.org/licenses/>.
19
20 Copyright (C) 2008 Christoph Würstle
21 """
22
23 import os
24 import logging
25
26 import gtk
27
28 try:
29         import hildon
30         isHildon = True
31 except:
32         isHildon = False
33
34 try:
35         import osso
36 except ImportError:
37         osso = None
38
39 import constants
40 import hildonize
41
42 import libspeichern
43 import sqldialog
44 import libselection
45 import libview
46 import libliststorehandler
47 import libsync
48 import libbottombar
49
50 try:
51         _
52 except NameError:
53         _ = lambda x: x
54
55
56 _moduleLogger = logging.getLogger(__name__)
57 PROFILE_STARTUP = False
58
59
60 class Multilist(hildonize.get_app_class()):
61
62         _user_data = os.path.join(os.path.expanduser("~"), ".%s" % constants.__app_name__)
63         _user_settings = "%s/settings.ini" % _user_data
64
65         def __init__(self):
66                 super(Multilist, self).__init__()
67                 self._clipboard = gtk.clipboard_get()
68
69                 logging.info('Starting Multilist')
70
71                 try:
72                         os.makedirs(self._user_data)
73                 except OSError, e:
74                         if e.errno != 17:
75                                 raise
76
77                 self.db = libspeichern.Speichern()
78                 self.window_in_fullscreen = False #The window isn't in full screen mode initially.
79
80                 #Haupt vbox für alle Elemente
81                 self.window = gtk.Window()
82                 self.vbox = gtk.VBox(homogeneous = False, spacing = 0)
83
84                 self.selection = libselection.Selection(self.db, isHildon)
85                 self.liststorehandler = libliststorehandler.Liststorehandler(self.db, self.selection)
86                 self.view = libview.View(self.db, self.liststorehandler, self.window)
87                 self.bottombar = libbottombar.Bottombar(self.db, self.view, isHildon)
88
89                 #Menue
90                 if hildonize.GTK_MENU_USED:
91                         dateimenu = gtk.Menu()
92
93                         menu_items = gtk.MenuItem(_("Choose database file"))
94                         dateimenu.append(menu_items)
95                         menu_items.connect("activate", self.select_db_dialog, None)
96
97                         menu_items = gtk.MenuItem(_("SQL history"))
98                         dateimenu.append(menu_items)
99                         menu_items.connect("activate", self.view_sql_history, None)
100
101                         menu_items = gtk.MenuItem(_("SQL optimize"))
102                         dateimenu.append(menu_items)
103                         menu_items.connect("activate", self.optimizeSQL, None)
104
105                         menu_items = gtk.MenuItem(_("Sync items"))
106                         dateimenu.append(menu_items)
107                         menu_items.connect("activate", self.sync_notes, None)
108
109                         menu_items = gtk.MenuItem(_("Quit"))
110                         dateimenu.append(menu_items)
111                         menu_items.connect("activate", self.destroy, None)
112                         #menu_items.show()
113
114                         datei_menu = gtk.MenuItem(_("File"))
115                         datei_menu.show()
116                         datei_menu.set_submenu(dateimenu)
117
118                         toolsmenu = gtk.Menu()
119
120                         menu_items = gtk.MenuItem(_("Choose columns"))
121                         toolsmenu.append(menu_items)
122                         menu_items.connect("activate", self.show_columns_dialog, None)
123
124                         menu_items = gtk.MenuItem(_("Rename Category"))
125                         toolsmenu.append(menu_items)
126                         menu_items.connect("activate", self.bottombar.rename_category, None)
127
128                         menu_items = gtk.MenuItem(_("Rename List"))
129                         toolsmenu.append(menu_items)
130                         menu_items.connect("activate", self.bottombar.rename_list, None)
131
132                         tools_menu = gtk.MenuItem(_("Tools"))
133                         tools_menu.show()
134                         tools_menu.set_submenu(toolsmenu)
135
136                         hilfemenu = gtk.Menu()
137                         menu_items = gtk.MenuItem(_("About"))
138                         hilfemenu.append(menu_items)
139                         menu_items.connect("activate", self.show_about, None)
140
141                         hilfe_menu = gtk.MenuItem(_("Help"))
142                         hilfe_menu.show()
143                         hilfe_menu.set_submenu(hilfemenu)
144
145                         menu_bar = gtk.MenuBar()
146                         menu_bar.show()
147                         menu_bar.append (datei_menu)
148                         menu_bar.append (tools_menu)
149                         # unten -> damit als letztes menu_bar.append (hilfe_menu)
150                         #Als letztes menü
151                         menu_bar.append (hilfe_menu)
152
153                         self.vbox.pack_start(menu_bar, False, False, 0)
154                 else:
155                         menuBar = gtk.MenuBar()
156                         menuBar.show()
157                         self.vbox.pack_start(menuBar, False, False, 0)
158
159                 #add to vbox below (to get it on top)
160                 self.vbox.pack_end(self.bottombar, expand = False, fill = True, padding = 0)
161                 self.vbox.pack_end(self.view, expand = True, fill = True, padding = 0)
162                 self.vbox.pack_end(self.selection, expand = False, fill = True, padding = 0)
163
164                 #Get the Main Window, and connect the "destroy" event
165                 self.window.add(self.vbox)
166
167                 self.window = hildonize.hildonize_window(self, self.window)
168                 hildonize.set_application_title(self.window, "%s" % constants.__pretty_app_name__)
169                 menu_bar = hildonize.hildonize_menu(
170                         self.window,
171                         menu_bar,
172                 )
173                 if hildonize.IS_FREMANTLE_SUPPORTED:
174                         pass
175
176                 if not hildonize.IS_HILDON_SUPPORTED:
177                         _moduleLogger.info("No hildonization support")
178
179                 if osso is not None:
180                         self.osso_c = osso.Context(
181                                 constants.__app_name__,
182                                 constants.__version__,
183                                 False
184                         )
185                 else:
186                         _moduleLogger.info("No osso support")
187                         self._osso_c = None
188
189                 self.window.connect("delete_event", self.delete_event)
190                 self.window.connect("destroy", self.destroy)
191                 self.window.connect("key-press-event", self.on_key_press)
192                 self.window.connect("window-state-event", self.on_window_state_change)
193
194                 self.window.show_all()
195                 self.prepare_sync_dialog()
196                 self.ladeAlles()
197
198         def on_key_press(self, widget, event, *args):
199                 RETURN_TYPES = (gtk.keysyms.Return, gtk.keysyms.ISO_Enter, gtk.keysyms.KP_Enter)
200                 isCtrl = bool(event.get_state() & gtk.gdk.CONTROL_MASK)
201                 if (
202                         event.keyval == gtk.keysyms.F6 or
203                         event.keyval in RETURN_TYPES and isCtrl
204                 ):
205                         # The "Full screen" hardware key has been pressed 
206                         if self.window_in_fullscreen:
207                                 self.window.unfullscreen ()
208                         else:
209                                 self.window.fullscreen ()
210                         return True
211                 #elif event.keyval == gtk.keysyms.f and isCtrl:
212                 #       self._toggle_search()
213                 #       return True
214                 elif (
215                         event.keyval in (gtk.keysyms.w, gtk.keysyms.q) and
216                         event.get_state() & gtk.gdk.CONTROL_MASK
217                 ):
218                         self.window.destroy()
219                 elif event.keyval == gtk.keysyms.l and event.get_state() & gtk.gdk.CONTROL_MASK:
220                         with open(constants._user_logpath_, "r") as f:
221                                 logLines = f.xreadlines()
222                                 log = "".join(logLines)
223                                 self._clipboard.set_text(str(log))
224                         return True
225
226         def on_window_state_change(self, widget, event, *args):
227                 if event.new_window_state & gtk.gdk.WINDOW_STATE_FULLSCREEN:
228                         self.window_in_fullscreen = True
229                 else:
230                         self.window_in_fullscreen = False
231
232         def speichereAlles(self, data = None, data2 = None):
233                 logging.info("Speichere alles")
234
235         def ladeAlles(self, data = None, data2 = None):
236                 logging.info("Lade alles")
237
238         def beforeSync(self, data = None, data2 = None):
239                 logging.info("Lade alles")
240
241         def sync_finished(self, data = None, data2 = None):
242                 self.selection.comboList_changed()
243                 self.selection.comboCategory_changed()
244                 self.liststorehandler.update_list()
245
246         def prepare_sync_dialog(self):
247                 self.sync_dialog = gtk.Dialog(_("Sync"), None, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, (gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
248
249                 self.sync_dialog.set_position(gtk.WIN_POS_CENTER)
250                 sync = libsync.Sync(self.db, self.window, 50503)
251                 sync.connect("syncFinished", self.sync_finished)
252                 self.sync_dialog.vbox.pack_start(sync, True, True, 0)
253                 self.sync_dialog.set_size_request(500, 350)
254                 self.sync_dialog.vbox.show_all()
255                 sync.connect("syncFinished", self.sync_finished)
256
257         def sync_notes(self, widget = None, data = None):
258                 if self.sync_dialog == None:
259                         self.prepare_sync_dialog()
260                 self.sync_dialog.run()
261                 self.sync_dialog.hide()
262
263         def show_columns_dialog(self, widget = None, data = None):
264                 col_dialog = gtk.Dialog(_("Choose columns"), self.window, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
265
266                 col_dialog.set_position(gtk.WIN_POS_CENTER)
267                 cols = libview.Columns_dialog(self.db, self.liststorehandler)
268
269                 col_dialog.vbox.pack_start(cols, True, True, 0)
270                 col_dialog.set_size_request(500, 350)
271                 col_dialog.vbox.show_all()
272
273                 resp = col_dialog.run()
274                 col_dialog.hide()
275                 if resp == gtk.RESPONSE_ACCEPT:
276                         logging.info("changing columns")
277                         cols.save_column_setting()
278                         self.view.reload_view()
279                         #children = self.vbox.get_children()
280                         #while len(children)>1:
281                         #       self.vbox.remove(children[1])
282
283                         #self.vbox.pack_end(self.bottombar, expand = True, fill = True, padding = 0)
284                         #self.vbox.pack_end(view, expand = True, fill = True, padding = 0)
285                         #self.vbox.pack_end(self.selection, expand = False, fill = True, padding = 0)
286
287                 col_dialog.destroy()
288
289         def destroy(self, widget = None, data = None):
290                 try:
291                         self.speichereAlles()
292                         self.db.close()
293                         try:
294                                 self._osso_c.close()
295                         except AttributeError:
296                                 pass # Either None or close was removed (in Fremantle)
297                 finally:
298                         gtk.main_quit()
299
300         def delete_event(self, widget, event, data = None):
301                 #print "delete event occurred"
302                 return False
303
304         def dlg_delete(self, widget, event, data = None):
305                 return False
306
307         def show_about(self, widget = None, data = None):
308                 dialog = gtk.AboutDialog()
309                 dialog.set_position(gtk.WIN_POS_CENTER)
310                 dialog.set_name(constants.__pretty_app_name__)
311                 dialog.set_version(constants.__version__)
312                 dialog.set_copyright("")
313                 dialog.set_website("http://axique.de/f = Multilist")
314                 comments = "%s is a program to handle multiple lists." % constants.__pretty_app_name__
315                 dialog.set_comments(comments)
316                 dialog.set_authors(["Christoph Wurstle <n800@axique.net>", "Ed Page <eopage@byu.net> (Blame him for the most recent bugs)"])
317                 dialog.run()
318                 dialog.destroy()
319
320         def on_info1_activate(self, menuitem):
321                 self.show_about(menuitem)
322
323         def view_sql_history(self, widget = None, data = None, data2 = None):
324                 sqldiag = sqldialog.SqlDialog(self.db)
325                 res = sqldiag.run()
326                 sqldiag.hide()
327
328                 try:
329                         if res != gtk.RESPONSE_OK:
330                                 return
331                         logging.info("exporting sql")
332
333                         if not isHildon:
334                                 dlg = gtk.FileChooserDialog(
335                                         parent = self.window,
336                                         action = gtk.FILE_CHOOSER_ACTION_SAVE
337                                 )
338                                 dlg.add_button( gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
339                                 dlg.add_button( gtk.STOCK_OK, gtk.RESPONSE_OK)
340                         else:
341                                 dlg = hildon.FileChooserDialog(self.window, gtk.FILE_CHOOSER_ACTION_SAVE)
342
343                         dlg.set_title(_("Select SQL export file"))
344                         exportFileResponse = dlg.run()
345                         try:
346                                 if exportFileResponse == gtk.RESPONSE_OK:
347                                         fileName = dlg.get_filename()
348                                         sqldiag.exportSQL(fileName)
349                         finally:
350                                 dlg.destroy()
351                 finally:
352                         sqldiag.destroy()
353
354         def optimizeSQL(self, widget = None, data = None, data2 = None):
355                 #optimiere sql
356                 self.db.speichereSQL("VACUUM", log = False)
357
358         def select_db_dialog(self, widget = None, data = None, data2 = None):
359                 if (isHildon == False):
360                         dlg = gtk.FileChooserDialog(parent = self.window, action = gtk.FILE_CHOOSER_ACTION_SAVE)
361                         dlg.add_button( gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
362                         dlg.add_button( gtk.STOCK_OK, gtk.RESPONSE_OK)
363                 else:
364                         #dlg = hildon.FileChooserDialog(parent = self.window, action = gtk.FILE_CHOOSER_ACTION_SAVE)
365                         dlg = hildon.FileChooserDialog(self.window, gtk.FILE_CHOOSER_ACTION_SAVE)
366
367                 if self.db.ladeDirekt('datenbank'):
368                         dlg.set_filename(self.db.ladeDirekt('datenbank'))
369                 dlg.set_title(_("Choose your database file"))
370                 if dlg.run() == gtk.RESPONSE_OK:
371                         fileName = dlg.get_filename()
372                         self.db.speichereDirekt('datenbank', fileName)
373                         self.speichereAlles()
374                         self.db.openDB()
375                         self.ladeAlles()
376                 dlg.destroy()
377
378
379 def run_multilist():
380         if hildonize.IS_HILDON_SUPPORTED:
381                 gtk.set_application_name(constants.__pretty_app_name__)
382         app = Multilist()
383         if not PROFILE_STARTUP:
384                 gtk.main()
385
386
387 if __name__ == "__main__":
388         logging.basicConfig(level = logging.DEBUG)
389         run_multilist()