Merge lp:~tintou/scratch/scratch-backup-changes into lp:~elementary-apps/scratch/scratch
- scratch-backup-changes
- Merge into scratch
Status: | Needs review |
---|---|
Proposed branch: | lp:~tintou/scratch/scratch-backup-changes |
Merge into: | lp:~elementary-apps/scratch/scratch |
Diff against target: |
628 lines (+206/-165) 4 files modified
plugins/outline/CMakeLists.txt (+9/-5) src/MainWindow.vala (+1/-1) src/Services/Document.vala (+195/-158) src/Services/FileHandler.vala (+1/-1) |
To merge this branch: | bzr merge lp:~tintou/scratch/scratch-backup-changes |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Zisu Andrei (community) | Needs Information | ||
xapantu (community) | Needs Fixing | ||
Review via email: mp+271337@code.launchpad.net |
Commit message
Description of the change
The restoration point isn't kept in memory but in the backup file.
Don't check for file existence at focus but creates a FileMonitor to have every events on real-time.
With this the file loading process is much faster.
- 1559. By Corentin Noël
-
Don't save the file while restoring it.
Corentin Noël (tintou) wrote : | # |
Lucas: I fixed most inline comment you did, but most of the code is just copy/paste from older functions so it's not the scope of this branch to change all the behavior and strings :)
- 1560. By Corentin Noël
-
Fix save as.
Fixed Outline plugin cmake.
xapantu (xapantu) wrote : | # |
Ok, nice, I will check that as soon as possible!
On 21/10/2015 22:31, Corentin Noël wrote:
> Lucas: I fixed most inline comment you did, but most of the code is just copy/paste from older functions so it's not the scope of this branch to change all the behavior and strings :)
>
Zisu Andrei (matzipan) wrote : | # |
How do I test this?
Zisu Andrei (matzipan) wrote : | # |
From tintou:
I think you have to open a document, and delete it, and see if scratch shows the infobar without even focusing it. Also see if the file~ is created and removed as it should be.
Unmerged revisions
- 1560. By Corentin Noël
-
Fix save as.
Fixed Outline plugin cmake. - 1559. By Corentin Noël
-
Don't save the file while restoring it.
- 1558. By Corentin Noël
-
Fixed reverting sensitivity not being per-document.
- 1557. By Corentin Noël
-
More efficient document loading and changes handling.
Preview Diff
1 | === modified file 'plugins/outline/CMakeLists.txt' |
2 | --- plugins/outline/CMakeLists.txt 2015-03-19 14:49:48 +0000 |
3 | +++ plugins/outline/CMakeLists.txt 2015-10-21 20:31:41 +0000 |
4 | @@ -21,6 +21,11 @@ |
5 | set(VALA_SHORTVER "${maj_ver}.${min_ver}" CACHE INTERNAL "") |
6 | |
7 | |
8 | +pkg_check_modules (LIBVALA "libvala-${VALA_SHORTVER}") |
9 | + |
10 | +if (${LIBVALA_FOUND}) |
11 | +link_directories(${LIBVALA_LIBRARY_DIRS}) |
12 | +add_definitions(${LIBVALA_CFLAGS}) |
13 | |
14 | vala_precompile(VALA_C ${PLUGIN_NAME} |
15 | CtagsSymbolResolver.vala |
16 | @@ -49,15 +54,14 @@ |
17 | include (GResource) |
18 | glib_compile_resources (GLIB_RESOURCES_OUTLINE SOURCE icons/outline.gresource.xml) |
19 | |
20 | -pkg_check_modules(OUTLINE_DEPS libvala-${VALA_SHORTVER}) |
21 | -link_directories(${OUTLINE_DEPS_LIBRARY_DRIS}) |
22 | -add_definitions(${OUTLINE_DEPS_CFLAGS}) |
23 | - |
24 | add_library(${PLUGIN_NAME} MODULE ${VALA_C} ${GLIB_RESOURCES_OUTLINE}) |
25 | add_dependencies(${PLUGIN_NAME} ${LIBNAME} scratch) |
26 | -target_link_libraries(${PLUGIN_NAME} ${NORMAL_LIBRARIES} ${OUTLINE_DEPS_LIBRARIES}) |
27 | +target_link_libraries(${PLUGIN_NAME} ${NORMAL_LIBRARIES} ${LIBVALA_LIBRARIES}) |
28 | |
29 | install(TARGETS ${PLUGIN_NAME} DESTINATION ${PLUGINDIR}/${PLUGIN_NAME}) |
30 | install(FILES ${PLUGIN_NAME}.plugin DESTINATION ${PLUGINDIR}/${PLUGIN_NAME}) |
31 | |
32 | message("-- Outline plugin will be compiled") |
33 | +else() |
34 | +message("-- Outline plugin will NOT be compiled") |
35 | +endif() |
36 | |
37 | === modified file 'src/MainWindow.vala' |
38 | --- src/MainWindow.vala 2015-10-01 10:42:31 +0000 |
39 | +++ src/MainWindow.vala 2015-10-21 20:31:41 +0000 |
40 | @@ -322,7 +322,7 @@ |
41 | main_actions.get_action ("SaveFileAs").sensitive = val; |
42 | main_actions.get_action ("Undo").sensitive = val; |
43 | main_actions.get_action ("Redo").sensitive = val; |
44 | - main_actions.get_action ("Revert").sensitive = val; |
45 | + main_actions.get_action ("Revert").sensitive = val && main_actions.get_action ("Revert").sensitive; |
46 | this.toolbar.share_app_menu.sensitive = val; |
47 | |
48 | // Zoom button |
49 | |
50 | === modified file 'src/Services/Document.vala' |
51 | --- src/Services/Document.vala 2015-09-16 01:11:55 +0000 |
52 | +++ src/Services/Document.vala 2015-10-21 20:31:41 +0000 |
53 | @@ -20,7 +20,6 @@ |
54 | ***/ |
55 | |
56 | namespace Scratch.Services { |
57 | - |
58 | public enum DocumentStates { |
59 | NORMAL, |
60 | READONLY |
61 | @@ -45,22 +44,38 @@ |
62 | public signal void doc_saved (); |
63 | public signal void doc_closed (); |
64 | |
65 | + public bool can_revert = false; |
66 | + |
67 | // Widgets |
68 | public Scratch.Widgets.SourceView source_view; |
69 | private Gtk.InfoBar info_bar; |
70 | |
71 | // Objects |
72 | private Gtk.SourceFile source_file; |
73 | + private FileMonitor file_monitor = null; |
74 | + public File backup_file; |
75 | public File file { |
76 | get { return source_file.location; } |
77 | set { |
78 | source_file.set_location (value); |
79 | - file_changed (); |
80 | + backup_file = File.new_for_path ("%s~".printf (value.get_path ())); |
81 | + attribute_changed (); |
82 | + if (file_monitor != null) { |
83 | + file_monitor.changed.disconnect (monitor_changed); |
84 | + file_monitor.cancel (); |
85 | + } |
86 | + |
87 | + try { |
88 | + file_monitor = value.monitor_file (FileMonitorFlags.WATCH_MOUNTS); |
89 | + file_monitor.changed.connect (monitor_changed); |
90 | + } catch (Error e) { |
91 | + debug (e.message); |
92 | + } |
93 | } |
94 | } |
95 | |
96 | - public string original_content; |
97 | public bool saved = true; |
98 | + private bool ignore_next = false; |
99 | private bool error_shown = false; |
100 | public bool is_file_temporary { |
101 | get { |
102 | @@ -84,7 +99,7 @@ |
103 | |
104 | // Mount state of the file |
105 | private bool mounted = true; |
106 | - private Mount mount; |
107 | + private bool read_only = false; |
108 | |
109 | public Document (Gtk.ActionGroup actions, File? file = null) { |
110 | this.main_actions = actions; |
111 | @@ -123,14 +138,15 @@ |
112 | Source.remove (timeout_saving); |
113 | timeout_saving = 0; |
114 | } |
115 | + |
116 | timeout_saving = Timeout.add (1000, () => { |
117 | save.begin (); |
118 | timeout_saving = 0; |
119 | return false; |
120 | }); |
121 | - } |
122 | - else |
123 | + } else { |
124 | this.set_saved_status (false); |
125 | + } |
126 | }); |
127 | }); |
128 | } else if (onchange_handler_id != 0) { |
129 | @@ -159,9 +175,7 @@ |
130 | // Focus in event for SourceView |
131 | this.source_view.focus_in_event.connect (() => { |
132 | main_actions.get_action ("SaveFile").visible = !(settings.autosave); |
133 | - check_file_status (); |
134 | check_undoable_actions (); |
135 | - |
136 | return false; |
137 | }); |
138 | |
139 | @@ -197,9 +211,10 @@ |
140 | return false; |
141 | } |
142 | |
143 | + can_revert = false; |
144 | source_view.buffer.set_modified (false); |
145 | - original_content = source_view.buffer.text; |
146 | loaded = true; |
147 | + check_undoable_actions (); |
148 | |
149 | doc_opened (); |
150 | |
151 | @@ -286,6 +301,7 @@ |
152 | save_cancellable = new GLib.Cancellable (); |
153 | var source_file_saver = new Gtk.SourceFileSaver (source_view.buffer, source_file); |
154 | try { |
155 | + ignore_next = true; |
156 | yield source_file_saver.save_async (GLib.Priority.DEFAULT, save_cancellable, null); |
157 | } catch (Error e) { |
158 | // We don't need to send an error message at cancellation (corresponding to error code 19) |
159 | @@ -299,9 +315,10 @@ |
160 | // Zeitgeist integration |
161 | zg_log.save_insert (file.get_uri (), get_mime_type ()); |
162 | #endif |
163 | - |
164 | doc_saved (); |
165 | + can_revert = true; |
166 | this.set_saved_status (true); |
167 | + check_undoable_actions (); |
168 | |
169 | message ("File \"%s\" saved succesfully", get_basename ()); |
170 | |
171 | @@ -316,12 +333,18 @@ |
172 | bool is_current_file_temporary = this.is_file_temporary; |
173 | |
174 | if (filech.run () == Gtk.ResponseType.ACCEPT) { |
175 | - this.file = File.new_for_uri (filech.get_file ().get_uri ()); |
176 | + var dest = File.new_for_uri (filech.get_file ().get_uri ()); |
177 | + try { |
178 | + file.copy (dest, GLib.FileCopyFlags.OVERWRITE); |
179 | + } catch (Error e) { |
180 | + critical (e.message); |
181 | + return false; |
182 | + } |
183 | + file = dest; |
184 | // Update last visited path |
185 | Utils.last_path = Path.get_dirname (filech.get_file ().get_uri ()); |
186 | filech.destroy (); |
187 | - } |
188 | - else { |
189 | + } else { |
190 | filech.destroy (); |
191 | return false; |
192 | } |
193 | @@ -338,7 +361,7 @@ |
194 | } |
195 | |
196 | // Delete backup file |
197 | - delete_backup (current_file + "~"); |
198 | + delete_backup (); |
199 | |
200 | // Change syntax highlight |
201 | this.source_view.change_syntax_highlight_from_file (this.file); |
202 | @@ -401,10 +424,11 @@ |
203 | |
204 | // Get file name |
205 | public string get_basename () { |
206 | - if (is_file_temporary) |
207 | + if (is_file_temporary) { |
208 | return _("New Document"); |
209 | - else |
210 | + } else { |
211 | return file.get_basename (); |
212 | + } |
213 | } |
214 | |
215 | // Set InfoBars message |
216 | @@ -421,6 +445,7 @@ |
217 | if (w != null) |
218 | w.destroy (); |
219 | }); |
220 | + |
221 | ((Gtk.Box)info_bar.get_action_area ()).get_children ().foreach ((w) => { |
222 | if (w != null) |
223 | w.destroy (); |
224 | @@ -438,17 +463,21 @@ |
225 | var main = info_bar.get_content_area () as Gtk.Box; |
226 | main.orientation = Gtk.Orientation.HORIZONTAL; |
227 | main.pack_start (l, false, false, 0); |
228 | - if (button1 != null) |
229 | + if (button1 != null) { |
230 | info_bar.add_button (button1, 0); |
231 | - if (button2 != null) |
232 | + } |
233 | + |
234 | + if (button2 != null) { |
235 | info_bar.add_button (button2, 1); |
236 | + } |
237 | |
238 | // Response |
239 | info_bar.response.connect ((id) => { |
240 | - if (id == 0) |
241 | + if (id == 0) { |
242 | callback1 (); |
243 | - else if (id == 1) |
244 | + } else if (id == 1) { |
245 | callback2 (); |
246 | + } |
247 | }); |
248 | |
249 | // Show everything |
250 | @@ -476,7 +505,8 @@ |
251 | |
252 | // Revert |
253 | public void revert () { |
254 | - this.source_view.set_text (original_content, false); |
255 | + restore_backup (); |
256 | + can_revert = false; |
257 | check_undoable_actions (); |
258 | } |
259 | |
260 | @@ -493,26 +523,28 @@ |
261 | // Get language name |
262 | public string get_language_name () { |
263 | var lang = this.source_view.buffer.language; |
264 | - if (lang != null) |
265 | + if (lang != null) { |
266 | return lang.name; |
267 | - else |
268 | + } else { |
269 | return ""; |
270 | + } |
271 | } |
272 | |
273 | // Get language id |
274 | public string get_language_id () { |
275 | var lang = this.source_view.buffer.language; |
276 | - if (lang != null) |
277 | + if (lang != null) { |
278 | return lang.id; |
279 | - else |
280 | + } else { |
281 | return ""; |
282 | + } |
283 | } |
284 | |
285 | // Duplicate selected text |
286 | public void duplicate_selection () { |
287 | this.source_view.duplicate_selection (); |
288 | } |
289 | - |
290 | + |
291 | // Show an error dialog which says "Hey, I cannot read that file!" |
292 | private void show_error_dialog () { |
293 | if (this.error_shown) |
294 | @@ -528,139 +560,76 @@ |
295 | dialog.destroy (); |
296 | this.close (); |
297 | } |
298 | - |
299 | - // Check if the file was deleted/changed by an external source |
300 | - public void check_file_status () { |
301 | - // If the file does not exist anymore |
302 | - if (!exists ()) { |
303 | - if (mounted == false) { |
304 | - string message = _("The location containing the file \"%s\" was unmounted. Do you want to save somewhere else?").printf ("<b>%s</b>".printf (get_basename ())); |
305 | - |
306 | - set_message (Gtk.MessageType.WARNING, message, _("Save As…"), () => { |
307 | - this.save_as.begin (); |
308 | - hide_info_bar (); |
309 | - }); |
310 | - } else { |
311 | - string message = _("File \"%s\" was deleted. Do you want to save it anyway?").printf ("<b>%s</b>".printf (get_basename ())); |
312 | - |
313 | - set_message (Gtk.MessageType.WARNING, message, _("Save"), () => { |
314 | - this.save.begin (); |
315 | - hide_info_bar (); |
316 | - }); |
317 | - } |
318 | - main_actions.get_action ("SaveFile").sensitive = false; |
319 | - this.source_view.editable = false; |
320 | - return; |
321 | - } |
322 | - // If the file can't be written |
323 | - if (!can_write ()) { |
324 | - string message = _("You cannot save changes on file \"%s\". Do you want to save the changes to this file in a different location?").printf ("<b>%s</b>".printf (get_basename ())); |
325 | - |
326 | - set_message (Gtk.MessageType.WARNING, message, _("Save changes elsewhere"), () => { |
327 | - this.save_as.begin (); |
328 | - hide_info_bar (); |
329 | - }); |
330 | - main_actions.get_action ("SaveFile").sensitive = false; |
331 | - this.source_view.editable = !settings.autosave; |
332 | - } |
333 | - else { |
334 | - main_actions.get_action ("SaveFile").sensitive = true; |
335 | - this.source_view.editable = true; |
336 | - } |
337 | - // Detect external changes |
338 | - if (loaded) { |
339 | - var new_buffer = new Gtk.SourceBuffer (null); |
340 | - var source_file_loader = new Gtk.SourceFileLoader (new_buffer, source_file); |
341 | - source_file_loader.load_async.begin (GLib.Priority.DEFAULT, null, null, (obj, res) => { |
342 | - try { |
343 | - source_file_loader.load_async.end (res); |
344 | - } catch (Error e) { |
345 | - critical (e.message); |
346 | - show_error_dialog (); |
347 | - return; |
348 | - } |
349 | - |
350 | - if (source_view.buffer.text == new_buffer.text) |
351 | - return; |
352 | - |
353 | - if (!source_view.buffer.get_modified ()) { |
354 | - if (settings.autosave) { |
355 | - source_view.set_text (new_buffer.text, false); |
356 | - } else { |
357 | - string message = _("File \"%s\" was modified by an external application. Do you want to load it again or continue your editing?").printf ("<b>%s</b>".printf (get_basename ())); |
358 | - set_message (Gtk.MessageType.WARNING, message, _("Load"), () => { |
359 | - this.source_view.set_text (new_buffer.text, false); |
360 | - hide_info_bar (); |
361 | - }, _("Continue"), () => { |
362 | - hide_info_bar (); |
363 | - }); |
364 | - } |
365 | - } |
366 | - }); |
367 | - } |
368 | - } |
369 | |
370 | // Set Undo/Redo action sensitive property |
371 | public void check_undoable_actions () { |
372 | main_actions.get_action ("Undo").sensitive = this.source_view.buffer.can_undo; |
373 | main_actions.get_action ("Redo").sensitive = this.source_view.buffer.can_redo; |
374 | - main_actions.get_action ("Revert").sensitive = (original_content != source_view.buffer.text); |
375 | + main_actions.get_action ("Revert").sensitive = can_revert; |
376 | } |
377 | |
378 | // Set saved status |
379 | public void set_saved_status (bool val) { |
380 | this.saved = val; |
381 | - |
382 | string unsaved_identifier = "* "; |
383 | - |
384 | if (!val) { |
385 | - if (!(unsaved_identifier in this.label)) |
386 | + if (!(unsaved_identifier in this.label)) { |
387 | this.label = unsaved_identifier + this.label; |
388 | - } |
389 | - else |
390 | + } |
391 | + } else { |
392 | this.label = this.label.replace (unsaved_identifier, ""); |
393 | + } |
394 | } |
395 | |
396 | // Backup functions |
397 | private void create_backup () { |
398 | - if (!can_write ()) |
399 | + if (read_only) { |
400 | return; |
401 | - |
402 | - var backup = File.new_for_path (this.file.get_path () + "~"); |
403 | - |
404 | - if (!backup.query_exists ()) { |
405 | + } |
406 | + |
407 | + if (!backup_file.query_exists ()) { |
408 | try { |
409 | - file.copy (backup, FileCopyFlags.NONE); |
410 | + file.copy (backup_file, FileCopyFlags.NONE); |
411 | } catch (Error e) { |
412 | warning ("Cannot create backup copy for file \"%s\": %s", get_basename (), e.message); |
413 | } |
414 | } |
415 | } |
416 | |
417 | - private void delete_backup (string? backup_path = null) { |
418 | - |
419 | - string backup_file = ""; |
420 | - |
421 | - if (backup_path == null) |
422 | - backup_file = file.get_path () + "~"; |
423 | - else |
424 | - backup_file = backup_path; |
425 | - |
426 | - debug ("Backup file deleting: %s", backup_file); |
427 | - |
428 | - var backup = File.new_for_path (backup_file); |
429 | - if (backup == null || !backup.query_exists ()) { |
430 | - debug ("Backup file doesn't exists: %s", backup.get_path ()); |
431 | + private void delete_backup () { |
432 | + debug ("Backup file deleting: %s", backup_file.get_path ()); |
433 | + if (backup_file == null || !backup_file.query_exists ()) { |
434 | + debug ("Backup file doesn't exists: %s", backup_file.get_path ()); |
435 | return; |
436 | } |
437 | + |
438 | try { |
439 | - backup.delete (); |
440 | - debug ("Backup file deleted: %s", backup_file); |
441 | + backup_file.delete (); |
442 | + debug ("Backup file deleted: %s", backup_file.get_path ()); |
443 | } catch (Error e) { |
444 | warning ("Cannot delete backup for file \"%s\": %s", get_basename (), e.message); |
445 | } |
446 | } |
447 | |
448 | + private void restore_backup () { |
449 | + var backup_source = new Gtk.SourceFile (); |
450 | + backup_source.set_location (backup_file); |
451 | + var new_buffer = new Gtk.SourceBuffer (null); |
452 | + var source_file_loader = new Gtk.SourceFileLoader (new_buffer, backup_source); |
453 | + loaded = false; |
454 | + source_file_loader.load_async.begin (GLib.Priority.DEFAULT, null, null, (obj, res) => { |
455 | + try { |
456 | + source_file_loader.load_async.end (res); |
457 | + source_view.buffer.text = new_buffer.text; |
458 | + loaded = true; |
459 | + } catch (Error e) { |
460 | + critical (e.message); |
461 | + show_error_dialog (); |
462 | + return; |
463 | + } |
464 | + }); |
465 | + } |
466 | + |
467 | private bool delete_temporary_file (bool force = false) { |
468 | if (!is_file_temporary || (get_text ().length > 0 && !force)) |
469 | return false; |
470 | @@ -674,46 +643,114 @@ |
471 | } |
472 | |
473 | // Return true if the file is writable |
474 | - public bool can_write () { |
475 | - FileInfo info; |
476 | - |
477 | - bool writable = false; |
478 | - |
479 | - try { |
480 | - info = this.file.query_info (FileAttribute.ACCESS_CAN_WRITE, FileQueryInfoFlags.NONE, null); |
481 | - writable = info.get_attribute_boolean (FileAttribute.ACCESS_CAN_WRITE); |
482 | - return writable; |
483 | - } catch (Error e) { |
484 | - warning ("query_info failed, but filename appears to be correct, allowing as new file"); |
485 | - writable = true; |
486 | - return writable; |
487 | - } |
488 | - } |
489 | |
490 | // Return true if the file exists |
491 | public bool exists () { |
492 | return this.file.query_exists (); |
493 | } |
494 | |
495 | - private void file_changed () { |
496 | - if (mount != null) { |
497 | - mount.unmounted.disconnect (unmounted_cb); |
498 | - mount = null; |
499 | - } |
500 | - |
501 | - try { |
502 | - mount = file.find_enclosing_mount (); |
503 | - mount.unmounted.connect (unmounted_cb); |
504 | - } catch (Error e) { |
505 | - debug ("Could not find mount location"); |
506 | - return; |
507 | - } |
508 | - mounted = true; |
509 | - } |
510 | - |
511 | - private void unmounted_cb () { |
512 | - warning ("Folder containing the file was unmounted"); |
513 | + private void monitor_changed (File file, File? other_file, FileMonitorEvent event_type) { |
514 | + switch (event_type) { |
515 | + case FileMonitorEvent.CHANGED: |
516 | + attribute_changed (); |
517 | + break; |
518 | + case FileMonitorEvent.DELETED: |
519 | + deleted (); |
520 | + break; |
521 | + case FileMonitorEvent.CREATED: |
522 | + if (ignore_next == false) { |
523 | + changed_external (); |
524 | + } |
525 | + |
526 | + ignore_next = false; |
527 | + break; |
528 | + case FileMonitorEvent.UNMOUNTED: |
529 | + unmounted (); |
530 | + break; |
531 | + case FileMonitorEvent.ATTRIBUTE_CHANGED: |
532 | + attribute_changed (); |
533 | + break; |
534 | + default: |
535 | + break; |
536 | + } |
537 | + } |
538 | + |
539 | + private void changed_external () { |
540 | + var new_buffer = new Gtk.SourceBuffer (null); |
541 | + var source_file_loader = new Gtk.SourceFileLoader (new_buffer, source_file); |
542 | + source_file_loader.load_async.begin (GLib.Priority.DEFAULT, null, null, (obj, res) => { |
543 | + try { |
544 | + source_file_loader.load_async.end (res); |
545 | + } catch (Error e) { |
546 | + critical (e.message); |
547 | + show_error_dialog (); |
548 | + return; |
549 | + } |
550 | + |
551 | + if (source_view.buffer.text == new_buffer.text) |
552 | + return; |
553 | + |
554 | + if (!source_view.buffer.get_modified ()) { |
555 | + if (settings.autosave) { |
556 | + source_view.set_text (new_buffer.text, false); |
557 | + attribute_changed (); |
558 | + } else { |
559 | + string message = _("File \"%s\" was modified by an external application. Do you want to load it again or continue your editing?").printf ("<b>%s</b>".printf (get_basename ())); |
560 | + set_message (Gtk.MessageType.WARNING, message, _("Load"), () => { |
561 | + this.source_view.set_text (new_buffer.text, false); |
562 | + attribute_changed (); |
563 | + hide_info_bar (); |
564 | + }, _("Continue"), () => { |
565 | + hide_info_bar (); |
566 | + }); |
567 | + } |
568 | + } |
569 | + }); |
570 | + } |
571 | + |
572 | + private void deleted () { |
573 | + string message = _("File \"%s\" was deleted. Do you want recreate it?").printf ("<b>%s</b>".printf (get_basename ())); |
574 | + |
575 | + set_message (Gtk.MessageType.WARNING, message, _("Save"), () => { |
576 | + this.save.begin (); |
577 | + hide_info_bar (); |
578 | + }); |
579 | + } |
580 | + |
581 | + private void unmounted () { |
582 | mounted = false; |
583 | + main_actions.get_action ("SaveFile").sensitive = false; |
584 | + source_view.editable = false; |
585 | + string message = _("The location containing the file \"%s\" was unmounted. Do you want to save somewhere else?").printf ("<b>%s</b>".printf (get_basename ())); |
586 | + |
587 | + set_message (Gtk.MessageType.WARNING, message, _("Save As…"), () => { |
588 | + this.save_as.begin (); |
589 | + hide_info_bar (); |
590 | + }); |
591 | + } |
592 | + |
593 | + public void attribute_changed () { |
594 | + FileInfo info; |
595 | + try { |
596 | + info = file.query_info (FileAttribute.ACCESS_CAN_WRITE, FileQueryInfoFlags.NONE, null); |
597 | + read_only = !info.get_attribute_boolean (FileAttribute.ACCESS_CAN_WRITE); |
598 | + if (read_only) { |
599 | + string message = _("You cannot save changes on file \"%s\". Do you want to save the changes to this file in a different location?").printf ("<b>%s</b>".printf (get_basename ())); |
600 | + |
601 | + set_message (Gtk.MessageType.WARNING, message, _("Save changes elsewhere"), () => { |
602 | + this.save_as.begin (); |
603 | + hide_info_bar (); |
604 | + }); |
605 | + main_actions.get_action ("SaveFile").sensitive = false; |
606 | + this.source_view.editable = !settings.autosave; |
607 | + } else { |
608 | + main_actions.get_action ("SaveFile").sensitive = true; |
609 | + this.source_view.editable = true; |
610 | + } |
611 | + } catch (Error e) { |
612 | + warning ("query_info failed, but filename appears to be correct, allowing as new file"); |
613 | + read_only = false; |
614 | + } |
615 | } |
616 | } |
617 | } |
618 | |
619 | === modified file 'src/Services/FileHandler.vala' |
620 | --- src/Services/FileHandler.vala 2015-03-19 21:34:20 +0000 |
621 | +++ src/Services/FileHandler.vala 2015-10-21 20:31:41 +0000 |
622 | @@ -130,4 +130,4 @@ |
623 | |
624 | } |
625 | |
626 | -} |
627 | \ No newline at end of file |
628 | +} |
Some in-line comments, maybe more to come.
Here is a crash, after using the "save as" button (maybe not related, I don't have a backtrace yet).
xapantu@ntu /t/s/build> src/scratch- text-editor vala:155: Scratch version: 2.2.1 vala:157: Kernel version: 4.1.4-1-ARCH scratch. saved-state' scratch. settings' scratch. services' scratch. plugins. terminal' gtk-menu- images is deprecated and shouldn't be used anymore. It will be removed in a future version. bar_pack: assertion 'gtk_widget_ get_parent (widget) == NULL' failed set_visible: assertion 'GTK_IS_ACTION (action)' failed vala:673: open temporary file: Fichier texte à partir de 2015-09-24 01:28:31 vala:204: schema_version is 10 Pixbuf: follow- state is deprecated and shouldn't be used anymore. It will be removed in a future version. scratch. plugins. folder- manager' vala:204: schema_version is 10 vala:142: This Document was already opened! Not opening a duplicate! vala:204: schema_version is 10 view_get_ editable: assertion 'GTK_IS_TEXT_VIEW (text_view)' failed view_get_ editable: assertion 'GTK_IS_TEXT_VIEW (text_view)' failed view_get_ editable: assertion 'GTK_IS_TEXT_VIEW (text_view)' failed view_get_ editable: assertion 'GTK_IS_TEXT_VIEW (text_view)' failed view_get_ editable: assertion 'GTK_IS_TEXT_VIEW (text_view)' failed view_get_ editable: assertion 'GTK_IS_TEXT_VIEW (text_view)' failed
[INFO 02:22:03.881206] Application.
[INFO 02:22:03.881260] Application.
[DEBUG 02:22:03.882757] Settings.vala:163: Loading settings from schema 'org.pantheon.
[DEBUG 02:22:03.883261] Settings.vala:163: Loading settings from schema 'org.pantheon.
[DEBUG 02:22:03.884352] Settings.vala:163: Loading settings from schema 'org.pantheon.
[DEBUG 02:22:03.959510] [Gtk] Connecting to session manager
[WARNING 02:22:03.965308] [Gtk] Attempting to add a widget with type GtkScrolledWindow to a GtkDialog, but as a GtkBin subclass a GtkDialog can only contain one widget at a time; it already contains a widget of type GtkBox
[WARNING 02:22:03.965550] [libpeas] Failed to enable unknown plugin loader 'gjs'
[DEBUG 02:22:03.991315] Settings.vala:163: Loading settings from schema 'org.pantheon.
[WARNING 02:22:04.011552] [libpeas] Failed to enable unknown plugin loader 'gjs'
[WARNING 02:22:04.045298] [GLib-GObject] The property GtkSettings:
[FATAL 02:22:04.051353] [Gtk] gtk_header_
[FATAL 02:22:04.157390] [Gtk] gtk_action_
[DEBUG 02:22:04.157634] MainWindow.
[DEBUG 02:22:04.162284] sql-schema.
[INFO 02:22:04.206977] Document.vala:171: Opening "Nouveau document"
[DEBUG 02:22:04.312185] SplitView.vala:124: View added successfully
[WARNING 02:22:04.501706] [GLib-GObject] The property GtkCellRenderer
[DEBUG 02:22:04.502441] Settings.vala:163: Loading settings from schema 'org.pantheon.
[DEBUG 02:22:04.596172] sql-schema.
[INFO 02:22:04.606347] Document.vala:171: Opening "Nouveau document"
[WARNING 02:22:04.616528] DocumentView.
[DEBUG 02:22:04.618693] sql-schema.
[INFO 02:22:04.625701] Document.vala:171: Opening "40_39.diff"
[FATAL 02:22:04.712490] [Gtk] gtk_text_
[FATAL 02:22:04.718433] [Gtk] gtk_text_
[FATAL 02:22:04.722147] [Gtk] gtk_text_
[FATAL 02:22:04.727046] [Gtk] gtk_text_
[FATAL 02:22:04.730144] [Gtk] gtk_text_
[FATAL 02:22:04.732916] [Gtk] gtk_text_
[FAT...