~sir-rainbow/+junk/scribes-on-win

« back to all changes in this revision

Viewing changes to SCRIBES/FileSaver.py

  • Committer: goldenmyst
  • Date: 2007-09-25 17:15:52 UTC
  • Revision ID: goldenmyst@goldenmyst-desktop-20070925171552-mvrhxdd39iibs0sr
New branch. New Trigger Management System. New Trigger API. New Plugin Management System. Fix for bug triggered by PyGTK+ version 2.11 or better.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- coding: utf-8 -*-
 
2
# Copyright © 2007 Lateef Alabi-Oki
 
3
#
 
4
# This file is part of Scribes.
 
5
#
 
6
# Scribes is free software; you can redistribute it and/or modify
 
7
# it under the terms of the GNU General Public License as published by
 
8
# the Free Software Foundation; either version 2 of the License, or
 
9
# (at your option) any later version.
 
10
#
 
11
# Scribes is distributed in the hope that it will be useful,
 
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
# GNU General Public License for more details.
 
15
#
 
16
# You should have received a copy of the GNU General Public License
 
17
# along with Scribes; if not, write to the Free Software
 
18
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
 
19
# USA
 
20
 
 
21
"""
 
22
This module documents a class that saves files.
 
23
 
 
24
@author: Lateef Alabi-Oki
 
25
@organization: The Scribes Project
 
26
@copyright: Copyright © 2007 Lateef Alabi-Oki
 
27
@license: GNU GPLv2 or Later
 
28
@contact: mystilleef@gmail.com
 
29
"""
 
30
 
 
31
PRIORITY = 0
 
32
 
 
33
class FileSaver(object):
 
34
        """
 
35
        This class creates an object that saves the content of the text
 
36
        editor's buffer to a file.
 
37
        """
 
38
 
 
39
        def __init__(self, editor):
 
40
                """
 
41
                Initialize object.
 
42
 
 
43
                @param self: Reference to the FileSaver instance.
 
44
                @type self: A FileSaver object.
 
45
 
 
46
                @param editor: Reference to the text editor.
 
47
                @type editor: An Editor object.
 
48
                """
 
49
                self.__init_attributes(editor)
 
50
                self.__create_swap_folder_and_file()
 
51
                self.__signal_id_1 = editor.connect("close-document", self.__close_document_cb)
 
52
                self.__signal_id_2 = editor.connect("close-document-no-save", self.__close_document_no_save_cb)
 
53
                self.__signal_id_3 = editor.connect("save-document", self.__save_document_cb)
 
54
                self.__signal_id_4 = editor.connect("loading-document", self.__checking_document_cb)
 
55
                self.__signal_id_5 = editor.connect_after("loaded-document", self.__loaded_document_cb)
 
56
                self.__signal_id_6 = editor.connect_after("load-error", self.__load_error_cb)
 
57
                self.__signal_id_7 = editor.textbuffer.connect("modified-changed", self.__modified_changed_cb)
 
58
                self.__signal_id_8 = editor.connect_after("rename-document", self.__rename_document_cb)
 
59
                self.__signal_id_9 = editor.connect("saved-document", self.__saved_document_cb)
 
60
                self.__signal_id_10 = editor.store.connect("updated", self.__updated_cb)
 
61
                self.__signal_id_11 = editor.connect_after("renamed-document", self.__renamed_document_cb)
 
62
                self.__signal_id_12 = editor.connect_after("reload-document", self.__reload_document_cb)
 
63
                from gobject import timeout_add
 
64
                timeout_add(100, self.__check_encoding_manager)
 
65
 
 
66
        def __init_attributes(self, editor):
 
67
                """
 
68
                Initialize data attributes.
 
69
 
 
70
                @param self: Reference to the FileSaver instance.
 
71
                @type self: A FileSaver object.
 
72
 
 
73
                @param editor: Reference to the text editor.
 
74
                @type editor: An Editor object.
 
75
                """
 
76
                self.__editor = editor
 
77
                self.__termination_id = editor.register_termination_id()
 
78
                self.__encoding_manager = self.__editor.get_object("EncodingManager")
 
79
                self.__should_rename = False
 
80
                self.__can_quit = False
 
81
                self.__file_info = None
 
82
                self.__save_timer = None
 
83
                self.__swap_folder = None
 
84
                self.__swap_uri = None
 
85
                self.__swap_file = None
 
86
                self.__last_modification_time = None
 
87
                self.__modification_dialog = None
 
88
                self.__do_not_save = False
 
89
                self.__toggle_readonly = False
 
90
                self.__signal_id_1 = self.__signal_id_2 = self.__signal_id_3 = None
 
91
                self.__signal_id_4 = self.__signal_id_5 = self.__signal_id_6 = None
 
92
                self.__signal_id_7 = self.__signal_id_8 = self.__signal_id_9 = None
 
93
                self.__signal_id_10 = self.__monitor_id = self.__signal_id_11 = None
 
94
                self.__signal_id_12 = None
 
95
                return
 
96
 
 
97
########################################################################
 
98
#
 
99
#                           Public API
 
100
#
 
101
########################################################################
 
102
 
 
103
        def save_file(self, is_closing=False):
 
104
                """
 
105
                Save content of text editor's buffer to a file.
 
106
 
 
107
                @param self: Reference to the FileSaver instance.
 
108
                @type self: A FileSaver object.
 
109
 
 
110
                @param is_closing: True if this is the last call.
 
111
                @type is_closing: A Boolean object.
 
112
                """
 
113
                from Exceptions import PermissionError, SwapError, FileWriteError
 
114
                from Exceptions import FileCloseError, FileCreateError, TransferError
 
115
                from Exceptions import DoNothingError, FileModificationError
 
116
                try:
 
117
                        self.__can_save()
 
118
                        self.__determine_action(is_closing)
 
119
                        self.__check_permissions()
 
120
                        self.__check_swap_folder_and_file()
 
121
                        self.__save_file()
 
122
                except PermissionError:
 
123
                        from internationalization import msg0469
 
 
b'\t\t\tself.__error(msg0469)'
 
 
b'\t\texcept SwapError:'
 
124
                        from internationalization import msg0471
 
125
                        self.__error(msg0471)
 
126
                except FileModificationError:
 
127
                        print "File has been modified by another program"
 
128
                except DoNothingError:
 
 
b'\t\t\tpass'
 
129
                return False
 
130
 
 
131
        def reset_save_flag(self):
 
132
                """
 
133
                Reset the "__do_not_save" flag to its default value.
 
134
 
 
135
                @param self: Reference to the FileSaver instance.
 
136
                @type self: A FileSaver object.
 
137
                """
 
138
                self.__do_not_save = False
 
139
                return
 
140
 
 
141
########################################################################
 
142
#
 
143
#                       Helper Methods
 
144
#
 
145
########################################################################
 
146
 
 
147
        def __save_file(self):
 
148
                """
 
149
                Save document to a temporary file.
 
150
 
 
151
                @param self: Reference to the FileSaver instance.
 
152
                @type self: A FileSaver object.
 
153
                """
 
154
                self.__can_save()
 
155
                self.__editor.emit("saving-document", self.__editor.uri)
 
156
                text = self.__encode_text()
 
157
                from gnomevfs import OPEN_WRITE, URI
 
158
                from gnomevfs.async import create
 
159
                from Exceptions import FileCreateError
 
160
                try:
 
161
                        try:
 
162
                                # Write to a temporary file.
 
163
                                create(uri=URI(self.__swap_uri),
 
164
                                                callback=self.__write_cb,
 
165
                                                open_mode=OPEN_WRITE,
 
166
                                                exclusive=False,
 
167
                                                perm=0644,
 
168
                                                priority=PRIORITY,
 
169
                                                data=text)
 
170
                        except:
 
171
                                raise FileCreateError
 
 
b'\t\texcept FileCreateError:'
 
172
                        from internationalization import msg0472
 
173
                        self.__error(msg0472)
 
174
                return
 
175
 
 
176
        def __write_cb(self, handle, result, text):
 
177
                """
 
178
                Callback to the GNOME-VFS asynchronous create method.
 
179
 
 
180
                @param self: Reference to the FileSaver instance.
 
181
                @type self: A FileSaver object.
 
182
                """
 
183
                from Exceptions import FileWriteError
 
184
                try:
 
185
                        self.__can_save()
 
186
                        try:
 
 
b'\t\t\t\thandle.write(text, self.__close_cb)'
 
187
                        except:
 
188
                                handle.cancel()
 
189
                                raise FileWriteError
 
190
                except FileWriteError:
 
191
                        from internationalization import msg0473
 
192
                        self.__error(msg0473)
 
193
                return
 
194
 
 
195
        def __close_cb(self, handle, bytes, result, bytes_requested):
 
196
                """
 
197
                Callback to the GNOME-VFS asynchronous write method.
 
198
 
 
199
                @param self: Reference to the FileSaver instance.
 
200
                @type self: A FileSaver object.
 
201
                """
 
202
                from Exceptions import FileCloseError
 
203
                try:
 
204
                        self.__can_save()
 
205
                        try:
 
206
                                handle.close(self.__finalize_cb)
 
207
                        except:
 
208
                                handle.cancel()
 
209
                                raise FileCloseError
 
210
                except FileCloseError:
 
211
                        from internationalization import msg0474
 
212
                        self.__error(msg0474)
 
213
                return
 
214
 
 
215
        def __finalize_cb(self, *args):
 
216
                """
 
217
                Callback to the GNOME-VFS asynchronous close method.
 
218
 
 
219
                @param self: Reference to the FileSaver instance.
 
220
                @type self: A FileSaver object.
 
221
                """
 
222
                self.__can_save()
 
223
                self.__update_file_info()
 
224
                self.__begin_file_transfer()
 
225
                return
 
226
 
 
227
        def __begin_file_transfer(self):
 
228
                """
 
229
                Transfer temporary file from swap location to permanent location.
 
230
 
 
231
                @param self: Reference to the FileSaver instance.
 
232
                @type self: A FileSaver object.
 
233
                """
 
234
                from gnomevfs import XFER_OVERWRITE_MODE_REPLACE
 
235
                from gnomevfs import XFER_ERROR_MODE_QUERY, URI
 
236
                from gnomevfs.async import xfer
 
237
                from Exceptions import TransferError
 
238
                XFER_TARGET_DEFAULT_PERMS = 1 << 12
 
239
                try:
 
240
                        self.__can_save()
 
241
                        try:
 
242
                                xfer(source_uri_list=[URI(self.__swap_uri)],
 
243
                                        target_uri_list=[URI(self.__editor.uri)],
 
244
                                        xfer_options=XFER_TARGET_DEFAULT_PERMS,
 
245
                                        error_mode=XFER_ERROR_MODE_QUERY,
 
246
                                        priority = PRIORITY,
 
247
                                        overwrite_mode=XFER_OVERWRITE_MODE_REPLACE,
 
248
                                        progress_update_callback=self.__update_cb,
 
249
                                        update_callback_data=self.__swap_file,
 
250
                                        progress_sync_callback=self.__sync_cb)
 
251
                        except:
 
252
                                raise TransferError
 
253
                except TransferError:
 
254
                        from internationalization import msg0470
 
255
                        self.__error(msg0470)
 
256
                return
 
257
 
 
258
        def __sync_cb(self, info):
 
259
                """
 
260
                Callback the GNOME-VFS asynchronous transfer method.
 
261
 
 
262
                @param self: Reference to the FileSaver instance.
 
263
                @type self: A FileSaver object.
 
264
                """
 
265
                from Exceptions import DoNothingError
 
266
                try:
 
267
                        self.__can_save()
 
268
                        if info.vfs_status:
 
269
                                return False
 
270
                except DoNothingError:
 
271
                        return False
 
272
                return  True
 
273
 
 
274
        def __update_cb(self, handle, info, data):
 
275
                """
 
276
                Callback to the GNOME-VFS asynchronous transfer method.
 
277
 
 
278
                @param self: Reference to the FileSaver instance.
 
279
                @type self: A FileSaver object.
 
280
                """
 
281
                from Exceptions import TransferError, DoNothingError
 
282
                try:
 
283
                        self.__can_save()
 
284
                        if info.vfs_status:
 
285
                                # A transfer error occured.
 
286
                                handle.cancel()
 
287
                                raise TransferError
 
288
                        from gnomevfs import XFER_PHASE_COMPLETED
 
289
                        from operator import ne
 
290
                        if ne(info.phase, XFER_PHASE_COMPLETED): return True
 
291
                        from gobject import idle_add
 
292
                        self.__set_file_info()
 
293
                        self.__finish_up()
 
294
                except TransferError:
 
295
                        from internationalization import msg0470
 
296
                        self.__error(msg0470)
 
297
                except DoNothingError:
 
298
                        pass
 
299
                return True
 
300
 
 
301
        def __set_file_info(self):
 
302
                """
 
303
                Set correct permissions of a file after it has been saved.
 
304
 
 
305
                @param self: Reference to the FileSaver instance.
 
306
                @type self: A FileSaver object.
 
307
                """
 
308
                from operator import not_
 
309
                if not_(self.__file_info): return False
 
310
                try:
 
311
                        from gnomevfs import set_file_info, SET_FILE_INFO_PERMISSIONS
 
312
                        set_file_info(self.__editor.uri, self.__file_info, SET_FILE_INFO_PERMISSIONS)
 
313
                except:
 
314
                        pass
 
315
                return False
 
316
 
 
317
        def __finish_up(self):
 
318
                """
 
319
                Finalize the saving process.
 
320
 
 
321
                @param self: Reference to the FileSaver instance.
 
322
                @type self: A FileSaver object.
 
323
                """
 
324
                self.__file_info = None
 
325
                if self.__toggle_readonly:
 
326
                        self.__toggle_readonly = False
 
327
                        self.__editor.trigger("toggle_readonly")
 
328
                if self.__should_rename:
 
329
                        self.__editor.emit("renamed-document", self.__editor.uri)
 
330
                else:
 
331
                        self.__editor.emit("saved-document", self.__editor.uri)
 
 
b'\t\tself.__should_rename = False'
 
332
                if self.__can_quit:
 
333
                        self.__destroy()
 
334
                else:
 
335
                        self.__update_modification_time()
 
336
                return False
 
337
 
 
338
        def __update_modification_time(self):
 
339
                fileinfo = self.__get_file_info()
 
340
                from operator import not_
 
341
                if not_(fileinfo): return
 
342
                self.__last_modification_time = fileinfo.mtime
 
343
                return
 
344
 
 
345
        def __encode_text(self):
 
346
                """
 
347
                Convert the encoding of the content of the document from "UTF-8"
 
348
                to an encoding specified by the user, or back to "UTF-8"
 
349
 
 
350
                @param self: Reference to the FileSaver instance.
 
351
                @type self: A FileSaver object.
 
352
 
 
353
                @return: An encoded string.
 
354
                @rtype: A String object.
 
355
                """
 
356
                try:
 
357
                        self.__can_save()
 
358
                        start, end = self.__editor.textbuffer.get_bounds()
 
359
                        text = self.__editor.textbuffer.get_text(start, end)
 
360
                        unicode_text = text.decode("utf8")
 
361
                        encoded_text = unicode_text.encode(self.__encoding_manager.get_encoding())
 
362
                except UnicodeEncodeError:
 
363
                        from internationalization import msg0476
 
364
                        self.__error(msg0476)
 
365
                except UnicodeDecodeError:
 
366
                        from internationalization import msg0475
 
367
                        self.__error(msg0475)
 
368
                return encoded_text
 
369
 
 
370
        def __check_permissions(self):
 
371
                """
 
372
                Check the permissions of a file.
 
373
 
 
374
                @param self: Reference to the FileSaver instance.
 
375
                @type self: A FileSaver object.
 
376
                """
 
377
                self.__can_save()
 
378
                from operator import not_, is_
 
379
                if not_(self.__editor.uri.startswith("file:///")): return
 
380
                from gnomevfs import get_local_path_from_uri
 
381
                file_path = get_local_path_from_uri(self.__editor.uri)
 
382
                from os import access, W_OK, path
 
383
                folder_path = path.dirname(file_path)
 
384
                from Exceptions import PermissionError
 
385
                if is_(access(folder_path, W_OK), False):
 
386
                        raise PermissionError
 
 
b'\t\telif is_(access(file_path, W_OK), False):'
 
387
                        if path.exists(file_path): raise PermissionError
 
388
                return
 
389
 
 
390
        def __create_swap_folder_and_file(self):
 
391
                """
 
392
                Create the swap location and temporary file.
 
393
 
 
394
                @param self: Reference to the FileSaver instance.
 
395
                @type self: A FileSaver object.
 
396
                """
 
397
                # Create a temporary folder.
 
398
                from tempfile import mkdtemp, NamedTemporaryFile
 
399
                from info import home_folder
 
400
                try:
 
401
                        self.__can_save()
 
402
                        self.__swap_folder = mkdtemp(suffix="scribes",
 
403
                                                                                prefix=".Scribes",
 
404
                                                                                dir=home_folder)
 
405
                        # Create a randomly generated temporary file in the
 
406
                        # temporary folder created above.
 
407
                        self.__swap_file = NamedTemporaryFile(mode="w+",
 
408
                                                                                                suffix="Scribes",
 
409
                                                                                                prefix="scribes",
 
410
                                                                                                dir=self.__swap_folder)
 
411
                        from gnomevfs import get_uri_from_local_path
 
412
                        self.__swap_uri = get_uri_from_local_path(self.__swap_file.name)
 
413
                except:
 
414
                        from Exceptions import SwapError
 
415
                        raise SwapError
 
416
                return
 
417
 
 
418
        def __delete_swap_folder_and_file(self):
 
419
                """
 
420
                Remove swap location.
 
421
 
 
422
                @param self: Reference to the FileSaver instance.
 
423
                @type self: A FileSaver object.
 
424
                """
 
425
                try:
 
426
                        self.__swap_file.close()
 
427
                        from os import rmdir
 
428
                        rmdir(self.__swap_folder)
 
429
                except:
 
430
                        pass
 
431
                return
 
432
 
 
433
        def __check_swap_folder_and_file(self):
 
434
                """
 
435
                Check if swap location and temporary file exists.
 
436
 
 
437
                @param self: Reference to the FileSaver instance.
 
438
                @type self: A FileSaver object.
 
439
                """
 
440
                from gnomevfs import exists
 
441
                from operator import not_
 
442
                if not_(exists(self.__swap_uri)):
 
443
                        print "Woops swap area not found: creating..."
 
444
                        self.__create_swap_folder_and_file()
 
445
                return
 
446
 
 
447
        def __determine_action(self, is_closing):
 
448
                """
 
449
                Determine what saving action to take for files that have not
 
450
                yet been saved to disk.
 
451
 
 
452
                @param self: Reference to the FileSaver instance.
 
453
                @type self: A FileSaver object.
 
454
 
 
455
                @param is_closing: True if this is the last save call.
 
456
                @type is_closing: A Boolean object.
 
457
                """
 
458
                self.__can_save()
 
459
                if self.__editor.uri: return
 
460
                if is_closing:
 
 
b"\t\t\t# Create a new file and save it if the text editor's buffer"
 
461
                        # contains a document but there is no document to save.
 
462
                        self.__can_quit = True
 
463
                        self.__editor.create_new_file()
 
464
                        self.save_file()
 
465
                else:
 
466
                        # Show the save dialog if the text editor's buffer is empty and
 
467
                        # there is no document to save.
 
468
                        self.__editor.triggermanager.trigger("show_save_dialog")
 
469
                from Exceptions import DoNothingError
 
470
                raise DoNothingError
 
471
                return
 
472
 
 
473
        def __update_file_info(self):
 
474
                """
 
475
                Update file information.
 
476
 
 
477
                @param self: Reference to the FileSaver instance.
 
478
                @type self: A FileSaver object.
 
479
                """
 
480
                try:
 
481
                        self.__file_info = None
 
482
                        fileinfo = self.__get_file_info()
 
483
                        from gnomevfs import FILE_INFO_FIELDS_PERMISSIONS
 
484
                        if fileinfo.valid_fields & FILE_INFO_FIELDS_PERMISSIONS:
 
485
                                self.__file_info = fileinfo
 
486
                except:
 
487
                        pass
 
488
                return
 
489
 
 
490
        def __get_file_info(self):
 
491
                """
 
492
                Get file information about the file.
 
493
 
 
494
                @param self: Reference to the FileSaver instance.
 
495
                @type self: A FileSaver object.
 
496
 
 
497
                @return: An object containing file information.
 
498
                @rtype: A gnomevfs.FILE_INFO object.
 
499
                """
 
500
                try:
 
501
                        from operator import is_
 
502
                        if is_(self.__editor.uri, None): return None
 
503
                        if is_(self.__editor.uri.startswith("file:///"), False): return None
 
504
                        from gnomevfs import get_file_info
 
505
                        fileinfo = get_file_info(self.__editor.uri)
 
506
                except:
 
 
b'\t\t\treturn None'
 
 
b'\t\treturn fileinfo'
 
507
 
 
508
        def __error(self, message):
 
509
                """
 
510
                Show error message.
 
511
 
 
512
                @param self: Reference to the FileSaver instance.
 
513
                @type self: A FileSaver object.
 
514
 
 
515
                @param message: An error message.
 
516
                @type message: A String object.
 
517
                """
 
518
                self.__file_info = None
 
519
                from internationalization import msg0477, msg0468
 
520
                title = msg0477 % (self.__editor.uri)
 
521
                message_id = self.__editor.feedback.set_modal_message(msg0468, "error")
 
522
                self.__editor.show_error_message(message, title, self.__editor.window)
 
523
                self.__editor.emit("save-error", str(self.__editor.uri))
 
524
                self.__editor.feedback.unset_modal_message(message_id)
 
525
                return
 
526
 
 
527
        def __save_file_timeout_cb(self):
 
528
                """
 
529
                Callback to the save timeout add function.
 
530
 
 
531
                @param self: Reference to the FileSaver instance.
 
532
                @type self: A FileSaver object.
 
533
                """
 
534
                from gobject import idle_add
 
535
                idle_add(self.save_file)
 
536
                return False
 
537
 
 
538
        def __remove_save_timer(self):
 
539
                """
 
540
                Remove timer.
 
541
 
 
542
                @param self: Reference to the FileSaver instance.
 
543
                @type self: A FileSaver object.
 
544
                """
 
545
                try:
 
546
                        from gobject import source_remove
 
547
                        source_remove(self.__save_timer)
 
548
                except:
 
549
                        pass
 
550
                return
 
551
 
 
552
        def __destroy(self):
 
553
                """
 
554
                Destroy instance of this class.
 
555
 
 
556
                @param self: Reference to the FileSaver instance.
 
557
                @type self: A FileSaver object.
 
558
                """
 
559
                if self.__modification_dialog: self.__modification_dialog.destroy()
 
560
                self.__stop_monitoring_file()
 
561
                self.__encoding_manager.destroy()
 
562
                self.__remove_save_timer()
 
563
                self.__delete_swap_folder_and_file()
 
564
                from utils import disconnect_signal
 
565
                disconnect_signal(self.__signal_id_1, self.__editor)
 
566
                disconnect_signal(self.__signal_id_2, self.__editor)
 
567
                disconnect_signal(self.__signal_id_3, self.__editor)
 
568
                disconnect_signal(self.__signal_id_4, self.__editor)
 
569
                disconnect_signal(self.__signal_id_5, self.__editor)
 
570
                disconnect_signal(self.__signal_id_6, self.__editor)
 
571
                disconnect_signal(self.__signal_id_7, self.__editor.textbuffer)
 
572
                disconnect_signal(self.__signal_id_8, self.__editor)
 
573
                disconnect_signal(self.__signal_id_9, self.__editor)
 
574
                disconnect_signal(self.__signal_id_10, self.__editor)
 
575
                disconnect_signal(self.__signal_id_11, self.__editor)
 
576
                disconnect_signal(self.__signal_id_12, self.__editor)
 
577
                self.__editor.unregister_termination_id(self.__termination_id)
 
578
                del self
 
579
                self = None
 
580
                return
 
581
 
 
582
        def __precompile_methods(self):
 
583
                """
 
584
                Use Psyco to optimize some methods.
 
585
 
 
586
                @param self: Reference to the FileSaver instance.
 
587
                @type self: A FileSaver object.
 
588
                """
 
589
                try:
 
590
                        from psyco import bind
 
591
                        bind(self.__encode_text)
 
592
                        bind(self.__save_file)
 
593
                        bind(self.__check_permissions)
 
594
                        bind(self.__can_save)
 
595
                        bind(self.__get_file_info)
 
596
                except ImportError:
 
597
                        pass
 
598
                return
 
599
 
 
600
        def __check_last_modification(self):
 
601
                """
 
602
                Check if the document has been modified by another application.
 
603
 
 
604
                @param self: Reference to the FileSaver instance.
 
605
                @type self: A FileSaver object.
 
606
                """
 
607
                from operator import not_, is_, eq
 
608
                fileinfo = self.__get_file_info()
 
609
                if not_(fileinfo): return
 
610
                if is_(self.__last_modification_time, None): return
 
611
                if eq(self.__last_modification_time, fileinfo.mtime): return
 
612
                from Exceptions import FileModificationError
 
613
                raise FileModificationError
 
614
                return
 
615
 
 
616
        def __start_monitoring_file(self):
 
617
                from operator import not_
 
618
                if not_(self.__editor.uri.startswith("file:///")): return
 
619
                # Monitor database for changes.
 
620
                self.__update_modification_time()
 
621
                from gnomevfs import monitor_add, MONITOR_FILE
 
622
                self.__monitor_id = monitor_add(self.__editor.uri, MONITOR_FILE,
 
623
                                        self.__file_changed_cb)
 
624
                return
 
625
 
 
626
        def __stop_monitoring_file(self):
 
627
                from gnomevfs import monitor_cancel
 
628
                from operator import not_
 
629
                if not_(self.__monitor_id): return
 
630
                monitor_cancel(self.__monitor_id)
 
631
                return
 
632
 
 
633
        def __show_modification_dialog(self):
 
634
                """
 
635
                Show a dialog when another application modifies this file.
 
636
 
 
637
                @param self: Reference to the FileSaver instance.
 
638
                @type self: A FileSaver object.
 
639
                """
 
640
                try:
 
641
                        self.__modification_dialog.show()
 
642
                except AttributeError:
 
643
                        from ModificationDialog import ModificationDialog
 
644
                        self.__modification_dialog = ModificationDialog(self, self.__editor)
 
645
                        self.__modification_dialog.show()
 
646
                return
 
647
 
 
648
        def __can_save(self):
 
649
                """
 
650
                Check whether or not to save the current file.
 
651
 
 
652
                @param self: Reference to the FileSaver instance.
 
653
                @type self: A FileSaver object.
 
654
                """
 
655
                from Exceptions import DoNothingError
 
656
                if self.__do_not_save: raise DoNothingError
 
657
                return
 
658
 
 
659
########################################################################
 
660
#
 
661
#                       Signal and Event Handlers
 
662
#
 
663
########################################################################
 
664
 
 
665
        def __close_document_cb(self, editor):
 
666
                """
 
667
                Handles callback when the "close-document" signal is emitted.
 
668
 
 
669
                @param self: Reference to the FileSaver instance.
 
670
                @type self: A FileSaver object.
 
671
 
 
672
                @param editor: Reference to the text editor.
 
673
                @type editor: An Editor object.
 
674
                """
 
675
                self.__can_quit = True
 
676
                self.__remove_save_timer()
 
677
                from operator import not_
 
678
                if not_(editor.file_is_saved):
 
679
                        from gobject import idle_add
 
680
                        idle_add(self.save_file, True)
 
681
                else:
 
682
                        self.__destroy()
 
683
                return
 
684
 
 
685
        def __close_document_no_save_cb(self, editor):
 
686
                """
 
687
                Handles callback when the "close-document-no-save" signal is emitted.
 
688
 
 
689
                @param self: Reference to the FileSaver instance.
 
690
                @type self: A FileSaver object.
 
691
 
 
692
                @param editor: Reference to the text editor.
 
693
                @type editor: An Editor object.
 
694
                """
 
695
                self.__remove_save_timer()
 
696
                self.__destroy()
 
697
                return
 
698
 
 
699
        def __checking_document_cb(self, editor, uri):
 
700
                """
 
701
                Handles callback when the "checking-document" signal is emitted.
 
702
 
 
703
                @param self: Reference to the FileSaver instance.
 
704
                @type self: A FileSaver object.
 
705
 
 
706
                @param editor: Reference to the text editor.
 
707
                @type editor: An Editor object.
 
708
 
 
709
                @param uri: Reference to a file.
 
710
                @type uri: A String object.
 
711
                """
 
712
                editor.textbuffer.handler_block(self.__signal_id_7)
 
713
                return
 
714
 
 
715
        def __loaded_document_cb(self, editor, uri):
 
716
                """
 
717
                Handles callback when the "loaded-document" signal is emitted.
 
718
 
 
719
                @param self: Reference to the FileSaver instance.
 
720
                @type self: A FileSaver object.
 
721
 
 
722
                @param editor: Reference to the text editor.
 
723
                @type editor: An Editor object.
 
724
 
 
725
                @param uri: Reference to a file.
 
726
                @type uri: A String object.
 
727
                """
 
728
                editor.textbuffer.handler_unblock(self.__signal_id_7)
 
729
                self.__start_monitoring_file()
 
730
                return
 
731
 
 
732
        def __load_error_cb(self, editor, uri):
 
733
                """
 
734
                Handles callback when the "load-error" signal is emitted.
 
735
 
 
736
                @param self: Reference to the FileSaver instance.
 
737
                @type self: A FileSaver object.
 
738
 
 
739
                @param editor: Reference to the text editor.
 
740
                @type editor: An Editor object.
 
741
 
 
742
                @param uri: Reference to a file.
 
743
                @type uri: A String object.
 
744
                """
 
745
                editor.textbuffer.handler_unblock(self.__signal_id_7)
 
746
                return
 
747
 
 
748
        def __save_document_cb(self, editor):
 
749
                """
 
750
                Handles callback when the "save-document" signal is emitted.
 
751
 
 
752
                @param self: Reference to the FileSaver instance.
 
753
                @type self: A FileSaver object.
 
754
 
 
755
                @param editor: Reference to the text editor.
 
756
                @type editor: An Editor object.
 
757
                """
 
758
                from gobject import idle_add
 
759
                idle_add(self.save_file)
 
760
                return
 
761
 
 
762
        def __saved_document_cb(self, editor, uri):
 
763
                """
 
764
                Handles callback when the "saved-document" signal is emitted.
 
765
 
 
766
                @param self: Reference to the FileSaver instance.
 
767
                @type self: A FileSaver object.
 
768
 
 
769
                @param editor: Reference to the text editor.
 
770
                @type editor: An Editor object.
 
771
 
 
772
                @param uri: Reference to a file.
 
773
                @type uri: A String object.
 
774
                """
 
775
                self.__remove_save_timer()
 
776
                return
 
777
 
 
778
        def __modified_changed_cb(self, textbuffer):
 
779
                """
 
780
                Handles callback when the "modified-changed" signal is emitted.
 
781
 
 
782
                @param self: Reference to the FileSaver instance.
 
783
                @type self: A FileSaver object.
 
784
 
 
785
                @param textbuffer: Reference to the text editor's buffer.
 
786
                @type textbuffer: A ScribesTextBuffer object.
 
787
                """
 
788
                if textbuffer.get_modified() is False: return False
 
789
                self.__editor.emit("modified-document")
 
790
                if self.__editor.uri is None: return False
 
791
                from gobject import timeout_add, PRIORITY_LOW
 
792
                self.__save_timer = timeout_add(21000, self.__save_file_timeout_cb, priority=PRIORITY_LOW)
 
793
                return False
 
794
 
 
795
        def __reload_document_cb(self, *args):
 
796
                self.__remove_save_timer()
 
797
                return
 
798
 
 
799
        def __rename_document_cb(self, editor, uri):
 
800
                """
 
801
                Handles callback when the "rename-document" signal is emitted.
 
802
 
 
803
                @param self: Reference to the FileSaver instance.
 
804
                @type self: A FileSaver object.
 
805
 
 
806
                @param editor: Reference to the text editor.
 
807
                @type editor: An Editor object.
 
808
 
 
809
                @param uri: Reference to a file.
 
810
                @type uri: A String object.
 
811
                """
 
812
                self.__stop_monitoring_file()
 
813
                if self.__editor.is_readonly: self.__toggle_readonly = True
 
814
                self.__should_rename = True
 
815
                from gobject import idle_add
 
816
                idle_add(self.save_file)
 
817
                return
 
818
 
 
819
        def __updated_cb(self, store, name):
 
820
                from operator import ne
 
821
                if ne(name, "EncodingManager"): return
 
822
                self.__encoding_manager = store.get_object("EncodingManager")
 
823
                return
 
824
 
 
825
        def __check_encoding_manager(self):
 
826
                if self.__encoding_manager: return False
 
827
                self.__encoding_manager = self.__editor.store.get_object("EncodingManager")
 
828
                return True
 
829
 
 
830
        def __file_changed_cb(self, monitor_uri, info_uri, event_type):
 
831
                """
 
832
                Handles callback when the current file is modified.
 
833
 
 
834
                @param self: Reference to the AutoReplaceManager instance.
 
835
                @type self: An AutoReplaceManager object.
 
836
 
 
837
                @param monitor_uri: The uri that is monitored.
 
838
                @type monitor_uri: A String object.
 
839
 
 
840
                @param info_uri: The uri that is monitored.
 
841
                @type info_uri: A String object.
 
842
 
 
843
                @param event_type: The type of modification that occured.
 
844
                @type event_type: A gnomevfs.MONITOR_EVENT* object.
 
845
                """
 
846
                from gnomevfs import MONITOR_EVENT_DELETED
 
847
                from gnomevfs import MONITOR_EVENT_CREATED
 
848
                from gnomevfs import MONITOR_EVENT_CHANGED
 
849
                if event_type in [MONITOR_EVENT_DELETED, MONITOR_EVENT_CREATED, MONITOR_EVENT_CHANGED]:
 
850
                        if self.__can_quit: return
 
851
                        fileinfo = self.__get_file_info()
 
852
                        from operator import not_, eq
 
853
                        if not_(fileinfo): return
 
854
                        if eq(self.__last_modification_time, fileinfo.mtime): return
 
855
                        self.__do_not_save = True
 
856
                        self.__show_modification_dialog()
 
857
                return
 
858
 
 
859
        def __renamed_document_cb(self, *args):
 
860
                self.__start_monitoring_file()
 
861
                return