Removed the pyc files (oops!).
[rox-archive.git] / SaveBox.py
blob3fbb18adb4a941aa835a213f2b47c3d841a19cc4
1 from string import rfind
3 from gtk import *
4 from GDK import *
5 import _gtk
7 import __main__
8 from support import *
9 import choices
11 TARGET_XDS = 0
12 TARGET_RAW = 1
14 def icon_for_type(window, media, subtype):
15 '''Search <Choices> for a suitable icon. Returns (pixmap, mask) '''
16 path = choices.load('MIME-icons', media + '_' + subtype + '.xpm')
17 if not path:
18 path = choices.load('MIME-icons', media + '.xpm')
19 if path:
20 p, m = load_pixmap(window, path)
21 else:
22 p = None
23 if not p:
24 p, m = load_pixmap(window, __main__.app_dir + '/icons/File.xpm')
25 return p, m
27 def write_xds_property(context, value):
28 XdndDirectSave = _gtk.gdk_atom_intern('XdndDirectSave0', FALSE)
29 text_plain = _gtk.gdk_atom_intern('text/plain', FALSE)
30 win = context.source_window
31 if value:
32 win.property_change(XdndDirectSave, text_plain, 8,
33 PROP_MODE_REPLACE,
34 value)
35 else:
36 win.property_delete(XdndDirectSave)
38 def read_xds_property(context, delete):
39 XdndDirectSave = _gtk.gdk_atom_intern('XdndDirectSave0', FALSE)
40 text_plain = _gtk.gdk_atom_intern('text/plain', FALSE)
41 win = context.source_window
42 retval = win.property_get(XdndDirectSave, text_plain, delete)
43 if retval:
44 return retval[2]
45 return None
47 # 'window' should have the following methods/attribs:
49 # uri - the initial pathname to use
50 # save_as(path) - write data to file, TRUE on success
51 # set_uri(uri) - data is safely saved to this location
52 # send_raw(selection_data) - write data to selection
53 # (if missing, data can only be saved to the filesystem)
54 # discard() - discard button clicked
55 # (only needed if discard = TRUE)
57 class SaveBox(GtkWindow):
58 def __init__(self, window, media, subtype, discard = FALSE):
59 GtkWindow.__init__(self, WINDOW_DIALOG)
60 self.discard = discard
61 self.set_title('Save As:')
62 self.set_position(WIN_POS_MOUSE)
63 self.set_border_width(4)
64 self.window = window
66 vbox = GtkVBox(FALSE, 0)
67 self.add(vbox)
69 align = GtkAlignment()
70 align.set(.5, .5, 0, 0)
71 vbox.pack_start(align, TRUE, TRUE, 0)
73 drag_box = GtkEventBox()
74 drag_box.set_border_width(4)
75 drag_box.add_events(BUTTON_PRESS_MASK)
76 align.add(drag_box)
78 pixmap, mask = icon_for_type(self, media, subtype)
79 self.icon = GtkPixmap(pixmap, mask)
81 if (hasattr(window, 'send_raw')):
82 target = [('XdndDirectSave0', 0, TARGET_XDS),
83 ('%s/%s' % (media, subtype), 0, TARGET_RAW),
84 ('application/octet-stream', 0, TARGET_RAW)
86 else:
87 target = [('XdndDirectSave0', 0, TARGET_XDS)]
89 drag_box.drag_source_set(BUTTON1_MASK | BUTTON3_MASK,
90 target,
91 ACTION_COPY | ACTION_MOVE)
92 drag_box.connect('drag_begin', self.drag_begin)
93 drag_box.connect('drag_data_get', self.drag_data_get)
95 drag_box.add(self.icon)
97 entry = GtkEntry()
98 self.entry = entry
99 vbox.pack_start(entry, FALSE, TRUE, 4)
101 hbox = GtkHBox(TRUE, 0)
102 vbox.pack_start(hbox, FALSE, TRUE, 0)
104 ok = GtkButton("Save")
105 ok.set_flags(CAN_DEFAULT)
106 hbox.pack_start(ok, FALSE, TRUE, 0)
108 cancel = GtkButton("Cancel")
109 cancel.set_flags(CAN_DEFAULT)
110 hbox.pack_start(cancel, FALSE, TRUE, 0)
111 cancel.connect('clicked', self.cancel)
113 if discard:
114 vbox.pack_start(GtkHSeparator(), FALSE, TRUE, 4)
115 button = GtkButton('Discard')
116 vbox.pack_start(button, FALSE, TRUE, 0)
117 button.connect('clicked', self.discard_clicked)
119 vbox.show_all()
120 ok.grab_default()
121 ok.connect('clicked', self.ok, entry)
123 entry.grab_focus()
124 entry.connect('activate', self.ok, entry)
126 entry.set_text(window.uri)
127 i = rfind(window.uri, '/')
128 i = i + 1
130 entry.realize()
131 entry.set_position(-1)
132 entry.select_region(i, -1)
134 def cancel(self, widget):
135 self.destroy()
137 def ok(self, widget, entry):
138 uri = entry.get_text()
139 path = get_local_path(uri)
141 if path:
142 if self.window.save_as(path):
143 self.window.set_uri(path)
144 self.destroy()
145 if self.discard:
146 self.window.close()
147 else:
148 report_error("Drag the icon to a directory viewer\n" +
149 "(or enter a full pathname)",
150 "To Save:")
152 def drag_begin(self, drag_box, context):
153 self.using_xds = 0
154 self.data_sent = 0
155 p, m = self.icon.get()
156 drag_box.drag_source_set_icon(self.icon.get_colormap(), p, m)
158 uri = self.entry.get_text()
159 if uri:
160 i = rfind(uri, '/')
161 if (i == -1):
162 leaf = uri
163 else:
164 leaf = uri[i + 1:]
165 else:
166 leaf = 'Unnamed'
167 write_xds_property(context, leaf)
169 def drag_data_get(self, widget, context, selection_data, info, time):
170 if info == TARGET_RAW:
171 self.window.send_raw(selection_data)
172 self.data_sent = 1
173 write_xds_property(context, None)
174 self.destroy()
175 if self.discard:
176 self.window.close()
177 return
178 elif info != TARGET_XDS:
179 write_xds_property(context, None)
180 report_error("Bad target requested!")
181 return
183 # Using XDS:
185 # Get the path that the destination app wants us to save to.
186 # If it's local, save and return Success
187 # (or Error if save fails)
188 # If it's remote, return Failure (remote may try another method)
189 # If no URI is given, return Error
190 to_send = 'E'
191 uri = read_xds_property(context, FALSE)
192 if uri:
193 path = get_local_path(uri)
194 if path:
195 self.data_sent = self.window.save_as(path)
196 if self.data_sent:
197 to_send = 'S'
198 # (else Error)
199 else:
200 to_send = 'F' # Non-local transfer
201 else:
202 report_error("Remote application wants to use " +
203 "Direct Save, but I can't read the " +
204 "XdndDirectSave0 (type text/plain) " +
205 "property.")
207 selection_data.set(selection_data.target, 8, to_send)
209 if to_send != 'E':
210 write_xds_property(context, None)
211 path = get_local_path(uri)
212 if path:
213 self.window.set_uri(path)
214 else:
215 self.window.set_uri(uri)
216 if self.data_sent:
217 self.destroy()
218 if self.discard:
219 self.window.close()
221 def discard_clicked(self, event):
222 self.window.discard()