1### Copyright (C) 2002-2006 Stephen Kennedy <stevek@gnome.org> 2### Copyright (C) 2011 Kai Willadsen <kai.willadsen@gmail.com> 3 4### This program is free software; you can redistribute it and/or modify 5### it under the terms of the GNU General Public License as published by 6### the Free Software Foundation; either version 2 of the License, or 7### (at your option) any later version. 8 9### This program is distributed in the hope that it will be useful, 10### but WITHOUT ANY WARRANTY; without even the implied warranty of 11### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12### GNU General Public License for more details. 13 14### You should have received a copy of the GNU General Public License 15### along with this program; if not, write to the Free Software 16### Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 17### USA. 18 19 20import subprocess 21import sys 22 23import gobject 24import gio 25import gtk 26 27from . import task 28 29from gettext import gettext as _ 30 31 32class MeldDoc(gobject.GObject): 33 """Base class for documents in the meld application. 34 """ 35 36 __gsignals__ = { 37 'label-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, 38 (gobject.TYPE_STRING, gobject.TYPE_STRING)), 39 'file-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, 40 (gobject.TYPE_STRING,)), 41 'create-diff': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, 42 (gobject.TYPE_PYOBJECT, 43 gobject.TYPE_PYOBJECT)), 44 'status-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, 45 (gobject.TYPE_PYOBJECT,)), 46 'current-diff-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, 47 ()), 48 'next-diff-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, 49 (bool, bool)), 50 } 51 52 def __init__(self, prefs): 53 gobject.GObject.__init__(self) 54 self.scheduler = task.FifoScheduler() 55 self.prefs = prefs 56 self.prefs.notify_add(self.on_preference_changed) 57 self.num_panes = 0 58 self.label_text = _("untitled") 59 self.tooltip_text = _("untitled") 60 self.status_info_labels = [] 61 62 def get_info_widgets(self): 63 return self.status_info_labels 64 65 def get_comparison(self): 66 """Get the comparison type and path(s) being compared""" 67 pass 68 69 def save(self): 70 pass 71 72 def save_as(self): 73 pass 74 75 def stop(self): 76 if self.scheduler.tasks_pending(): 77 self.scheduler.remove_task(self.scheduler.get_current_task()) 78 79 def _open_files(self, selected, line=0): 80 query_attrs = ",".join((gio.FILE_ATTRIBUTE_STANDARD_TYPE, 81 gio.FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE)) 82 83 def os_open(path): 84 if not path: 85 return 86 if sys.platform == "win32": 87 subprocess.Popen(["start", path], shell=True) 88 elif sys.platform == "darwin": 89 subprocess.Popen(["open", path]) 90 else: 91 subprocess.Popen(["xdg-open", path]) 92 93 def open_cb(source, result, *data): 94 info = source.query_info_finish(result) 95 file_type = info.get_file_type() 96 if file_type == gio.FILE_TYPE_DIRECTORY: 97 os_open(source.get_path()) 98 elif file_type == gio.FILE_TYPE_REGULAR: 99 content_type = info.get_content_type() 100 path = source.get_path() 101 # FIXME: Content types are broken on Windows with current gio 102 if gio.content_type_is_a(content_type, "text/plain") or \ 103 sys.platform == "win32": 104 editor = self.prefs.get_editor_command(path, line) 105 if editor: 106 subprocess.Popen(editor) 107 else: 108 os_open(path) 109 else: 110 os_open(path) 111 else: 112 # TODO: Add some kind of 'failed to open' notification 113 pass 114 115 for f in [gio.File(s) for s in selected]: 116 f.query_info_async(query_attrs, open_cb) 117 118 def open_external(self): 119 pass 120 121 def on_refresh_activate(self, *extra): 122 pass 123 124 def on_find_activate(self, *extra): 125 pass 126 127 def on_find_next_activate(self, *extra): 128 pass 129 130 def on_find_previous_activate(self, *extra): 131 pass 132 133 def on_replace_activate(self, *extra): 134 pass 135 136 def on_preference_changed(self, key, value): 137 pass 138 139 def on_file_changed(self, filename): 140 pass 141 142 def label_changed(self): 143 self.emit("label-changed", self.label_text, self.tooltip_text) 144 145 def set_labels(self, lst): 146 pass 147 148 def on_container_switch_in_event(self, uimanager): 149 """Called when the container app switches to this tab. 150 """ 151 self.ui_merge_id = uimanager.add_ui_from_file(self.ui_file) 152 uimanager.insert_action_group(self.actiongroup, -1) 153 self.popup_menu = uimanager.get_widget("/Popup") 154 uimanager.ensure_update() 155 if hasattr(self, "focus_pane") and self.focus_pane: 156 self.scheduler.add_task(self.focus_pane.grab_focus) 157 158 def on_container_switch_out_event(self, uimanager): 159 """Called when the container app switches away from this tab. 160 """ 161 uimanager.remove_action_group(self.actiongroup) 162 uimanager.remove_ui(self.ui_merge_id) 163 164 def on_delete_event(self, appquit=0): 165 """Called when the docs container is about to close. 166 167 A doc normally returns gtk.RESPONSE_OK, but may instead return 168 gtk.RESPONSE_CANCEL to request that the container not delete it. 169 """ 170 return gtk.RESPONSE_OK 171