7 from notebook
import Notebook
8 from shell_buffer
import ShellBuffer
9 from shell_view
import ShellView
11 from format_escaped
import format_escaped
12 from optparse
import OptionParser
14 usage
= "usage: %prog [options]"
15 op
= OptionParser(usage
=usage
)
16 op
.add_option("-u", "--ui", type="choice", choices
=("standard", "hildon"),
17 default
="standard", help=("which user interface to use (standard or "
18 "hildon), default=%default"))
20 options
, args
= op
.parse_args()
23 if options
.ui
== "hildon":
27 except ImportError, e
:
28 print "Error importing hildon. Falling back to standard ui."
40 buf
= ShellBuffer(notebook
)
42 view
.modify_font(pango
.FontDescription("monospace"))
43 buf
= view
.get_buffer()
45 ui_manager
= gtk
.UIManager()
46 w
.add_accel_group(ui_manager
.get_accel_group())
49 if not confirm_discard('Save the unchanged changes to worksheet "%s" before quitting?', '_Quit without saving'):
57 view
.emit('cut-clipboard')
60 view
.emit('copy-clipboard')
62 def on_copy_as_doctests(action
):
63 view
.get_buffer().copy_as_doctests(view
.get_clipboard(gtk
.gdk
.SELECTION_CLIPBOARD
))
66 view
.emit('paste-clipboard')
68 def on_delete(action
):
69 buf
.delete_selection(True, view
.get_editable())
71 def confirm_discard(message_format
, continue_button_text
):
72 if not buf
.code_modified
:
75 if buf
.filename
== None:
76 save_button_text
= gtk
.STOCK_SAVE_AS
78 save_button_text
= gtk
.STOCK_SAVE
80 if buf
.filename
== None:
81 name
= "Unsaved Worksheet"
85 message
= format_escaped("<big><b>" + message_format
+ "</b></big>", name
)
87 dialog
= gtk
.MessageDialog(parent
=w
, buttons
=gtk
.BUTTONS_NONE
,
88 type=gtk
.MESSAGE_WARNING
)
89 dialog
.set_markup(message
)
91 dialog
.add_buttons(continue_button_text
, gtk
.RESPONSE_OK
,
92 gtk
.STOCK_CANCEL
, gtk
.RESPONSE_CANCEL
,
94 dialog
.set_default_response(1)
95 response
= dialog
.run()
98 if response
== gtk
.RESPONSE_OK
:
101 if buf
.filename
== None:
106 if buf
.code_modified
:
114 if not confirm_discard('Discard unsaved changes to worksheet "%s"?', '_Discard'):
120 notebook
.set_path([os
.path
.dirname(os
.path
.abspath(filename
))])
126 if not confirm_discard('Discard unsaved changes to worksheet "%s"?', '_Discard'):
130 chooser
= hildon
.FileChooserDialog(w
, gtk
.FILE_CHOOSER_ACTION_OPEN
)
132 chooser
= gtk
.FileChooserDialog("Open Worksheet...", w
, gtk
.FILE_CHOOSER_ACTION_OPEN
,
133 (gtk
.STOCK_CANCEL
, gtk
.RESPONSE_CANCEL
,
134 gtk
.STOCK_OPEN
, gtk
.RESPONSE_OK
))
135 chooser
.set_default_response(gtk
.RESPONSE_OK
)
136 response
= chooser
.run()
138 if response
== gtk
.RESPONSE_OK
:
139 filename
= chooser
.get_filename()
147 if buf
.filename
== None:
154 chooser
= hildon
.FileChooserDialog(w
, gtk
.FILE_CHOOSER_ACTION_SAVE
)
156 chooser
= gtk
.FileChooserDialog("Save As...", w
, gtk
.FILE_CHOOSER_ACTION_SAVE
,
157 (gtk
.STOCK_CANCEL
, gtk
.RESPONSE_CANCEL
,
158 gtk
.STOCK_SAVE
, gtk
.RESPONSE_OK
))
159 chooser
.set_default_response(gtk
.RESPONSE_OK
)
160 response
= chooser
.run()
162 if response
== gtk
.RESPONSE_OK
:
163 filename
= chooser
.get_filename()
167 notebook
.set_path([os
.path
.dirname(os
.path
.abspath(filename
))])
171 def on_save_as(action
):
177 # This is a hack to work around the fact that scroll_mark_onscreen()
178 # doesn't wait for a size-allocate cycle, so doesn't properly handle
179 # embedded request widgets
180 w
, h
= view
.size_request()
181 view
.size_allocate((view
.allocation
.x
, view
.allocation
.y
, w
, h
))
183 view
.scroll_mark_onscreen(buf
.get_insert())
185 def on_calculate(action
):
188 action_group
= gtk
.ActionGroup("main")
189 action_group
.add_actions([
190 ('file', None, "_File"),
191 ('edit', None, "_Edit"),
192 ('new', gtk
.STOCK_NEW
, None, None, None, on_new
),
193 ('open', gtk
.STOCK_OPEN
, None, None, None, on_open
),
194 ('save', gtk
.STOCK_SAVE
, None, None, None, on_save
),
195 ('save-as', gtk
.STOCK_SAVE_AS
, None, None, None, on_save_as
),
196 ('quit', gtk
.STOCK_QUIT
, None, None, None, on_quit
),
197 ('cut', gtk
.STOCK_CUT
, None, None, None, on_cut
),
198 ('copy', gtk
.STOCK_COPY
, None, None, None, on_copy
),
204 on_copy_as_doctests
),
205 ('paste', gtk
.STOCK_PASTE
, None, None, None, on_paste
),
206 ('delete', gtk
.STOCK_DELETE
, None, None, None, on_delete
),
207 ('calculate', gtk
.STOCK_REFRESH
, "_Calculate", '<control>Return', None, on_calculate
),
210 ui_manager
.insert_action_group(action_group
, 0)
213 menu_element
= 'popup'
215 menu_element
= 'menubar'
219 <%(menu_element)s name="TopMenu">
221 <menuitem action="new"/>
222 <menuitem action="open"/>
224 <menuitem action="save"/>
225 <menuitem action="save-as"/>
227 <menuitem action="quit"/>
230 <menuitem action="cut"/>
231 <menuitem action="copy"/>
232 <menuitem action="copy-as-doctests"/>
233 <menuitem action="paste"/>
234 <menuitem action="delete"/>
236 <menuitem action="calculate"/>
239 <toolbar name="ToolBar">
240 <toolitem action="calculate"/>
243 """ % { 'menu_element': menu_element
}
245 ui_manager
.add_ui_from_string(ui_string
)
246 ui_manager
.ensure_update()
248 menu
= ui_manager
.get_widget("/TopMenu")
249 toolbar
= ui_manager
.get_widget("/ToolBar")
253 w
.add_toolbar(toolbar
)
255 v
.pack_start(menu
, expand
=False, fill
=False)
256 v
.pack_start(toolbar
, expand
=False, fill
=False)
258 sw
= gtk
.ScrolledWindow()
259 sw
.set_policy(gtk
.POLICY_AUTOMATIC
, gtk
.POLICY_AUTOMATIC
)
260 v
.pack_start(sw
, expand
=True, fill
=True)
264 w
.set_default_size(700, 800)
269 def update_title(*args
):
270 if buf
.code_modified
:
275 if buf
.filename
== None:
276 title
+= "Unsaved Worksheet"
278 title
+= os
.path
.basename(buf
.filename
)
280 title
+= " - Reinteract"
284 buf
.connect('filename-changed', update_title
)
285 buf
.connect('code-modified-changed', update_title
)
289 # We have a <Control>Return accelerator, but this hooks up <Control>KP_Enter as well;
290 # maybe someone wants that
291 def on_key_press_event(window
, event
):
292 if (event
.keyval
== 0xff0d or event
.keyval
== 0xff8d) and (event
.state
& gtk
.gdk
.CONTROL_MASK
!= 0):
297 w
.connect('key-press-event', on_key_press_event
)
302 # If you run reinteract from the command line, you'd expect to be able to
303 # create a worksheet, test it, then save it in the current directory, and
304 # have that act the same as loading the worksheet to start with. This is
305 # less obviously right when run from a menu item.
306 notebook
.set_path([os
.getcwd()])
309 settings
= w
.get_settings()
310 settings
.set_property("gtk-button-images", False)
311 settings
.set_property("gtk-menu-images", False)
315 def on_delete_event(window
, event
):
319 w
.connect('delete-event', on_delete_event
)