1 # -*- coding: latin-1; -*-
3 # PgWorksheet - PostgreSQL Front End
4 # http://pgworksheet.projects.postgresql.org/
6 # Copyright © 2004-2008 Henri Michelon & CML http://www.e-cml.org/
8 # This program is free software; you can redistribute it and/or
9 # modify it under the terms of the GNU General Public License
10 # as published by the Free Software Foundation; either version 2
11 # of the License, or (at your option) any later version.
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details (read LICENSE.txt).
18 # You should have received a copy of the GNU General Public License
19 # along with this program; if not, write to the Free Software
20 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 # $Id: UI.py,v 1.26 2008/03/12 20:26:23 hmichelon Exp $
33 PGW_CONNECT
= 'pgw-connect'
34 PGW_CONNECTNOW
= 'pgw-connectnow'
35 PGW_DISCONNECT
= 'pwg-disconnect'
36 PGW_SELECTALL
= 'pwg-selectall'
37 PGW_ENCODING
= 'pwg-encoding'
38 PGW_ABOUT
= 'pwg-about'
42 """UI Construction and management"""
44 def __init__(self
, app
, app_name
, app_version
, pixmap_path
):
45 self
.pixmap_path
= pixmap_path
46 self
.app_version
= app_version
47 self
.register_stock_items()
48 self
.file_dialog_path
= None # last used path
49 self
.file_dialog_filename
= None # last used filename
52 self
.wndmain
= gtk
.Window(gtk
.WINDOW_TOPLEVEL
)
53 self
.wndmain
.set_title(_('PgWorksheet - PostgreSQL SQL Tool'))
54 self
.wndmain
.set_icon_from_file(os
.path
.join(pixmap_path
,
55 "pgworksheet-32.png"))
56 self
.wndmain
.add_accel_group(self
.accelgroup
)
57 self
.wndmain
.set_default_size(640, 480)
58 self
.wndmain
.connect('window-state-event', self
.on_wndmain_state
)
59 self
.wndmain
.connect('configure-event', self
.on_wndmain_configure
)
60 self
.wndmain
.connect('destroy', app
.on_wndmain_destroy
)
61 self
.wndmain
.connect('delete_event', app
.on_wndmain_delete
)
63 hbox
= gtk
.VBox(False)
64 hbox
.pack_start(self
.uimanager
.get_widget('/MenuBar'), False)
65 hbox
.pack_start(self
.uimanager
.get_widget('/ToolBar'), False)
66 hbox
.pack_start(self
.vmain
, True, True)
67 hbox
.pack_start(self
.statusbar
, False, False)
68 self
.wndmain
.add(hbox
)
70 self
.load_user_parameters()
71 self
.wndmain
.show_all()
74 def load_user_parameters(self
):
75 cp
= ConfigParser
.ConfigParser()
77 cp
.readfp(open(pgw
.get_config_path(), 'r'))
80 maximized
= int(cp
.get("window", "maximized"))
84 self
.wndmain
.maximize()
86 width
, height
= self
.wndmain
.get_size()
88 width
= int(cp
.get("window", "width"))
92 height
= int(cp
.get("window", "height"))
95 self
.wndmain
.resize(width
, height
)
96 x
, y
= self
.wndmain
.get_position()
98 x
= int(cp
.get("window", "x"))
102 y
= int(cp
.get("window", "y"))
105 self
.wndmain
.move(x
, y
)
107 self
.vmain
.set_position(int(cp
.get("window", "divider")))
115 def message_dialog(self
, msg
, type, buttons
= gtk
.BUTTONS_OK
):
116 dialog
= gtk
.MessageDialog(self
.wndmain
,
117 gtk
.DIALOG_MODAL | gtk
.DIALOG_DESTROY_WITH_PARENT
,
119 result
= dialog
.run()
124 def message_box(self
, msg
):
125 self
.message_dialog(msg
, gtk
.MESSAGE_INFO
)
128 def error_box(self
, msg
):
129 self
.message_dialog(msg
, gtk
.MESSAGE_ERROR
)
132 def yesno_box(self
, msg
):
133 return self
.message_dialog(msg
, gtk
.MESSAGE_QUESTION
, gtk
.BUTTONS_YES_NO
)
136 def file_dialog(self
, msg
,
137 action
= gtk
.FILE_CHOOSER_ACTION_OPEN
,
138 button
= gtk
.STOCK_OPEN
):
139 fb
= gtk
.FileChooserDialog(msg
, self
.wndmain
,
141 (gtk
.STOCK_CANCEL
, gtk
.RESPONSE_CANCEL
,
142 button
, gtk
.RESPONSE_OK
))
143 if (self
.file_dialog_path
is not None):
144 fb
.set_current_folder_uri(self
.file_dialog_path
)
145 if (self
.file_dialog_filename
is not None):
146 fb
.set_filename(self
.file_dialog_filename
)
149 if (result
== gtk
.RESPONSE_OK
):
150 filename
= fb
.get_filename()
153 self
.file_dialog_path
= fb
.get_current_folder_uri()
154 self
.file_dialog_filename
= fb
.get_filename()
159 def register_stock_items(self
):
161 (PGW_CONNECT
, _('_Connect Server...'), gtk
.gdk
.CONTROL_MASK
,
162 gtk
.gdk
.keyval_from_name('N'), None),
163 (PGW_DISCONNECT
, _('_Disconnect'), 0, -1, None),
164 (PGW_SELECTALL
, _('Select _All'), gtk
.gdk
.CONTROL_MASK
,
165 gtk
.gdk
.keyval_from_name('A'), None),
166 (PGW_ENCODING
, _('Character _Encoding'), 0, -1, None),
167 (PGW_ABOUT
, _('_About...'), 0, -1, None),
168 (PGW_CONNECTNOW
, _('_Connect'), 0, -1, None),
170 self
.factory
= gtk
.IconFactory()
171 self
.factory
.add_default()
172 self
.factory
.add(PGW_CONNECTNOW
, gtk
.IconSet(gtk
.gdk
.pixbuf_new_from_file(
173 os
.path
.join(self
.pixmap_path
, "connect.png"))))
174 self
.factory
.add(PGW_CONNECT
, gtk
.IconSet(gtk
.gdk
.pixbuf_new_from_file(
175 os
.path
.join(self
.pixmap_path
, "connect.png"))))
176 self
.factory
.add(PGW_DISCONNECT
, gtk
.IconSet(gtk
.gdk
.pixbuf_new_from_file(
177 os
.path
.join(self
.pixmap_path
, "disconnect.png"))))
178 self
.factory
.add(PGW_ABOUT
, gtk
.IconSet(gtk
.gdk
.pixbuf_new_from_file(
179 os
.path
.join(self
.pixmap_path
, "about.png"))))
182 def define_ui(self
, app
):
184 <menubar name="MenuBar">
186 <menuitem action="Connect"/>
187 <menuitem action="Disconnect"/>
189 <menuitem action="Open SQL"/>
190 <menuitem action="Save SQL"/>
191 <menuitem action="Save Results"/>
192 <menuitem action="Save All Results"/>
194 <menuitem action="Quit"/>
197 <menuitem action="Undo"/>
198 <menuitem action="Redo"/>
200 <menuitem action="Cut"/>
201 <menuitem action="Copy"/>
202 <menuitem action="Paste"/>
204 <menuitem action="Select All"/>
206 <menu action="Tools">
207 <menuitem action="Run SQL"/>
209 <menu action="History">
210 <menuitem action="Prev Statement"/>
211 <menuitem action="Next Statement"/>
214 <menuitem action="About"/>
217 <toolbar name="ToolBar">
218 <toolitem action="Connect"/>
219 <toolitem action="Run SQL"/>
220 <toolitem action="Prev Statement"/>
221 <toolitem action="Next Statement"/>
223 <toolitem action="Open SQL"/>
224 <toolitem action="Save SQL"/>
226 <toolitem action="Cut"/>
227 <toolitem action="Copy"/>
228 <toolitem action="Paste"/>
230 <accelerator action="Run SQL 2"/>
231 <accelerator action="Run SQL 3"/>
234 self
.undo
= pgw
.Undo
.Undo()
235 self
.uimanager
= gtk
.UIManager()
236 self
.accelgroup
= self
.uimanager
.get_accel_group()
237 self
.actiongroup
= gtk
.ActionGroup('UIManagerMenuBar')
238 self
.actiongroup
.add_actions([
239 ('File', None, _('_File')),
240 ('Connect', PGW_CONNECT
, None, None,
241 _('Connect to a database'), app
.on_menu_connect
),
242 ('Disconnect', PGW_DISCONNECT
, None, '',
243 _('Disconnect from the database'), app
.on_menu_disconnect
),
244 ('Open SQL', gtk
.STOCK_OPEN
, _('_Open SQL queries...'), None,
245 _('Load SQL queries from a file'), app
.on_menu_opensql
),
246 ('Save SQL', gtk
.STOCK_SAVE
, _('_Save SQL queries...'), None,
247 _('Save SQL queries to a file'), app
.on_menu_savesql
),
248 ('Save Results', gtk
.STOCK_SAVE
, _('Save _Results...'), '<control>R',
249 _('Save the results to a file'), app
.on_menu_saveresults
),
250 ('Save All Results', gtk
.STOCK_SAVE
, _('Save _All Results...'),
252 _('Save all the results to a file'), app
.on_menu_saveallresults
),
253 ('Quit', gtk
.STOCK_QUIT
, None, None,
254 _('Quit the Program'), app
.on_wndmain_destroy
),
255 ('Edit', None, _('_Edit')),
256 ('Undo', gtk
.STOCK_UNDO
, None, '<control>Z',
257 _('Undo the last action'), lambda w
: self
.undo
.undo()),
258 ('Redo', gtk
.STOCK_REDO
, None, '<shift><control>Z',
259 _('Redo the last action'), lambda w
: self
.undo
.redo()),
260 ('Cut', gtk
.STOCK_CUT
, None, None,
261 _('Cut selection to the clipboard'), app
.on_menu_cut
),
262 ('Copy', gtk
.STOCK_COPY
, None, None,
263 _('Copy selection to the clipboard'), app
.on_menu_copy
),
264 ('Paste', gtk
.STOCK_PASTE
, None, None,
265 _('Paste the content of the clipboard'), app
.on_menu_paste
),
266 ('Select All', PGW_SELECTALL
, None, None,
267 _('Select all the text'), app
.on_menu_selectall
),
268 ('View', None, _('_View')),
269 ('Encoding', PGW_ENCODING
, None, None, _('Select the character \
270 encoding for display'), app
.on_menu_selectall
),
271 ('Tools', None, _('_Tools')),
272 ('Run SQL', gtk
.STOCK_EXECUTE
, None, "<control>Return",
273 _('Execute the content of the SQL buffer'), app
.on_menu_runsql
),
274 ('History', None, _('_History')),
275 ('Prev Statement', gtk
.STOCK_GO_BACK
, _('_Previous statements'),
276 "<control>Page_Down",
277 _('Go backward in the executed statements history'),
278 app
.on_menu_prevsql
),
279 ('Next Statement', gtk
.STOCK_GO_FORWARD
, _('_Next statements'),
281 _('Go forward in the executed statements history'),
282 app
.on_menu_nextsql
),
283 ('Help', None, _('_Help')),
284 ('About', PGW_ABOUT
, None, '',
285 _('More information about this application'), app
.on_menu_about
),
286 ('Run SQL 2', gtk
.STOCK_EXECUTE
, None, "F9", None, app
.on_menu_runsql
),
287 ('Run SQL 3', gtk
.STOCK_EXECUTE
, None, "F5", None, app
.on_menu_runsql
),
289 self
.uimanager
.insert_action_group(self
.actiongroup
, 0)
290 self
.uimanager
.add_ui_from_string(self
.ui
)
291 self
.uimanager
.get_widget('/MenuBar/Help').\
292 set_right_justified(True)
293 self
.enable_disconnect(False)
294 self
.enable_runsql(False)
295 self
.enable_prevsql(False)
296 self
.enable_nextsql(False)
297 self
.enable_saveresult(False)
298 self
.create_vpaned(app
)
299 self
.create_statusbar()
300 self
.uimanager
.get_widget('/ToolBar').set_style(gtk
.TOOLBAR_ICONS
)
303 def create_vpaned(self
, app
):
304 self
.vmain
= gtk
.VPaned()
305 self
.vmain
.connect("event", self
.on_vpaned_accept
)
306 scroll
= gtk
.ScrolledWindow()
307 scroll
.set_policy(gtk
.POLICY_AUTOMATIC
, gtk
.POLICY_AUTOMATIC
)
308 scroll
.set_property("height-request", 150)
309 scroll
.set_shadow_type(gtk
.SHADOW_NONE
)
310 self
.sqlbuffer
= gtk
.TextBuffer()
311 self
.sqlbuffer
.connect('delete-range', self
.undo
.text_deleted
)
312 self
.sqlbuffer
.connect('insert-text', self
.undo
.text_inserted
)
313 self
.syntax
= pgw
.Syntax
.Syntax(self
.sqlbuffer
)
314 self
.buffer_handlers
= []
315 self
.buffer_handlers
.append(self
.sqlbuffer
.connect('delete-range',
316 self
.syntax
.text_deleted
))
317 self
.buffer_handlers
.append(self
.sqlbuffer
.connect('insert-text',
318 self
.syntax
.text_inserted
))
319 self
.buffer_handlers
.append(self
.sqlbuffer
.connect('changed',
320 self
.syntax
.text_changed
))
321 self
.buffer_handlers
.append(self
.sqlbuffer
.connect('changed',
323 self
.sqlview
= gtk
.TextView(self
.sqlbuffer
)
324 self
.sqlview
.connect('focus-in-event', app
.on_sqlview_focus_in
)
325 self
.sqlview
.connect('focus-out-event', app
.on_sqlview_focus_out
)
326 self
.sqlview
.connect('key-press-event', app
.on_sqlview_keypress
)
327 scroll
.add(self
.sqlview
)
328 self
.vmain
.add1(scroll
)
329 self
.resulttab
= gtk
.Notebook()
330 self
.resulttab
.set_tab_pos(gtk
.POS_BOTTOM
)
331 self
.resulttab
.set_scrollable(True)
332 resultview
= gtk
.Viewport()
333 resultview
.set_shadow_type(gtk
.SHADOW_IN
)
334 resultview
.add(self
.resulttab
)
335 self
.vmain
.add2(resultview
)
338 def create_statusbar(self
):
339 self
.statusbar
= gtk
.Statusbar()
340 self
.statusbar
.set_border_width(0)
342 f
= self
.statusbar
.get_children()[0]
343 f
.set_shadow_type(gtk
.SHADOW_IN
)
344 self
.status_result
= f
.get_children()
345 self
.status_result
= self
.status_result
[0]
346 self
.statusbar
.set_child_packing(f
, True, True, 0, gtk
.PACK_START
)
348 self
.status_connect
= gtk
.Label();
349 self
.status_connect
.set_justify(gtk
.JUSTIFY_LEFT
)
351 f
.set_shadow_type(gtk
.SHADOW_IN
)
352 f
.add(self
.status_connect
)
353 self
.statusbar
.pack_start(f
, False, False)
355 self
.status_version
= gtk
.Label();
357 f
.set_shadow_type(gtk
.SHADOW_IN
)
358 f
.add(self
.status_version
)
359 self
.statusbar
.pack_start(f
, False, False)
362 self
.statusbar
.pack_start(f
, False, False)
365 def status(self
, connect
, version
):
366 """Update the status bar text"""
367 self
.status_connect
.set_markup(" " + connect
+ " ")
368 self
.status_version
.set_markup(" " + version
+ " ")
371 def setfocus_sqlbuffer(self
):
372 self
.sqlview
.grab_focus()
375 def enable_disconnect(self
, state
= True):
376 self
.uimanager
.get_widget('/MenuBar/File/Disconnect').\
380 def enable_saveresult(self
, state
= True):
381 self
.uimanager
.get_widget('/MenuBar/File/Save All Results').\
383 self
.uimanager
.get_widget('/MenuBar/File/Save Results').\
387 def enable_runsql(self
, state
= True):
388 self
.uimanager
.get_widget('/MenuBar/Tools/Run SQL').\
390 self
.uimanager
.get_widget('/ToolBar/Run SQL').\
394 def enable_cut(self
, state
= True):
395 self
.uimanager
.get_widget('/MenuBar/Edit/Cut').\
397 self
.uimanager
.get_widget('/ToolBar/Cut').\
401 def enable_copy(self
, state
= True):
402 self
.uimanager
.get_widget('/MenuBar/Edit/Copy').\
404 self
.uimanager
.get_widget('/ToolBar/Copy').\
408 def enable_selectall(self
, state
= True):
409 self
.uimanager
.get_widget('/MenuBar/Edit/Select All').\
413 def enable_paste(self
, state
= True):
414 self
.uimanager
.get_widget('/MenuBar/Edit/Paste').\
416 self
.uimanager
.get_widget('/ToolBar/Paste').\
420 def enable_prevsql(self
, state
= True):
421 self
.uimanager
.get_widget('/MenuBar/History/Prev Statement').\
423 self
.uimanager
.get_widget('/ToolBar/Prev Statement').\
427 def enable_nextsql(self
, state
= True):
428 self
.uimanager
.get_widget('/MenuBar/History/Next Statement').\
430 self
.uimanager
.get_widget('/ToolBar/Next Statement').\
434 def get_text(self
, buffer):
435 """Return the text of a widget"""
436 c1
= buffer.get_start_iter()
437 c2
= buffer.get_end_iter()
438 return buffer.get_slice(c1
, c2
, True)
441 def get_sqlbuffer_text(self
):
442 return self
.get_text(self
.sqlbuffer
)
445 def set_sqlbuffer_text(self
, text
):
446 self
.sqlbuffer
.set_text(text
)
449 def on_connect_event(self
, widget
, event
):
450 if ((not self
.entry_password
.is_focus()) and
451 self
.viewconn
.is_focus()):
452 self
.entry_password
.grab_focus()
455 def connect_dialog(self
, app
, host
, port
, user
, database
, overwrite_entry
):
456 dlg
= gtk
.Dialog(_('Database connection'),
458 gtk
.DIALOG_MODAL
or gtk
.DIALOG_DESTROY_WITH_PARENT
,
459 ((gtk
.STOCK_CANCEL
, gtk
.RESPONSE_CANCEL
,
460 PGW_CONNECTNOW
, gtk
.RESPONSE_OK
)))
461 dlg
.set_resizable(False)
465 self
.storeconn
= gtk
.ListStore(str, str)
466 self
.viewconn
= gtk
.TreeView(self
.storeconn
)
467 cell
= gtk
.CellRendererText()
468 column
= gtk
.TreeViewColumn(_('5 Previous connections'))
469 column
.pack_start(cell
, True)
470 column
.add_attribute(cell
, 'text', 0)
471 column
.set_sort_column_id(0)
472 self
.viewconn
.append_column(column
)
473 self
.viewconn
.connect('cursor-changed', app
.on_dlgconnect_change
)
474 box
.add(self
.viewconn
)
475 mbox
.pack_start(box
, True, True)
477 hbox
= gtk
.HBox(False)
478 hbox
.set_border_width(10)
483 lbl
= gtk
.Label(_('Host'))
484 lbl
.set_alignment(0, 0.1)
485 box
.pack_start(lbl
, True, True)
486 lbl
= gtk
.Label(_('Port'))
487 lbl
.set_alignment(0, 0.1)
488 box
.pack_start(lbl
, True, True)
489 lbl
= gtk
.Label(_('User'))
490 lbl
.set_alignment(0, 0.1)
491 box
.pack_start(lbl
, True, True)
492 lbl
= gtk
.Label(_('Password'))
493 lbl
.set_alignment(0, 0.1)
494 box
.pack_start(lbl
, True, True)
495 lbl
= gtk
.Label(_('Database'))
496 lbl
.set_alignment(0, 0.1)
497 box
.pack_start(lbl
, True, True)
498 hbox
.pack_start(box
, False, False)
500 box
= gtk
.VBox(False)
502 self
.entry_host
= gtk
.Entry()
503 self
.entry_host
.connect('activate', lambda w
: dlg
.response(gtk
.RESPONSE_OK
))
504 box
.pack_start(self
.entry_host
, True, True)
505 self
.entry_port
= gtk
.Entry()
506 self
.entry_port
.connect('activate', lambda w
: dlg
.response(gtk
.RESPONSE_OK
))
507 box
.pack_start(self
.entry_port
, True, True)
508 self
.entry_user
= gtk
.Entry()
509 self
.entry_user
.connect('activate', lambda w
: dlg
.response(gtk
.RESPONSE_OK
))
510 box
.pack_start(self
.entry_user
, True, True)
511 self
.entry_password
= gtk
.Entry()
512 self
.entry_password
.set_visibility(False)
513 self
.entry_password
.connect('activate', lambda w
: dlg
.response(gtk
.RESPONSE_OK
))
514 box
.pack_start(self
.entry_password
, True, True)
515 self
.entry_database
= gtk
.Entry()
516 self
.entry_database
.connect('activate', lambda w
: dlg
.response(gtk
.RESPONSE_OK
))
517 box
.pack_start(self
.entry_database
, True, True)
518 hbox
.pack_start(box
, True, True)
520 mbox
.pack_start(hbox
, True, True)
522 dlg
.vbox
.pack_start(mbox
, True, True, 0)
523 app
.on_dlgconnect_map(None)
524 if (overwrite_entry
or (not self
.storeconn
.iter_n_children(None))):
525 self
.entry_host
.set_text(host
)
526 self
.entry_port
.set_text(str(port
))
527 self
.entry_user
.set_text(user
)
528 self
.entry_database
.set_text(database
)
529 dlg
.set_default_response(gtk
.RESPONSE_OK
)
530 dlg
.connect('event-after', self
.on_connect_event
)
532 self
.entry_password
.grab_focus()
534 if (dlg
.run() == gtk
.RESPONSE_OK
):
535 result
= (self
.entry_host
.get_text(),
536 self
.entry_port
.get_text(),
537 self
.entry_user
.get_text(),
538 self
.entry_password
.get_text(),
539 self
.entry_database
.get_text())
544 def write_config(self
, cp
):
546 cp
.write(open(pgw
.get_config_path(), 'w'))
551 def on_vpaned_accept(self
, widget
, event
):
552 cp
= ConfigParser
.ConfigParser()
554 cp
.readfp(open(pgw
.get_config_path(), 'r'))
557 if (not cp
.has_section("window")):
558 cp
.add_section("window")
559 cp
.set("window", "divider", str(widget
.get_position()))
560 self
.write_config(cp
)
563 def on_wndmain_state(self
, widget
, event
):
564 cp
= ConfigParser
.ConfigParser()
566 cp
.readfp(open(pgw
.get_config_path(), 'r'))
569 if (not cp
.has_section("window")):
570 cp
.add_section("window")
571 if (event
.new_window_state
== gtk
.gdk
.WINDOW_STATE_MAXIMIZED
):
572 cp
.set("window", "maximized", "1")
574 cp
.set("window", "maximized", "0")
575 self
.write_config(cp
)
578 def on_wndmain_configure(self
, widget
, event
):
579 cp
= ConfigParser
.ConfigParser()
581 cp
.readfp(open(pgw
.get_config_path(), 'r'))
584 if (not cp
.has_section("window")):
585 cp
.add_section("window")
586 x
, y
= widget
.get_position()
587 cp
.set("window", "x", x
)
588 cp
.set("window", "y", y
)
589 width
, height
= widget
.get_size()
590 cp
.set("window", "width", width
)
591 cp
.set("window", "height", height
)
592 self
.write_config(cp
)
595 def about_dialog(self
):
596 dlg
= gtk
.Dialog(_('About PgWorksheet'),
598 gtk
.DIALOG_MODAL
or gtk
.DIALOG_DESTROY_WITH_PARENT
,
599 ((gtk
.STOCK_CLOSE
, gtk
.RESPONSE_CLOSE
)))
602 box
= gtk
.VBox(False)
606 <b>PgWorksheet - PostgreSQL Front End</b>
607 Version ''' + self
.app_version
+ '''
608 <u>http://pgworksheet.projects.postgresql.org/</u>
610 Copyright © 2004-2006, Henri Michelon and CML
611 <u>http://www.e-cml.org/</u>
613 lbl
.set_justify(gtk
.JUSTIFY_CENTER
)
614 lbl
.set_padding(10, 10)
615 box
.pack_start(lbl
, True)
618 <b>Internationalization:</b>
619 French : Henri Michelon <hmichelon@e-cml.org>
620 Japanese : Tadashi Jokagi <elf2000@users.sourceforge.net>
622 lbl
.set_padding(10, 0)
623 box
.pack_start(lbl
, True)
625 pix
.set_from_file(os
.path
.join(self
.pixmap_path
, "pgworksheet.png"))
626 pix
.set_padding(10, 10)
627 box
.pack_start(pix
, False)
628 nbk
.append_page(box
, gtk
.Label(_('About')))
630 txt
= gtk
.TextBuffer()
632 GNU GENERAL PUBLIC LICENSE
635 Copyright (C) 1989, 1991 Free Software Foundation, Inc.
636 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
637 Everyone is permitted to copy and distribute verbatim copies
638 of this license document, but changing it is not allowed.
642 The licenses for most software are designed to take away your
643 freedom to share and change it. By contrast, the GNU General Public
644 License is intended to guarantee your freedom to share and change free
645 software--to make sure the software is free for all its users. This
646 General Public License applies to most of the Free Software
647 Foundation's software and to any other program whose authors commit to
648 using it. (Some other Free Software Foundation software is covered by
649 the GNU Library General Public License instead.) You can apply it to
652 When we speak of free software, we are referring to freedom, not
653 price. Our General Public Licenses are designed to make sure that you
654 have the freedom to distribute copies of free software (and charge for
655 this service if you wish), that you receive source code or can get it
656 if you want it, that you can change the software or use pieces of it
657 in new free programs; and that you know you can do these things.
659 To protect your rights, we need to make restrictions that forbid
660 anyone to deny you these rights or to ask you to surrender the rights.
661 These restrictions translate to certain responsibilities for you if you
662 distribute copies of the software, or if you modify it.
664 For example, if you distribute copies of such a program, whether
665 gratis or for a fee, you must give the recipients all the rights that
666 you have. You must make sure that they, too, receive or can get the
667 source code. And you must show them these terms so they know their
670 We protect your rights with two steps: (1) copyright the software, and
671 (2) offer you this license which gives you legal permission to copy,
672 distribute and/or modify the software.
674 Also, for each author's protection and ours, we want to make certain
675 that everyone understands that there is no warranty for this free
676 software. If the software is modified by someone else and passed on, we
677 want its recipients to know that what they have is not the original, so
678 that any problems introduced by others will not reflect on the original
679 authors' reputations.
681 Finally, any free program is threatened constantly by software
682 patents. We wish to avoid the danger that redistributors of a free
683 program will individually obtain patent licenses, in effect making the
684 program proprietary. To prevent this, we have made it clear that any
685 patent must be licensed for everyone's free use or not licensed at all.
687 The precise terms and conditions for copying, distribution and
690 GNU GENERAL PUBLIC LICENSE
691 TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
693 0. This License applies to any program or other work which contains
694 a notice placed by the copyright holder saying it may be distributed
695 under the terms of this General Public License. The "Program", below,
696 refers to any such program or work, and a "work based on the Program"
697 means either the Program or any derivative work under copyright law:
698 that is to say, a work containing the Program or a portion of it,
699 either verbatim or with modifications and/or translated into another
700 language. (Hereinafter, translation is included without limitation in
701 the term "modification".) Each licensee is addressed as "you".
703 Activities other than copying, distribution and modification are not
704 covered by this License; they are outside its scope. The act of
705 running the Program is not restricted, and the output from the Program
706 is covered only if its contents constitute a work based on the
707 Program (independent of having been made by running the Program).
708 Whether that is true depends on what the Program does.
710 1. You may copy and distribute verbatim copies of the Program's
711 source code as you receive it, in any medium, provided that you
712 conspicuously and appropriately publish on each copy an appropriate
713 copyright notice and disclaimer of warranty; keep intact all the
714 notices that refer to this License and to the absence of any warranty;
715 and give any other recipients of the Program a copy of this License
716 along with the Program.
718 You may charge a fee for the physical act of transferring a copy, and
719 you may at your option offer warranty protection in exchange for a fee.
721 2. You may modify your copy or copies of the Program or any portion
722 of it, thus forming a work based on the Program, and copy and
723 distribute such modifications or work under the terms of Section 1
724 above, provided that you also meet all of these conditions:
726 a) You must cause the modified files to carry prominent notices
727 stating that you changed the files and the date of any change.
729 b) You must cause any work that you distribute or publish, that in
730 whole or in part contains or is derived from the Program or any
731 part thereof, to be licensed as a whole at no charge to all third
732 parties under the terms of this License.
734 c) If the modified program normally reads commands interactively
735 when run, you must cause it, when started running for such
736 interactive use in the most ordinary way, to print or display an
737 announcement including an appropriate copyright notice and a
738 notice that there is no warranty (or else, saying that you provide
739 a warranty) and that users may redistribute the program under
740 these conditions, and telling the user how to view a copy of this
741 License. (Exception: if the Program itself is interactive but
742 does not normally print such an announcement, your work based on
743 the Program is not required to print an announcement.)
745 These requirements apply to the modified work as a whole. If
746 identifiable sections of that work are not derived from the Program,
747 and can be reasonably considered independent and separate works in
748 themselves, then this License, and its terms, do not apply to those
749 sections when you distribute them as separate works. But when you
750 distribute the same sections as part of a whole which is a work based
751 on the Program, the distribution of the whole must be on the terms of
752 this License, whose permissions for other licensees extend to the
753 entire whole, and thus to each and every part regardless of who wrote it.
755 Thus, it is not the intent of this section to claim rights or contest
756 your rights to work written entirely by you; rather, the intent is to
757 exercise the right to control the distribution of derivative or
758 collective works based on the Program.
760 In addition, mere aggregation of another work not based on the Program
761 with the Program (or with a work based on the Program) on a volume of
762 a storage or distribution medium does not bring the other work under
763 the scope of this License.
765 3. You may copy and distribute the Program (or a work based on it,
766 under Section 2) in object code or executable form under the terms of
767 Sections 1 and 2 above provided that you also do one of the following:
769 a) Accompany it with the complete corresponding machine-readable
770 source code, which must be distributed under the terms of Sections
771 1 and 2 above on a medium customarily used for software interchange; or,
773 b) Accompany it with a written offer, valid for at least three
774 years, to give any third party, for a charge no more than your
775 cost of physically performing source distribution, a complete
776 machine-readable copy of the corresponding source code, to be
777 distributed under the terms of Sections 1 and 2 above on a medium
778 customarily used for software interchange; or,
780 c) Accompany it with the information you received as to the offer
781 to distribute corresponding source code. (This alternative is
782 allowed only for noncommercial distribution and only if you
783 received the program in object code or executable form with such
784 an offer, in accord with Subsection b above.)
786 The source code for a work means the preferred form of the work for
787 making modifications to it. For an executable work, complete source
788 code means all the source code for all modules it contains, plus any
789 associated interface definition files, plus the scripts used to
790 control compilation and installation of the executable. However, as a
791 special exception, the source code distributed need not include
792 anything that is normally distributed (in either source or binary
793 form) with the major components (compiler, kernel, and so on) of the
794 operating system on which the executable runs, unless that component
795 itself accompanies the executable.
797 If distribution of executable or object code is made by offering
798 access to copy from a designated place, then offering equivalent
799 access to copy the source code from the same place counts as
800 distribution of the source code, even though third parties are not
801 compelled to copy the source along with the object code.
803 4. You may not copy, modify, sublicense, or distribute the Program
804 except as expressly provided under this License. Any attempt
805 otherwise to copy, modify, sublicense or distribute the Program is
806 void, and will automatically terminate your rights under this License.
807 However, parties who have received copies, or rights, from you under
808 this License will not have their licenses terminated so long as such
809 parties remain in full compliance.
811 5. You are not required to accept this License, since you have not
812 signed it. However, nothing else grants you permission to modify or
813 distribute the Program or its derivative works. These actions are
814 prohibited by law if you do not accept this License. Therefore, by
815 modifying or distributing the Program (or any work based on the
816 Program), you indicate your acceptance of this License to do so, and
817 all its terms and conditions for copying, distributing or modifying
818 the Program or works based on it.
820 6. Each time you redistribute the Program (or any work based on the
821 Program), the recipient automatically receives a license from the
822 original licensor to copy, distribute or modify the Program subject to
823 these terms and conditions. You may not impose any further
824 restrictions on the recipients' exercise of the rights granted herein.
825 You are not responsible for enforcing compliance by third parties to
828 7. If, as a consequence of a court judgment or allegation of patent
829 infringement or for any other reason (not limited to patent issues),
830 conditions are imposed on you (whether by court order, agreement or
831 otherwise) that contradict the conditions of this License, they do not
832 excuse you from the conditions of this License. If you cannot
833 distribute so as to satisfy simultaneously your obligations under this
834 License and any other pertinent obligations, then as a consequence you
835 may not distribute the Program at all. For example, if a patent
836 license would not permit royalty-free redistribution of the Program by
837 all those who receive copies directly or indirectly through you, then
838 the only way you could satisfy both it and this License would be to
839 refrain entirely from distribution of the Program.
841 If any portion of this section is held invalid or unenforceable under
842 any particular circumstance, the balance of the section is intended to
843 apply and the section as a whole is intended to apply in other
846 It is not the purpose of this section to induce you to infringe any
847 patents or other property right claims or to contest validity of any
848 such claims; this section has the sole purpose of protecting the
849 integrity of the free software distribution system, which is
850 implemented by public license practices. Many people have made
851 generous contributions to the wide range of software distributed
852 through that system in reliance on consistent application of that
853 system; it is up to the author/donor to decide if he or she is willing
854 to distribute software through any other system and a licensee cannot
857 This section is intended to make thoroughly clear what is believed to
858 be a consequence of the rest of this License.
860 8. If the distribution and/or use of the Program is restricted in
861 certain countries either by patents or by copyrighted interfaces, the
862 original copyright holder who places the Program under this License
863 may add an explicit geographical distribution limitation excluding
864 those countries, so that distribution is permitted only in or among
865 countries not thus excluded. In such case, this License incorporates
866 the limitation as if written in the body of this License.
868 9. The Free Software Foundation may publish revised and/or new versions
869 of the General Public License from time to time. Such new versions will
870 be similar in spirit to the present version, but may differ in detail to
871 address new problems or concerns.
873 Each version is given a distinguishing version number. If the Program
874 specifies a version number of this License which applies to it and "any
875 later version", you have the option of following the terms and conditions
876 either of that version or of any later version published by the Free
877 Software Foundation. If the Program does not specify a version number of
878 this License, you may choose any version ever published by the Free Software
881 10. If you wish to incorporate parts of the Program into other free
882 programs whose distribution conditions are different, write to the author
883 to ask for permission. For software which is copyrighted by the Free
884 Software Foundation, write to the Free Software Foundation; we sometimes
885 make exceptions for this. Our decision will be guided by the two goals
886 of preserving the free status of all derivatives of our free software and
887 of promoting the sharing and reuse of software generally.
891 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
892 FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
893 OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
894 PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
895 OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
896 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
897 TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
898 PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
899 REPAIR OR CORRECTION.
901 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
902 WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
903 REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
904 INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
905 OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
906 TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
907 YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
908 PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
909 POSSIBILITY OF SUCH DAMAGES.
911 END OF TERMS AND CONDITIONS
913 How to Apply These Terms to Your New Programs
915 If you develop a new program, and you want it to be of the greatest
916 possible use to the public, the best way to achieve this is to make it
917 free software which everyone can redistribute and change under these terms.
919 To do so, attach the following notices to the program. It is safest
920 to attach them to the start of each source file to most effectively
921 convey the exclusion of warranty; and each file should have at least
922 the "copyright" line and a pointer to where the full notice is found.
924 <one line to give the program's name and a brief idea of what it does.>
925 Copyright (C) <year> <name of author>
927 This program is free software; you can redistribute it and/or modify
928 it under the terms of the GNU General Public License as published by
929 the Free Software Foundation; either version 2 of the License, or
930 (at your option) any later version.
932 This program is distributed in the hope that it will be useful,
933 but WITHOUT ANY WARRANTY; without even the implied warranty of
934 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
935 GNU General Public License for more details.
937 You should have received a copy of the GNU General Public License
938 along with this program; if not, write to the Free Software
939 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
942 Also add information on how to contact you by electronic and paper mail.
944 If the program is interactive, make it output a short notice like this
945 when it starts in an interactive mode:
947 Gnomovision version 69, Copyright (C) year name of author
948 Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
949 This is free software, and you are welcome to redistribute it
950 under certain conditions; type `show c' for details.
952 The hypothetical commands `show w' and `show c' should show the appropriate
953 parts of the General Public License. Of course, the commands you use may
954 be called something other than `show w' and `show c'; they could even be
955 mouse-clicks or menu items--whatever suits your program.
957 You should also get your employer (if you work as a programmer) or your
958 school, if any, to sign a "copyright disclaimer" for the program, if
959 necessary. Here is a sample; alter the names:
961 Yoyodyne, Inc., hereby disclaims all copyright interest in the program
962 `Gnomovision' (which makes passes at compilers) written by James Hacker.
964 <signature of Ty Coon>, 1 April 1989
965 Ty Coon, President of Vice
967 This General Public License does not permit incorporating your program into
968 proprietary programs. If your program is a subroutine library, you may
969 consider it more useful to permit linking proprietary applications with the
970 library. If this is what you want to do, use the GNU Library General
971 Public License instead of this License.
973 scroll
= gtk
.ScrolledWindow()
974 scroll
.add(gtk
.TextView(txt
))
975 nbk
.append_page(scroll
, gtk
.Label(_('License')))
977 dlg
.vbox
.pack_start(nbk
, True, True, 0)