/b-gtk/fix-viz

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/b-gtk/fix-viz
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
1
# Copyright (C) 2006 by Szilveszter Farkas (Phanatic) <szilveszter.farkas@gmail.com>
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
import os
18
import sys
195.6.1 by Szilveszter Farkas (Phanatic)
Implemented sortable columns, and there are also some new columns
19
import time
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
20
89 by Jelmer Vernooij
Rename OliveBranch -> BranchDialog.
21
# gettext support
22
import gettext
23
gettext.install('olive-gtk')
24
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
25
try:
26
    import pygtk
27
    pygtk.require("2.0")
28
except:
29
    pass
0.8.92 by Szilveszter Farkas (Phanatic)
Cleanup Jelmer's changes.
30
195.6.1 by Szilveszter Farkas (Phanatic)
Implemented sortable columns, and there are also some new columns
31
import gobject
0.13.11 by Jelmer Vernooij
Bunch of small fixes, cleanups and simplifications.
32
import gtk
33
import gtk.gdk
34
import gtk.glade
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
35
0.8.92 by Szilveszter Farkas (Phanatic)
Cleanup Jelmer's changes.
36
from bzrlib.branch import Branch
126.1.11 by Szilveszter Farkas (Phanatic)
Add revert all functionality and fix another regression.
37
import bzrlib.errors as bzrerrors
157.1.6 by Aaron Bentley
Defer importing branchwin to avoid cairo import errors
38
from bzrlib.lazy_import import lazy_import
195.1.10 by Szilveszter Farkas (Phanatic)
Showing progress of loading remote branch.
39
from bzrlib.ui import ui_factory
0.13.13 by Jelmer Vernooij
Update TODO
40
from bzrlib.workingtree import WorkingTree
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
41
151 by Jelmer Vernooij
Move dialog to top-level directory.
42
from bzrlib.plugins.gtk.dialog import error_dialog, info_dialog, warning_dialog
43
from bzrlib.plugins.gtk.errors import show_bzr_error
93.1.12 by Alexander Belchenko
Names XML files with GUI resources obtained via olive/guifiles.py
44
from guifiles import GLADEFILENAME
0.8.92 by Szilveszter Farkas (Phanatic)
Cleanup Jelmer's changes.
45
151 by Jelmer Vernooij
Move dialog to top-level directory.
46
from bzrlib.plugins.gtk.diff import DiffWindow
157.1.6 by Aaron Bentley
Defer importing branchwin to avoid cairo import errors
47
lazy_import(globals(), """
48
from bzrlib.plugins.gtk.viz import branchwin
49
""")
149 by Jelmer Vernooij
Move diff to top-level directory as well.
50
from bzrlib.plugins.gtk.annotate.gannotate import GAnnotateWindow
51
from bzrlib.plugins.gtk.annotate.config import GAnnotateConfig
52
from bzrlib.plugins.gtk.commit import CommitDialog
126.1.26 by Szilveszter Farkas (Phanatic)
Added Conflicts entry to the Branch menu.
53
from bzrlib.plugins.gtk.conflicts import ConflictsDialog
188.1.3 by Szilveszter Farkas (Phanatic)
Added the new Initialize dialog to Olive.
54
from bzrlib.plugins.gtk.initialize import InitDialog
149 by Jelmer Vernooij
Move diff to top-level directory as well.
55
from bzrlib.plugins.gtk.push import PushDialog
195.1.24 by Szilveszter Farkas (Phanatic)
The History feature kinda works now, but still needs some polishing.
56
from bzrlib.plugins.gtk.revbrowser import RevisionBrowser
93.1.3 by Alexander Belchenko
olive is able to successfully work without installation
57
218 by Jelmer Vernooij
Move olive about dialog into olive.
58
def about():
59
    """ Display the AboutDialog. """
60
    from bzrlib.plugins.gtk import __version__
61
    from bzrlib.plugins.gtk.olive.guifiles import GLADEFILENAME
62
63
    # Load AboutDialog description
64
    dglade = gtk.glade.XML(GLADEFILENAME, 'aboutdialog')
65
    dialog = dglade.get_widget('aboutdialog')
66
67
    # Set version
68
    dialog.set_version(__version__)
69
70
    dialog.run()
71
    # Destroy the dialog
72
    dialog.destroy()
73
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
74
class OliveGtk:
75
    """ The main Olive GTK frontend class. This is called when launching the
76
    program. """
77
    
78
    def __init__(self):
93.1.6 by Alexander Belchenko
detecting name of glade file doing in separate module (olive.gladefile)
79
        self.toplevel = gtk.glade.XML(GLADEFILENAME, 'window_main', 'olive-gtk')
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
80
        self.window = self.toplevel.get_widget('window_main')
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
81
        self.pref = Preferences()
102 by Szilveszter Farkas (Phanatic)
Show current path in the statusbar.
82
        self.path = None
0.13.13 by Jelmer Vernooij
Update TODO
83
84
        # Initialize the statusbar
85
        self.statusbar = self.toplevel.get_widget('statusbar')
86
        self.context_id = self.statusbar.get_context_id('olive')
87
        
88
        # Get the main window
89
        self.window_main = self.toplevel.get_widget('window_main')
90
        # Get the HPaned
91
        self.hpaned_main = self.toplevel.get_widget('hpaned_main')
92
        # Get the TreeViews
93
        self.treeview_left = self.toplevel.get_widget('treeview_left')
94
        self.treeview_right = self.toplevel.get_widget('treeview_right')
95
        # Get some important menu items
96
        self.menuitem_add_files = self.toplevel.get_widget('menuitem_add_files')
97
        self.menuitem_remove_files = self.toplevel.get_widget('menuitem_remove_file')
98
        self.menuitem_file_make_directory = self.toplevel.get_widget('menuitem_file_make_directory')
99
        self.menuitem_file_rename = self.toplevel.get_widget('menuitem_file_rename')
100
        self.menuitem_file_move = self.toplevel.get_widget('menuitem_file_move')
124 by Szilveszter Farkas (Phanatic)
Implemented annotate functionality (Fixed: #73786).
101
        self.menuitem_file_annotate = self.toplevel.get_widget('menuitem_file_annotate')
0.13.13 by Jelmer Vernooij
Update TODO
102
        self.menuitem_view_show_hidden_files = self.toplevel.get_widget('menuitem_view_show_hidden_files')
103
        self.menuitem_branch = self.toplevel.get_widget('menuitem_branch')
104
        self.menuitem_branch_init = self.toplevel.get_widget('menuitem_branch_initialize')
105
        self.menuitem_branch_get = self.toplevel.get_widget('menuitem_branch_get')
106
        self.menuitem_branch_checkout = self.toplevel.get_widget('menuitem_branch_checkout')
107
        self.menuitem_branch_pull = self.toplevel.get_widget('menuitem_branch_pull')
108
        self.menuitem_branch_push = self.toplevel.get_widget('menuitem_branch_push')
126.1.11 by Szilveszter Farkas (Phanatic)
Add revert all functionality and fix another regression.
109
        self.menuitem_branch_revert = self.toplevel.get_widget('menuitem_branch_revert')
93 by Szilveszter Farkas (Phanatic)
Began to implement Merge dialog.
110
        self.menuitem_branch_merge = self.toplevel.get_widget('menuitem_branch_merge')
0.13.13 by Jelmer Vernooij
Update TODO
111
        self.menuitem_branch_commit = self.toplevel.get_widget('menuitem_branch_commit')
190.1.8 by Szilveszter Farkas (Phanatic)
Added Tags entry to the Branch menu in Olive.
112
        self.menuitem_branch_tags = self.toplevel.get_widget('menuitem_branch_tags')
0.13.13 by Jelmer Vernooij
Update TODO
113
        self.menuitem_branch_status = self.toplevel.get_widget('menuitem_branch_status')
114
        self.menuitem_branch_missing = self.toplevel.get_widget('menuitem_branch_missing_revisions')
126.1.26 by Szilveszter Farkas (Phanatic)
Added Conflicts entry to the Branch menu.
115
        self.menuitem_branch_conflicts = self.toplevel.get_widget('menuitem_branch_conflicts')
0.13.13 by Jelmer Vernooij
Update TODO
116
        self.menuitem_stats = self.toplevel.get_widget('menuitem_stats')
117
        self.menuitem_stats_diff = self.toplevel.get_widget('menuitem_stats_diff')
118
        self.menuitem_stats_log = self.toplevel.get_widget('menuitem_stats_log')
119
        # Get some toolbuttons
120
        #self.menutoolbutton_diff = self.toplevel.get_widget('menutoolbutton_diff')
121
        self.toolbutton_diff = self.toplevel.get_widget('toolbutton_diff')
122
        self.toolbutton_log = self.toplevel.get_widget('toolbutton_log')
123
        self.toolbutton_commit = self.toplevel.get_widget('toolbutton_commit')
124
        self.toolbutton_pull = self.toplevel.get_widget('toolbutton_pull')
125
        self.toolbutton_push = self.toplevel.get_widget('toolbutton_push')
126
        # Get the drive selector
127
        self.combobox_drive = gtk.combo_box_new_text()
128
        self.combobox_drive.connect("changed", self._refresh_drives)
129
        
195.6.1 by Szilveszter Farkas (Phanatic)
Implemented sortable columns, and there are also some new columns
130
        # Get the navigation widgets
195.6.4 by Szilveszter Farkas (Phanatic)
The Windows drive selector was moved to the location bar.
131
        self.hbox_location = self.toplevel.get_widget('hbox_location')
195.6.1 by Szilveszter Farkas (Phanatic)
Implemented sortable columns, and there are also some new columns
132
        self.button_location_up = self.toplevel.get_widget('button_location_up')
133
        self.button_location_jump = self.toplevel.get_widget('button_location_jump')
134
        self.entry_location = self.toplevel.get_widget('entry_location')
135
        self.image_location_error = self.toplevel.get_widget('image_location_error')
136
        
195.1.24 by Szilveszter Farkas (Phanatic)
The History feature kinda works now, but still needs some polishing.
137
        # Get the History widgets
138
        self.check_history = self.toplevel.get_widget('checkbutton_history')
139
        self.entry_history = self.toplevel.get_widget('entry_history_revno')
140
        self.button_history = self.toplevel.get_widget('button_history_browse')
141
        
0.13.13 by Jelmer Vernooij
Update TODO
142
        self.vbox_main_right = self.toplevel.get_widget('vbox_main_right')
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
143
        
144
        # Dictionary for signal_autoconnect
145
        dic = { "on_window_main_destroy": gtk.main_quit,
0.13.13 by Jelmer Vernooij
Update TODO
146
                "on_window_main_delete_event": self.on_window_main_delete_event,
147
                "on_quit_activate": self.on_window_main_delete_event,
148
                "on_about_activate": self.on_about_activate,
149
                "on_menuitem_add_files_activate": self.on_menuitem_add_files_activate,
150
                "on_menuitem_remove_file_activate": self.on_menuitem_remove_file_activate,
151
                "on_menuitem_file_make_directory_activate": self.on_menuitem_file_make_directory_activate,
152
                "on_menuitem_file_move_activate": self.on_menuitem_file_move_activate,
153
                "on_menuitem_file_rename_activate": self.on_menuitem_file_rename_activate,
124 by Szilveszter Farkas (Phanatic)
Implemented annotate functionality (Fixed: #73786).
154
                "on_menuitem_file_annotate_activate": self.on_menuitem_file_annotate_activate,
0.13.13 by Jelmer Vernooij
Update TODO
155
                "on_menuitem_view_show_hidden_files_activate": self.on_menuitem_view_show_hidden_files_activate,
156
                "on_menuitem_view_refresh_activate": self.on_menuitem_view_refresh_activate,
157
                "on_menuitem_branch_initialize_activate": self.on_menuitem_branch_initialize_activate,
158
                "on_menuitem_branch_get_activate": self.on_menuitem_branch_get_activate,
159
                "on_menuitem_branch_checkout_activate": self.on_menuitem_branch_checkout_activate,
126.1.11 by Szilveszter Farkas (Phanatic)
Add revert all functionality and fix another regression.
160
                "on_menuitem_branch_revert_activate": self.on_menuitem_branch_revert_activate,
93 by Szilveszter Farkas (Phanatic)
Began to implement Merge dialog.
161
                "on_menuitem_branch_merge_activate": self.on_menuitem_branch_merge_activate,
0.13.13 by Jelmer Vernooij
Update TODO
162
                "on_menuitem_branch_commit_activate": self.on_menuitem_branch_commit_activate,
163
                "on_menuitem_branch_push_activate": self.on_menuitem_branch_push_activate,
164
                "on_menuitem_branch_pull_activate": self.on_menuitem_branch_pull_activate,
190.1.8 by Szilveszter Farkas (Phanatic)
Added Tags entry to the Branch menu in Olive.
165
                "on_menuitem_branch_tags_activate": self.on_menuitem_branch_tags_activate,
0.13.13 by Jelmer Vernooij
Update TODO
166
                "on_menuitem_branch_status_activate": self.on_menuitem_branch_status_activate,
167
                "on_menuitem_branch_missing_revisions_activate": self.on_menuitem_branch_missing_revisions_activate,
126.1.26 by Szilveszter Farkas (Phanatic)
Added Conflicts entry to the Branch menu.
168
                "on_menuitem_branch_conflicts_activate": self.on_menuitem_branch_conflicts_activate,
0.13.13 by Jelmer Vernooij
Update TODO
169
                "on_menuitem_stats_diff_activate": self.on_menuitem_stats_diff_activate,
170
                "on_menuitem_stats_log_activate": self.on_menuitem_stats_log_activate,
171
                "on_menuitem_stats_infos_activate": self.on_menuitem_stats_infos_activate,
172
                "on_toolbutton_refresh_clicked": self.on_menuitem_view_refresh_activate,
173
                "on_toolbutton_log_clicked": self.on_menuitem_stats_log_activate,
174
                #"on_menutoolbutton_diff_clicked": self.on_menuitem_stats_diff_activate,
175
                "on_toolbutton_diff_clicked": self.on_menuitem_stats_diff_activate,
176
                "on_toolbutton_commit_clicked": self.on_menuitem_branch_commit_activate,
177
                "on_toolbutton_pull_clicked": self.on_menuitem_branch_pull_activate,
178
                "on_toolbutton_push_clicked": self.on_menuitem_branch_push_activate,
179
                "on_treeview_right_button_press_event": self.on_treeview_right_button_press_event,
180
                "on_treeview_right_row_activated": self.on_treeview_right_row_activated,
181
                "on_treeview_left_button_press_event": self.on_treeview_left_button_press_event,
195.6.1 by Szilveszter Farkas (Phanatic)
Implemented sortable columns, and there are also some new columns
182
                "on_treeview_left_row_activated": self.on_treeview_left_row_activated,
183
                "on_button_location_up_clicked": self.on_button_location_up_clicked,
184
                "on_button_location_jump_clicked": self.on_button_location_jump_clicked,
195.1.24 by Szilveszter Farkas (Phanatic)
The History feature kinda works now, but still needs some polishing.
185
                "on_entry_location_key_press_event": self.on_entry_location_key_press_event,
186
                "on_checkbutton_history_toggled": self.on_checkbutton_history_toggled,
187
                "on_entry_history_revno_key_press_event": self.on_entry_history_revno_key_press_event,
188
                "on_button_history_browse_clicked": self.on_button_history_browse_clicked
195.6.1 by Szilveszter Farkas (Phanatic)
Implemented sortable columns, and there are also some new columns
189
            }
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
190
        
191
        # Connect the signals to the handlers
192
        self.toplevel.signal_autoconnect(dic)
193
        
126.1.4 by Szilveszter Farkas (Phanatic)
Set default drive letter (Fixed: #67924)
194
        self._just_started = True
195
        
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
196
        # Apply window size and position
197
        width = self.pref.get_preference('window_width', 'int')
198
        height = self.pref.get_preference('window_height', 'int')
199
        self.window.resize(width, height)
200
        x = self.pref.get_preference('window_x', 'int')
201
        y = self.pref.get_preference('window_y', 'int')
202
        self.window.move(x, y)
203
        # Apply paned position
204
        pos = self.pref.get_preference('paned_position', 'int')
0.13.13 by Jelmer Vernooij
Update TODO
205
        self.hpaned_main.set_position(pos)
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
206
        
207
        # Apply menu to the toolbutton
208
        #menubutton = self.toplevel.get_widget('menutoolbutton_diff')
209
        #menubutton.set_menu(handler.menu.toolbar_diff)
210
        
211
        # Now we can show the window
212
        self.window.show()
213
        
214
        # Show drive selector if under Win32
215
        if sys.platform == 'win32':
195.6.4 by Szilveszter Farkas (Phanatic)
The Windows drive selector was moved to the location bar.
216
            self.hbox_location.pack_start(self.combobox_drive, False, False, 0)
217
            self.hbox_location.reorder_child(self.combobox_drive, 1)
0.13.13 by Jelmer Vernooij
Update TODO
218
            self.combobox_drive.show()
219
            self.gen_hard_selector()
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
220
        
221
        self._load_left()
0.13.13 by Jelmer Vernooij
Update TODO
222
223
        # Apply menu state
224
        self.menuitem_view_show_hidden_files.set_active(self.pref.get_preference('dotted_files', 'bool'))
225
195.1.9 by Szilveszter Farkas (Phanatic)
Browsing remote branches works. Still have to optimize some stuff.
226
        # We're starting local
227
        self.remote = False
228
        self.remote_branch = None
229
        self.remote_path = None
195.1.24 by Szilveszter Farkas (Phanatic)
The History feature kinda works now, but still needs some polishing.
230
        self.remote_revision = None
195.1.9 by Szilveszter Farkas (Phanatic)
Browsing remote branches works. Still have to optimize some stuff.
231
        
0.13.13 by Jelmer Vernooij
Update TODO
232
        self.set_path(os.getcwd())
0.8.92 by Szilveszter Farkas (Phanatic)
Cleanup Jelmer's changes.
233
        self._load_right()
126.1.4 by Szilveszter Farkas (Phanatic)
Set default drive letter (Fixed: #67924)
234
        
235
        self._just_started = False
0.13.13 by Jelmer Vernooij
Update TODO
236
195.1.24 by Szilveszter Farkas (Phanatic)
The History feature kinda works now, but still needs some polishing.
237
    def set_path(self, path, force_remote=False):
0.13.13 by Jelmer Vernooij
Update TODO
238
        self.notbranch = False
102 by Szilveszter Farkas (Phanatic)
Show current path in the statusbar.
239
        
195.1.24 by Szilveszter Farkas (Phanatic)
The History feature kinda works now, but still needs some polishing.
240
        if force_remote:
241
            # Forcing remote mode (reading data from inventory)
195.1.16 by Szilveszter Farkas (Phanatic)
Switching between local and remote locations fixed.
242
            self._show_stock_image(gtk.STOCK_DISCONNECT)
243
            try:
244
                br = Branch.open_containing(path)[0]
245
            except bzrerrors.NotBranchError:
246
                self._show_stock_image(gtk.STOCK_DIALOG_ERROR)
195.1.24 by Szilveszter Farkas (Phanatic)
The History feature kinda works now, but still needs some polishing.
247
                self.check_history.set_active(False)
248
                self.check_history.set_sensitive(False)
195.1.16 by Szilveszter Farkas (Phanatic)
Switching between local and remote locations fixed.
249
                return False
250
            except bzrerrors.UnsupportedProtocol:
251
                self._show_stock_image(gtk.STOCK_DIALOG_ERROR)
195.1.24 by Szilveszter Farkas (Phanatic)
The History feature kinda works now, but still needs some polishing.
252
                self.check_history.set_active(False)
253
                self.check_history.set_sensitive(False)
195.1.16 by Szilveszter Farkas (Phanatic)
Switching between local and remote locations fixed.
254
                return False
255
            
256
            self._show_stock_image(gtk.STOCK_CONNECT)
257
            
258
            self.remote = True
259
           
195.1.9 by Szilveszter Farkas (Phanatic)
Browsing remote branches works. Still have to optimize some stuff.
260
            # We're remote
261
            self.remote_branch, self.remote_path = Branch.open_containing(path)
262
            
195.1.24 by Szilveszter Farkas (Phanatic)
The History feature kinda works now, but still needs some polishing.
263
            if self.remote_revision is None:
195.1.25 by Szilveszter Farkas (Phanatic)
Fixed some minor things and added file_id to the list model.
264
                self.remote_revision = self.remote_branch.last_revision()
265
            
266
            self.remote_entries = self.remote_branch.repository.get_inventory(self.remote_revision).entries()
195.1.9 by Szilveszter Farkas (Phanatic)
Browsing remote branches works. Still have to optimize some stuff.
267
            
268
            if len(self.remote_path) == 0:
195.1.14 by Szilveszter Farkas (Phanatic)
Fixed the determination of tree root.
269
                self.remote_parent = self.remote_branch.repository.get_inventory(self.remote_branch.last_revision()).iter_entries_by_dir().next()[1].file_id
195.1.9 by Szilveszter Farkas (Phanatic)
Browsing remote branches works. Still have to optimize some stuff.
270
            else:
271
                for (name, type) in self.remote_entries:
272
                    if name == self.remote_path:
273
                        self.remote_parent = type.file_id
274
                        break
275
            
276
            if not path.endswith('/'):
277
                path += '/'
278
            
279
            if self.remote_branch.base == path:
195.6.1 by Szilveszter Farkas (Phanatic)
Implemented sortable columns, and there are also some new columns
280
                self.button_location_up.set_sensitive(False)
281
            else:
282
                self.button_location_up.set_sensitive(True)
195.1.24 by Szilveszter Farkas (Phanatic)
The History feature kinda works now, but still needs some polishing.
283
        else:
284
            if os.path.isdir(path):
285
                self.image_location_error.destroy()
286
                self.remote = False
287
                
288
                # We're local
289
                try:
290
                    self.wt, self.wtpath = WorkingTree.open_containing(path)
291
                except (bzrerrors.NotBranchError, bzrerrors.NoWorkingTree):
292
                    self.notbranch = True
293
                
294
                # If we're in the root, we cannot go up anymore
295
                if sys.platform == 'win32':
296
                    drive, tail = os.path.splitdrive(path)
297
                    if tail in ('', '/', '\\'):
298
                        self.button_location_up.set_sensitive(False)
299
                    else:
300
                        self.button_location_up.set_sensitive(True)
301
                else:
302
                    if self.path == '/':
303
                        self.button_location_up.set_sensitive(False)
304
                    else:
305
                        self.button_location_up.set_sensitive(True)
306
            elif not os.path.isfile(path):
307
                # Doesn't seem to be a file nor a directory, trying to open a
308
                # remote location
309
                self._show_stock_image(gtk.STOCK_DISCONNECT)
310
                try:
311
                    br = Branch.open_containing(path)[0]
312
                except bzrerrors.NotBranchError:
313
                    self._show_stock_image(gtk.STOCK_DIALOG_ERROR)
314
                    self.check_history.set_active(False)
315
                    self.check_history.set_sensitive(False)
316
                    return False
317
                except bzrerrors.UnsupportedProtocol:
318
                    self._show_stock_image(gtk.STOCK_DIALOG_ERROR)
319
                    self.check_history.set_active(False)
320
                    self.check_history.set_sensitive(False)
321
                    return False
322
                
323
                self._show_stock_image(gtk.STOCK_CONNECT)
324
                
325
                self.remote = True
326
               
327
                # We're remote
328
                self.remote_branch, self.remote_path = Branch.open_containing(path)
329
                
330
                if self.remote_revision is None:
195.1.25 by Szilveszter Farkas (Phanatic)
Fixed some minor things and added file_id to the list model.
331
                    self.remote_revision = self.remote_branch.last_revision()
332
                
333
                self.remote_entries = self.remote_branch.repository.get_inventory(self.remote_revision).entries()
195.1.24 by Szilveszter Farkas (Phanatic)
The History feature kinda works now, but still needs some polishing.
334
                
335
                if len(self.remote_path) == 0:
336
                    self.remote_parent = self.remote_branch.repository.get_inventory(self.remote_branch.last_revision()).iter_entries_by_dir().next()[1].file_id
337
                else:
338
                    for (name, type) in self.remote_entries:
339
                        if name == self.remote_path:
340
                            self.remote_parent = type.file_id
341
                            break
342
                
343
                if not path.endswith('/'):
344
                    path += '/'
345
                
346
                if self.remote_branch.base == path:
347
                    self.button_location_up.set_sensitive(False)
348
                else:
349
                    self.button_location_up.set_sensitive(True)
350
        
351
        if self.notbranch:
352
            self.check_history.set_active(False)
353
            self.check_history.set_sensitive(False)
354
        else:
355
            self.check_history.set_sensitive(True)
195.1.16 by Szilveszter Farkas (Phanatic)
Switching between local and remote locations fixed.
356
        
357
        self.statusbar.push(self.context_id, path)
358
        self.entry_location.set_text(path)
359
        self.path = path
360
        return True
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
361
0.13.13 by Jelmer Vernooij
Update TODO
362
    def get_path(self):
195.1.9 by Szilveszter Farkas (Phanatic)
Browsing remote branches works. Still have to optimize some stuff.
363
        if not self.remote:
364
            return self.path
365
        else:
366
            # Remote mode
367
            if len(self.remote_path) > 0:
368
                return self.remote_branch.base + self.remote_path + '/'
369
            else:
370
                return self.remote_branch.base
0.13.13 by Jelmer Vernooij
Update TODO
371
   
372
    def on_about_activate(self, widget):
373
        about()
195.1.24 by Szilveszter Farkas (Phanatic)
The History feature kinda works now, but still needs some polishing.
374
    
375
    def on_button_history_browse_clicked(self, widget):
376
        """ Browse for revision button handler. """
377
        if self.remote:
378
            br = self.remote_branch
379
        else:
380
            br = self.wt.branch
381
            
382
        revb = RevisionBrowser(br, self.window)
383
        response = revb.run()
384
        if response != gtk.RESPONSE_NONE:
385
            revb.hide()
386
        
387
            if response == gtk.RESPONSE_OK:
388
                if revb.selected_revno is not None:
389
                    self.entry_history.set_text(revb.selected_revno)
390
            
391
            revb.destroy()
392
    
393
    def on_button_location_jump_clicked(self, widget):
394
        """ Location Jump button handler. """
395
        location = self.entry_location.get_text()
396
        
397
        if self.set_path(location):
398
            self.refresh_right()
399
    
195.6.1 by Szilveszter Farkas (Phanatic)
Implemented sortable columns, and there are also some new columns
400
    def on_button_location_up_clicked(self, widget):
401
        """ Location Up button handler. """
195.1.9 by Szilveszter Farkas (Phanatic)
Browsing remote branches works. Still have to optimize some stuff.
402
        if not self.remote:
403
            # Local mode
404
            self.set_path(os.path.split(self.get_path())[0])
405
        else:
406
            # Remote mode
407
            delim = '/'
408
            newpath = delim.join(self.get_path().split(delim)[:-2])
409
            newpath += '/'
410
            self.set_path(newpath)
411
195.6.1 by Szilveszter Farkas (Phanatic)
Implemented sortable columns, and there are also some new columns
412
        self.refresh_right()
413
    
195.1.24 by Szilveszter Farkas (Phanatic)
The History feature kinda works now, but still needs some polishing.
414
    def on_checkbutton_history_toggled(self, widget):
415
        """ History Mode toggle handler. """
416
        if self.check_history.get_active():
417
            # History Mode activated
418
            self.entry_history.set_sensitive(True)
419
            self.button_history.set_sensitive(True)
420
        else:
421
            # History Mode deactivated
422
            self.entry_history.set_sensitive(False)
423
            self.button_history.set_sensitive(False)
424
    
195.1.25 by Szilveszter Farkas (Phanatic)
Fixed some minor things and added file_id to the list model.
425
    @show_bzr_error
195.1.24 by Szilveszter Farkas (Phanatic)
The History feature kinda works now, but still needs some polishing.
426
    def on_entry_history_revno_key_press_event(self, widget, event):
427
        """ Key pressed handler for the history entry. """
428
        if event.keyval == 65293:
429
            # Return was hit, so we have to load that specific revision
430
            # Emulate being remote, so inventory should be used
431
            path = self.get_path()
432
            if not self.remote:
433
                self.remote = True
434
                self.remote_branch = self.wt.branch
435
            
436
            revno = int(self.entry_history.get_text())
437
            self.remote_revision = self.remote_branch.get_rev_id(revno)
438
            if self.set_path(path, True):
439
                self.refresh_right()
195.6.1 by Szilveszter Farkas (Phanatic)
Implemented sortable columns, and there are also some new columns
440
    
441
    def on_entry_location_key_press_event(self, widget, event):
442
        """ Key pressed handler for the location entry. """
443
        if event.keyval == 65293:
444
            # Return was hit, so we have to jump
445
            self.on_button_location_jump_clicked(widget)
446
    
0.13.13 by Jelmer Vernooij
Update TODO
447
    def on_menuitem_add_files_activate(self, widget):
448
        """ Add file(s)... menu handler. """
449
        from add import OliveAdd
450
        add = OliveAdd(self.wt, self.wtpath, self.get_selected_right())
451
        add.display()
452
    
453
    def on_menuitem_branch_get_activate(self, widget):
454
        """ Branch/Get... menu handler. """
154 by Jelmer Vernooij
Add trivial generic class for storing URL history.
455
        from bzrlib.plugins.gtk.branch import BranchDialog
195.1.21 by Szilveszter Farkas (Phanatic)
Some small modifications to Branch, Checkout and Info to support remote branches.
456
        
457
        if self.remote:
458
            branch = BranchDialog(os.getcwd(), self.window, self.remote_branch.base)
459
        else:
460
            branch = BranchDialog(self.get_path(), self.window)
126.1.15 by Szilveszter Farkas (Phanatic)
Refactoring the Branch dialog. We also have a Revision Browser now.
461
        response = branch.run()
462
        if response != gtk.RESPONSE_NONE:
463
            branch.hide()
195.1.21 by Szilveszter Farkas (Phanatic)
Some small modifications to Branch, Checkout and Info to support remote branches.
464
            
126.1.15 by Szilveszter Farkas (Phanatic)
Refactoring the Branch dialog. We also have a Revision Browser now.
465
            if response == gtk.RESPONSE_OK:
466
                self.refresh_right()
467
            
468
            branch.destroy()
0.13.13 by Jelmer Vernooij
Update TODO
469
    
470
    def on_menuitem_branch_checkout_activate(self, widget):
471
        """ Branch/Checkout... menu handler. """
154 by Jelmer Vernooij
Add trivial generic class for storing URL history.
472
        from bzrlib.plugins.gtk.checkout import CheckoutDialog
195.1.21 by Szilveszter Farkas (Phanatic)
Some small modifications to Branch, Checkout and Info to support remote branches.
473
        
474
        if self.remote:
475
            checkout = CheckoutDialog(os.getcwd(), self.window, self.remote_branch.base)
476
        else:
477
            checkout = CheckoutDialog(self.get_path(), self.window)
126.1.18 by Szilveszter Farkas (Phanatic)
Improved Branch dialog. Refactored Checkout dialog.
478
        response = checkout.run()
479
        if response != gtk.RESPONSE_NONE:
480
            checkout.hide()
481
        
482
            if response == gtk.RESPONSE_OK:
483
                self.refresh_right()
484
            
485
            checkout.destroy()
0.13.13 by Jelmer Vernooij
Update TODO
486
    
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
487
    @show_bzr_error
0.13.13 by Jelmer Vernooij
Update TODO
488
    def on_menuitem_branch_commit_activate(self, widget):
489
        """ Branch/Commit... menu handler. """
135 by Jelmer Vernooij
Throw out the old CommitDialog code and use the new code instead, also for 'gcommit'.
490
        commit = CommitDialog(self.wt, self.wtpath, self.notbranch, self.get_selected_right(), self.window)
126.1.1 by Szilveszter Farkas (Phanatic)
New Commit dialog implementation (no more Glade).
491
        response = commit.run()
492
        if response != gtk.RESPONSE_NONE:
493
            commit.hide()
494
        
495
            if response == gtk.RESPONSE_OK:
496
                self.refresh_right()
497
            
498
            commit.destroy()
0.13.13 by Jelmer Vernooij
Update TODO
499
    
126.1.26 by Szilveszter Farkas (Phanatic)
Added Conflicts entry to the Branch menu.
500
    def on_menuitem_branch_conflicts_activate(self, widget):
501
        """ Branch/Conflicts... menu handler. """
502
        conflicts = ConflictsDialog(self.wt, self.window)
503
        response = conflicts.run()
504
        if response != gtk.RESPONSE_NONE:
505
            conflicts.destroy()
506
    
93 by Szilveszter Farkas (Phanatic)
Began to implement Merge dialog.
507
    def on_menuitem_branch_merge_activate(self, widget):
508
        """ Branch/Merge... menu handler. """
154 by Jelmer Vernooij
Add trivial generic class for storing URL history.
509
        from bzrlib.plugins.gtk.merge import MergeDialog
122 by Szilveszter Farkas (Phanatic)
Do not allow merge if there are local changes (Fixed: #73770).
510
        
511
        if self.check_for_changes():
512
            error_dialog(_('There are local changes in the branch'),
513
                         _('Please commit or revert the changes before merging.'))
514
        else:
515
            merge = MergeDialog(self.wt, self.wtpath)
516
            merge.display()
93 by Szilveszter Farkas (Phanatic)
Began to implement Merge dialog.
517
155 by Jelmer Vernooij
Fix a couple of smaller bugs.
518
    @show_bzr_error
0.13.13 by Jelmer Vernooij
Update TODO
519
    def on_menuitem_branch_missing_revisions_activate(self, widget):
520
        """ Branch/Missing revisions menu handler. """
521
        local_branch = self.wt.branch
522
        
523
        other_branch = local_branch.get_parent()
524
        if other_branch is None:
525
            error_dialog(_('Parent location is unknown'),
0.8.94 by Szilveszter Farkas (Phanatic)
Cleanups: bookmarks and sensitivity.
526
                         _('Cannot determine missing revisions if no parent location is known.'))
0.13.13 by Jelmer Vernooij
Update TODO
527
            return
528
        
529
        remote_branch = Branch.open(other_branch)
530
        
531
        if remote_branch.base == local_branch.base:
532
            remote_branch = local_branch
533
534
        ret = len(local_branch.missing_revisions(remote_branch))
535
536
        if ret > 0:
537
            info_dialog(_('There are missing revisions'),
0.8.94 by Szilveszter Farkas (Phanatic)
Cleanups: bookmarks and sensitivity.
538
                        _('%d revision(s) missing.') % ret)
0.13.13 by Jelmer Vernooij
Update TODO
539
        else:
540
            info_dialog(_('Local branch up to date'),
0.8.94 by Szilveszter Farkas (Phanatic)
Cleanups: bookmarks and sensitivity.
541
                        _('There are no missing revisions.'))
0.13.13 by Jelmer Vernooij
Update TODO
542
132 by Jelmer Vernooij
Use decorator for catching and showing bzr-gtk errors graphically. Eventually, this should go away and should be handled by the ui factory.
543
    @show_bzr_error
0.13.13 by Jelmer Vernooij
Update TODO
544
    def on_menuitem_branch_pull_activate(self, widget):
545
        """ Branch/Pull menu handler. """
546
        branch_to = self.wt.branch
547
548
        location = branch_to.get_parent()
549
        if location is None:
550
            error_dialog(_('Parent location is unknown'),
551
                                     _('Pulling is not possible until there is a parent location.'))
552
            return
553
132 by Jelmer Vernooij
Use decorator for catching and showing bzr-gtk errors graphically. Eventually, this should go away and should be handled by the ui factory.
554
        branch_from = Branch.open(location)
0.13.13 by Jelmer Vernooij
Update TODO
555
556
        if branch_to.get_parent() is None:
557
            branch_to.set_parent(branch_from.base)
558
0.14.14 by Alexander Belchenko
get number of pulled revision: it's return value of branch.pull() method
559
        ret = branch_to.pull(branch_from)
0.13.13 by Jelmer Vernooij
Update TODO
560
        
561
        info_dialog(_('Pull successful'), _('%d revision(s) pulled.') % ret)
562
    
563
    def on_menuitem_branch_push_activate(self, widget):
564
        """ Branch/Push... menu handler. """
126.1.19 by Szilveszter Farkas (Phanatic)
Refactored the Push dialog. Add 'gpush' command.
565
        push = PushDialog(self.wt.branch, self.window)
566
        response = push.run()
567
        if response != gtk.RESPONSE_NONE:
568
            push.destroy()
0.13.13 by Jelmer Vernooij
Update TODO
569
    
126.1.11 by Szilveszter Farkas (Phanatic)
Add revert all functionality and fix another regression.
570
    @show_bzr_error
571
    def on_menuitem_branch_revert_activate(self, widget):
572
        """ Branch/Revert all changes menu handler. """
573
        ret = self.wt.revert([])
574
        if ret:
575
            warning_dialog(_('Conflicts detected'),
576
                           _('Please have a look at the working tree before continuing.'))
577
        else:
578
            info_dialog(_('Revert successful'),
579
                        _('All files reverted to last revision.'))
580
        self.refresh_right()
581
    
0.13.13 by Jelmer Vernooij
Update TODO
582
    def on_menuitem_branch_status_activate(self, widget):
583
        """ Branch/Status... menu handler. """
156 by Jelmer Vernooij
Move status to the top-level, remove its use of glade and allow double-clicking on entries to get at the diff for a file.
584
        from bzrlib.plugins.gtk.status import StatusDialog
585
        status = StatusDialog(self.wt, self.wtpath)
195.3.1 by Szilveszter Farkas (Phanatic)
Fixed Branch -> Status in Olive (no more traceback).
586
        response = status.run()
587
        if response != gtk.RESPONSE_NONE:
588
            status.destroy()
0.13.13 by Jelmer Vernooij
Update TODO
589
    
590
    def on_menuitem_branch_initialize_activate(self, widget):
591
        """ Initialize current directory. """
188.1.3 by Szilveszter Farkas (Phanatic)
Added the new Initialize dialog to Olive.
592
        init = InitDialog(self.path, self.window)
593
        response = init.run()
594
        if response != gtk.RESPONSE_NONE:
595
            init.hide()
0.8.92 by Szilveszter Farkas (Phanatic)
Cleanup Jelmer's changes.
596
        
188.1.3 by Szilveszter Farkas (Phanatic)
Added the new Initialize dialog to Olive.
597
            if response == gtk.RESPONSE_OK:
598
                self.refresh_right()
599
            
600
            init.destroy()
0.13.13 by Jelmer Vernooij
Update TODO
601
        
190.1.8 by Szilveszter Farkas (Phanatic)
Added Tags entry to the Branch menu in Olive.
602
    def on_menuitem_branch_tags_activate(self, widget):
603
        """ Branch/Tags... menu handler. """
604
        from bzrlib.plugins.gtk.tags import TagsWindow
195.1.21 by Szilveszter Farkas (Phanatic)
Some small modifications to Branch, Checkout and Info to support remote branches.
605
        if not self.remote:
606
            window = TagsWindow(self.wt.branch, self.window)
607
        else:
608
            window = TagsWindow(self.remote_branch, self.window)
190.1.8 by Szilveszter Farkas (Phanatic)
Added Tags entry to the Branch menu in Olive.
609
        window.show()
610
    
124 by Szilveszter Farkas (Phanatic)
Implemented annotate functionality (Fixed: #73786).
611
    def on_menuitem_file_annotate_activate(self, widget):
612
        """ File/Annotate... menu handler. """
613
        if self.get_selected_right() is None:
614
            error_dialog(_('No file was selected'),
615
                         _('Please select a file from the list.'))
616
            return
617
        
618
        branch = self.wt.branch
619
        file_id = self.wt.path2id(self.wt.relpath(os.path.join(self.path, self.get_selected_right())))
620
        
621
        window = GAnnotateWindow(all=False, plain=False)
622
        window.set_title(os.path.join(self.path, self.get_selected_right()) + " - Annotate")
623
        config = GAnnotateConfig(window)
624
        window.show()
625
        branch.lock_read()
626
        try:
66.2.17 by Aaron Bentley
Update olive to use current bzr.dev API. Used _repo_relpath. Bad phanatic!
627
            window.annotate(self.wt, branch, file_id)
124 by Szilveszter Farkas (Phanatic)
Implemented annotate functionality (Fixed: #73786).
628
        finally:
629
            branch.unlock()
630
    
0.13.13 by Jelmer Vernooij
Update TODO
631
    def on_menuitem_file_make_directory_activate(self, widget):
632
        """ File/Make directory... menu handler. """
633
        from mkdir import OliveMkdir
634
        mkdir = OliveMkdir(self.wt, self.wtpath)
635
        mkdir.display()
636
    
637
    def on_menuitem_file_move_activate(self, widget):
638
        """ File/Move... menu handler. """
639
        from move import OliveMove
640
        move = OliveMove(self.wt, self.wtpath, self.get_selected_right())
641
        move.display()
642
    
643
    def on_menuitem_file_rename_activate(self, widget):
644
        """ File/Rename... menu handler. """
645
        from rename import OliveRename
646
        rename = OliveRename(self.wt, self.wtpath, self.get_selected_right())
647
        rename.display()
648
649
    def on_menuitem_remove_file_activate(self, widget):
650
        """ Remove (unversion) selected file. """
120 by Szilveszter Farkas (Phanatic)
Use OliveRemoveDialog class instead of OliveRemove.
651
        from remove import OliveRemoveDialog
652
        remove = OliveRemoveDialog(self.wt, self.wtpath,
653
                                   selected=self.get_selected_right(),
121 by Szilveszter Farkas (Phanatic)
Use OliveBookmarkDialog instead of OliveBookmark.
654
                                   parent=self.window)
120 by Szilveszter Farkas (Phanatic)
Use OliveRemoveDialog class instead of OliveRemove.
655
        response = remove.run()
656
        
657
        if response != gtk.RESPONSE_NONE:
658
            remove.hide()
659
        
660
            if response == gtk.RESPONSE_OK:
661
                self.set_path(self.path)
662
                self.refresh_right()
663
            
664
            remove.destroy()
0.13.13 by Jelmer Vernooij
Update TODO
665
    
666
    def on_menuitem_stats_diff_activate(self, widget):
667
        """ Statistics/Differences... menu handler. """
668
        window = DiffWindow()
669
        parent_tree = self.wt.branch.repository.revision_tree(self.wt.branch.last_revision())
670
        window.set_diff(self.wt.branch.nick, self.wt, parent_tree)
671
        window.show()
672
    
673
    def on_menuitem_stats_infos_activate(self, widget):
674
        """ Statistics/Informations... menu handler. """
675
        from info import OliveInfo
195.1.21 by Szilveszter Farkas (Phanatic)
Some small modifications to Branch, Checkout and Info to support remote branches.
676
        if self.remote:
677
            info = OliveInfo(self.remote_branch)
678
        else:
679
            info = OliveInfo(self.wt.branch)
0.13.13 by Jelmer Vernooij
Update TODO
680
        info.display()
681
    
682
    def on_menuitem_stats_log_activate(self, widget):
683
        """ Statistics/Log... menu handler. """
157.1.6 by Aaron Bentley
Defer importing branchwin to avoid cairo import errors
684
        window = branchwin.BranchWindow()
195.1.20 by Szilveszter Farkas (Phanatic)
Make bzrk working with remote branches.
685
        if not self.remote:
686
            window.set_branch(self.wt.branch, self.wt.branch.last_revision(), None)
687
        else:
688
            window.set_branch(self.remote_branch, self.remote_branch.last_revision(), None)
0.13.13 by Jelmer Vernooij
Update TODO
689
        window.show()
690
    
691
    def on_menuitem_view_refresh_activate(self, widget):
692
        """ View/Refresh menu handler. """
693
        # Refresh the left pane
694
        self.refresh_left()
695
        # Refresh the right pane
696
        self.refresh_right()
697
   
698
    def on_menuitem_view_show_hidden_files_activate(self, widget):
699
        """ View/Show hidden files menu handler. """
0.8.92 by Szilveszter Farkas (Phanatic)
Cleanup Jelmer's changes.
700
        self.pref.set_preference('dotted_files', widget.get_active())
102 by Szilveszter Farkas (Phanatic)
Show current path in the statusbar.
701
        if self.path is not None:
702
            self.refresh_right()
0.13.13 by Jelmer Vernooij
Update TODO
703
704
    def on_treeview_left_button_press_event(self, widget, event):
705
        """ Occurs when somebody right-clicks in the bookmark list. """
706
        if event.button == 3:
707
            # Don't show context with nothing selected
708
            if self.get_selected_left() == None:
709
                return
710
0.8.93 by Szilveszter Farkas (Phanatic)
Some further cleanups. More to come.
711
            # Create a menu
712
            from menu import OliveMenu
121 by Szilveszter Farkas (Phanatic)
Use OliveBookmarkDialog instead of OliveBookmark.
713
            menu = OliveMenu(path=self.get_path(),
714
                             selected=self.get_selected_left(),
715
                             app=self)
0.8.93 by Szilveszter Farkas (Phanatic)
Some further cleanups. More to come.
716
            
717
            menu.left_context_menu().popup(None, None, None, 0,
718
                                           event.time)
0.8.94 by Szilveszter Farkas (Phanatic)
Cleanups: bookmarks and sensitivity.
719
0.13.13 by Jelmer Vernooij
Update TODO
720
    def on_treeview_left_row_activated(self, treeview, path, view_column):
721
        """ Occurs when somebody double-clicks or enters an item in the
722
        bookmark list. """
723
724
        newdir = self.get_selected_left()
725
        if newdir == None:
726
            return
727
195.1.16 by Szilveszter Farkas (Phanatic)
Switching between local and remote locations fixed.
728
        if self.set_path(newdir):
729
            self.refresh_right()
0.8.94 by Szilveszter Farkas (Phanatic)
Cleanups: bookmarks and sensitivity.
730
0.13.13 by Jelmer Vernooij
Update TODO
731
    def on_treeview_right_button_press_event(self, widget, event):
732
        """ Occurs when somebody right-clicks in the file list. """
733
        if event.button == 3:
0.8.92 by Szilveszter Farkas (Phanatic)
Cleanup Jelmer's changes.
734
            # Create a menu
735
            from menu import OliveMenu
120 by Szilveszter Farkas (Phanatic)
Use OliveRemoveDialog class instead of OliveRemove.
736
            menu = OliveMenu(path=self.get_path(),
737
                             selected=self.get_selected_right(),
738
                             app=self)
0.13.13 by Jelmer Vernooij
Update TODO
739
            # get the menu items
195.1.21 by Szilveszter Farkas (Phanatic)
Some small modifications to Branch, Checkout and Info to support remote branches.
740
            m_open = menu.ui.get_widget('/context_right/open')
0.8.92 by Szilveszter Farkas (Phanatic)
Cleanup Jelmer's changes.
741
            m_add = menu.ui.get_widget('/context_right/add')
742
            m_remove = menu.ui.get_widget('/context_right/remove')
117 by Szilveszter Farkas (Phanatic)
Rename put into context menu (Fixed: #73774).
743
            m_rename = menu.ui.get_widget('/context_right/rename')
126.1.12 by Szilveszter Farkas (Phanatic)
Added revert functionality to the context menu.
744
            m_revert = menu.ui.get_widget('/context_right/revert')
0.8.92 by Szilveszter Farkas (Phanatic)
Cleanup Jelmer's changes.
745
            m_commit = menu.ui.get_widget('/context_right/commit')
195.1.21 by Szilveszter Farkas (Phanatic)
Some small modifications to Branch, Checkout and Info to support remote branches.
746
            m_annotate = menu.ui.get_widget('/context_right/annotate')
0.8.92 by Szilveszter Farkas (Phanatic)
Cleanup Jelmer's changes.
747
            m_diff = menu.ui.get_widget('/context_right/diff')
0.13.13 by Jelmer Vernooij
Update TODO
748
            # check if we're in a branch
749
            try:
750
                from bzrlib.branch import Branch
751
                Branch.open_containing(self.get_path())
195.1.21 by Szilveszter Farkas (Phanatic)
Some small modifications to Branch, Checkout and Info to support remote branches.
752
                if self.remote:
753
                    m_open.set_sensitive(False)
754
                    m_add.set_sensitive(False)
755
                    m_remove.set_sensitive(False)
756
                    m_rename.set_sensitive(False)
757
                    m_revert.set_sensitive(False)
758
                    m_commit.set_sensitive(False)
759
                    m_annotate.set_sensitive(False)
760
                    m_diff.set_sensitive(False)
761
                else:
762
                    m_open.set_sensitive(True)
763
                    m_add.set_sensitive(True)
764
                    m_remove.set_sensitive(True)
765
                    m_rename.set_sensitive(True)
766
                    m_revert.set_sensitive(True)
767
                    m_commit.set_sensitive(True)
768
                    m_annotate.set_sensitive(True)
769
                    m_diff.set_sensitive(True)
126.1.11 by Szilveszter Farkas (Phanatic)
Add revert all functionality and fix another regression.
770
            except bzrerrors.NotBranchError:
195.1.21 by Szilveszter Farkas (Phanatic)
Some small modifications to Branch, Checkout and Info to support remote branches.
771
                m_open.set_sensitive(True)
0.13.13 by Jelmer Vernooij
Update TODO
772
                m_add.set_sensitive(False)
773
                m_remove.set_sensitive(False)
117 by Szilveszter Farkas (Phanatic)
Rename put into context menu (Fixed: #73774).
774
                m_rename.set_sensitive(False)
126.1.12 by Szilveszter Farkas (Phanatic)
Added revert functionality to the context menu.
775
                m_revert.set_sensitive(False)
0.13.13 by Jelmer Vernooij
Update TODO
776
                m_commit.set_sensitive(False)
195.1.21 by Szilveszter Farkas (Phanatic)
Some small modifications to Branch, Checkout and Info to support remote branches.
777
                m_annotate.set_sensitive(False)
0.13.13 by Jelmer Vernooij
Update TODO
778
                m_diff.set_sensitive(False)
101 by Szilveszter Farkas (Phanatic)
Show/hide hidden files should work now.
779
195.1.24 by Szilveszter Farkas (Phanatic)
The History feature kinda works now, but still needs some polishing.
780
            if not self.remote:
781
                menu.right_context_menu().popup(None, None, None, 0,
782
                                                event.time)
783
            else:
784
                menu.remote_context_menu().popup(None, None, None, 0,
785
                                                 event.time)
0.13.13 by Jelmer Vernooij
Update TODO
786
        
787
    def on_treeview_right_row_activated(self, treeview, path, view_column):
788
        """ Occurs when somebody double-clicks or enters an item in the
789
        file list. """
0.8.92 by Szilveszter Farkas (Phanatic)
Cleanup Jelmer's changes.
790
        from launch import launch
791
        
0.13.13 by Jelmer Vernooij
Update TODO
792
        newdir = self.get_selected_right()
793
        
195.1.9 by Szilveszter Farkas (Phanatic)
Browsing remote branches works. Still have to optimize some stuff.
794
        if not self.remote:
795
            # We're local
796
            if newdir == '..':
797
                self.set_path(os.path.split(self.get_path())[0])
798
            else:
799
                fullpath = os.path.join(self.get_path(), newdir)
800
                if os.path.isdir(fullpath):
801
                    # selected item is an existant directory
802
                    self.set_path(fullpath)
803
                else:
804
                    launch(fullpath)
0.13.13 by Jelmer Vernooij
Update TODO
805
        else:
195.1.9 by Szilveszter Farkas (Phanatic)
Browsing remote branches works. Still have to optimize some stuff.
806
            # We're remote
807
            if self._is_remote_dir(self.get_path() + newdir):
808
                self.set_path(self.get_path() + newdir)
0.13.13 by Jelmer Vernooij
Update TODO
809
        
810
        self.refresh_right()
811
    
812
    def on_window_main_delete_event(self, widget, event=None):
813
        """ Do some stuff before exiting. """
814
        width, height = self.window_main.get_size()
815
        self.pref.set_preference('window_width', width)
816
        self.pref.set_preference('window_height', height)
817
        x, y = self.window_main.get_position()
818
        self.pref.set_preference('window_x', x)
819
        self.pref.set_preference('window_y', y)
820
        self.pref.set_preference('paned_position',
101 by Szilveszter Farkas (Phanatic)
Show/hide hidden files should work now.
821
                                 self.hpaned_main.get_position())
0.13.13 by Jelmer Vernooij
Update TODO
822
        
823
        self.pref.write()
824
        self.window_main.destroy()
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
825
        
826
    def _load_left(self):
827
        """ Load data into the left panel. (Bookmarks) """
828
        # Create TreeStore
829
        treestore = gtk.TreeStore(str, str)
830
        
831
        # Get bookmarks
0.13.13 by Jelmer Vernooij
Update TODO
832
        bookmarks = self.pref.get_bookmarks()
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
833
        
834
        # Add them to the TreeStore
835
        titer = treestore.append(None, [_('Bookmarks'), None])
836
        for item in bookmarks:
0.13.13 by Jelmer Vernooij
Update TODO
837
            title = self.pref.get_bookmark_title(item)
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
838
            treestore.append(titer, [title, item])
839
        
840
        # Create the column and add it to the TreeView
841
        self.treeview_left.set_model(treestore)
842
        tvcolumn_bookmark = gtk.TreeViewColumn(_('Bookmark'))
843
        self.treeview_left.append_column(tvcolumn_bookmark)
844
        
845
        # Set up the cells
846
        cell = gtk.CellRendererText()
847
        tvcolumn_bookmark.pack_start(cell, True)
848
        tvcolumn_bookmark.add_attribute(cell, 'text', 0)
849
        
850
        # Expand the tree
851
        self.treeview_left.expand_all()
852
853
    def _load_right(self):
854
        """ Load data into the right panel. (Filelist) """
855
        # Create ListStore
195.1.25 by Szilveszter Farkas (Phanatic)
Fixed some minor things and added file_id to the list model.
856
        # Model: [ icon, dir, name, status text, status, size (int), size (human), mtime (int), mtime (local), fileid]
857
        liststore = gtk.ListStore(gobject.TYPE_STRING,
858
                                  gobject.TYPE_BOOLEAN,
859
                                  gobject.TYPE_STRING,
860
                                  gobject.TYPE_STRING,
861
                                  gobject.TYPE_STRING,
862
                                  gobject.TYPE_INT,
863
                                  gobject.TYPE_STRING,
864
                                  gobject.TYPE_INT,
865
                                  gobject.TYPE_STRING,
866
                                  gobject.TYPE_STRING)
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
867
        
0.14.12 by Alexander Belchenko
updir link (..) added always to the top of directories list
868
        dirs = []
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
869
        files = []
870
        
871
        # Fill the appropriate lists
872
        dotted_files = self.pref.get_preference('dotted_files', 'bool')
0.13.13 by Jelmer Vernooij
Update TODO
873
        for item in os.listdir(self.path):
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
874
            if not dotted_files and item[0] == '.':
875
                continue
0.13.13 by Jelmer Vernooij
Update TODO
876
            if os.path.isdir(self.path + os.sep + item):
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
877
                dirs.append(item)
878
            else:
879
                files.append(item)
880
        
0.13.13 by Jelmer Vernooij
Update TODO
881
        if not self.notbranch:
882
            branch = self.wt.branch
883
            tree2 = self.wt.branch.repository.revision_tree(branch.last_revision())
884
        
885
            delta = self.wt.changes_from(tree2, want_unchanged=True)
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
886
        
887
        # Add'em to the ListStore
195.6.1 by Szilveszter Farkas (Phanatic)
Implemented sortable columns, and there are also some new columns
888
        for item in dirs:
889
            statinfo = os.stat(self.path + os.sep + item)
195.1.25 by Szilveszter Farkas (Phanatic)
Fixed some minor things and added file_id to the list model.
890
            liststore.append([ gtk.STOCK_DIRECTORY,
891
                               True,
892
                               item,
893
                               '',
894
                               '',
895
                               statinfo.st_size,
896
                               self._format_size(statinfo.st_size),
897
                               statinfo.st_mtime,
898
                               self._format_date(statinfo.st_mtime),
899
                               ''])
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
900
        for item in files:
901
            status = 'unknown'
195.1.25 by Szilveszter Farkas (Phanatic)
Fixed some minor things and added file_id to the list model.
902
            fileid = ''
0.13.13 by Jelmer Vernooij
Update TODO
903
            if not self.notbranch:
904
                filename = self.wt.relpath(self.path + os.sep + item)
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
905
                
126.1.39 by Szilveszter Farkas (Phanatic)
Fix the locking issue with Olive (LP: #91522)
906
                try:
907
                    self.wt.lock_read()
908
                    
909
                    for rpath, rpathnew, id, kind, text_modified, meta_modified in delta.renamed:
910
                        if rpathnew == filename:
911
                            status = 'renamed'
195.1.25 by Szilveszter Farkas (Phanatic)
Fixed some minor things and added file_id to the list model.
912
                            fileid = id
126.1.39 by Szilveszter Farkas (Phanatic)
Fix the locking issue with Olive (LP: #91522)
913
                    for rpath, id, kind in delta.added:
914
                        if rpath == filename:
915
                            status = 'added'
195.1.25 by Szilveszter Farkas (Phanatic)
Fixed some minor things and added file_id to the list model.
916
                            fileid = id
126.1.39 by Szilveszter Farkas (Phanatic)
Fix the locking issue with Olive (LP: #91522)
917
                    for rpath, id, kind in delta.removed:
918
                        if rpath == filename:
919
                            status = 'removed'
195.1.25 by Szilveszter Farkas (Phanatic)
Fixed some minor things and added file_id to the list model.
920
                            fileid = id
126.1.39 by Szilveszter Farkas (Phanatic)
Fix the locking issue with Olive (LP: #91522)
921
                    for rpath, id, kind, text_modified, meta_modified in delta.modified:
922
                        if rpath == filename:
923
                            status = 'modified'
195.1.25 by Szilveszter Farkas (Phanatic)
Fixed some minor things and added file_id to the list model.
924
                            fileid = id
126.1.39 by Szilveszter Farkas (Phanatic)
Fix the locking issue with Olive (LP: #91522)
925
                    for rpath, id, kind in delta.unchanged:
926
                        if rpath == filename:
927
                            status = 'unchanged'
195.1.25 by Szilveszter Farkas (Phanatic)
Fixed some minor things and added file_id to the list model.
928
                            fileid = id
126.1.39 by Szilveszter Farkas (Phanatic)
Fix the locking issue with Olive (LP: #91522)
929
                    for rpath, file_class, kind, id, entry in self.wt.list_files():
930
                        if rpath == filename and file_class == 'I':
931
                            status = 'ignored'
932
                finally:
933
                    self.wt.unlock()
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
934
            
935
            if status == 'renamed':
936
                st = _('renamed')
937
            elif status == 'removed':
938
                st = _('removed')
939
            elif status == 'added':
940
                st = _('added')
941
            elif status == 'modified':
942
                st = _('modified')
943
            elif status == 'unchanged':
944
                st = _('unchanged')
123 by Szilveszter Farkas (Phanatic)
Ignored files are no more shown as unknown (Fixed: #67926).
945
            elif status == 'ignored':
946
                st = _('ignored')
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
947
            else:
948
                st = _('unknown')
195.6.1 by Szilveszter Farkas (Phanatic)
Implemented sortable columns, and there are also some new columns
949
            
950
            statinfo = os.stat(self.path + os.sep + item)
195.1.25 by Szilveszter Farkas (Phanatic)
Fixed some minor things and added file_id to the list model.
951
            liststore.append([gtk.STOCK_FILE,
952
                              False,
953
                              item,
954
                              st,
955
                              status,
956
                              statinfo.st_size,
957
                              self._format_size(statinfo.st_size),
958
                              statinfo.st_mtime,
959
                              self._format_date(statinfo.st_mtime),
960
                              fileid])
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
961
        
962
        # Create the columns and add them to the TreeView
963
        self.treeview_right.set_model(liststore)
195.1.17 by Szilveszter Farkas (Phanatic)
Show/hide Status column accordingly.
964
        self._tvcolumn_filename = gtk.TreeViewColumn(_('Filename'))
965
        self._tvcolumn_status = gtk.TreeViewColumn(_('Status'))
966
        self._tvcolumn_size = gtk.TreeViewColumn(_('Size'))
967
        self._tvcolumn_mtime = gtk.TreeViewColumn(_('Last modified'))
968
        self.treeview_right.append_column(self._tvcolumn_filename)
969
        self.treeview_right.append_column(self._tvcolumn_status)
970
        self.treeview_right.append_column(self._tvcolumn_size)
971
        self.treeview_right.append_column(self._tvcolumn_mtime)
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
972
        
973
        # Set up the cells
974
        cellpb = gtk.CellRendererPixbuf()
975
        cell = gtk.CellRendererText()
195.1.17 by Szilveszter Farkas (Phanatic)
Show/hide Status column accordingly.
976
        self._tvcolumn_filename.pack_start(cellpb, False)
977
        self._tvcolumn_filename.pack_start(cell, True)
978
        self._tvcolumn_filename.set_attributes(cellpb, stock_id=0)
979
        self._tvcolumn_filename.add_attribute(cell, 'text', 2)
980
        self._tvcolumn_status.pack_start(cell, True)
981
        self._tvcolumn_status.add_attribute(cell, 'text', 3)
982
        self._tvcolumn_size.pack_start(cell, True)
983
        self._tvcolumn_size.add_attribute(cell, 'text', 6)
984
        self._tvcolumn_mtime.pack_start(cell, True)
985
        self._tvcolumn_mtime.add_attribute(cell, 'text', 8)
195.6.1 by Szilveszter Farkas (Phanatic)
Implemented sortable columns, and there are also some new columns
986
        
987
        # Set up the properties of the TreeView
988
        self.treeview_right.set_headers_visible(True)
989
        self.treeview_right.set_headers_clickable(True)
990
        self.treeview_right.set_search_column(1)
195.1.17 by Szilveszter Farkas (Phanatic)
Show/hide Status column accordingly.
991
        self._tvcolumn_filename.set_resizable(True)
992
        self._tvcolumn_status.set_resizable(True)
993
        self._tvcolumn_size.set_resizable(True)
994
        self._tvcolumn_mtime.set_resizable(True)
195.6.1 by Szilveszter Farkas (Phanatic)
Implemented sortable columns, and there are also some new columns
995
        # Set up sorting
996
        liststore.set_sort_func(13, self._sort_filelist_callback, None)
997
        liststore.set_sort_column_id(13, gtk.SORT_ASCENDING)
195.1.17 by Szilveszter Farkas (Phanatic)
Show/hide Status column accordingly.
998
        self._tvcolumn_filename.set_sort_column_id(13)
999
        self._tvcolumn_status.set_sort_column_id(3)
1000
        self._tvcolumn_size.set_sort_column_id(5)
1001
        self._tvcolumn_mtime.set_sort_column_id(7)
0.8.95 by Szilveszter Farkas (Phanatic)
Some sensitivity changes; branching (get) fixed.
1002
        
1003
        # Set sensitivity
1004
        self.set_sensitivity()
0.13.13 by Jelmer Vernooij
Update TODO
1005
        
195.1.25 by Szilveszter Farkas (Phanatic)
Fixed some minor things and added file_id to the list model.
1006
    def get_selected_fileid(self):
1007
        """ Get the file_id of the selected file. """
1008
        treeselection = self.treeview_right.get_selection()
1009
        (model, iter) = treeselection.get_selected()
1010
        
1011
        if iter is None:
1012
            return None
1013
        else:
1014
            return model.get_value(iter, 9)
1015
    
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
1016
    def get_selected_right(self):
1017
        """ Get the selected filename. """
1018
        treeselection = self.treeview_right.get_selection()
1019
        (model, iter) = treeselection.get_selected()
1020
        
1021
        if iter is None:
1022
            return None
1023
        else:
195.6.1 by Szilveszter Farkas (Phanatic)
Implemented sortable columns, and there are also some new columns
1024
            return model.get_value(iter, 2)
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
1025
    
1026
    def get_selected_left(self):
1027
        """ Get the selected bookmark. """
1028
        treeselection = self.treeview_left.get_selection()
1029
        (model, iter) = treeselection.get_selected()
1030
        
1031
        if iter is None:
1032
            return None
1033
        else:
1034
            return model.get_value(iter, 1)
1035
1036
    def set_statusbar(self, message):
1037
        """ Set the statusbar message. """
1038
        self.statusbar.push(self.context_id, message)
1039
    
1040
    def clear_statusbar(self):
1041
        """ Clean the last message from the statusbar. """
1042
        self.statusbar.pop(self.context_id)
1043
    
0.8.95 by Szilveszter Farkas (Phanatic)
Some sensitivity changes; branching (get) fixed.
1044
    def set_sensitivity(self):
1045
        """ Set menu and toolbar sensitivity. """
195.1.21 by Szilveszter Farkas (Phanatic)
Some small modifications to Branch, Checkout and Info to support remote branches.
1046
        if not self.remote:
1047
            # We're local
1048
            self.menuitem_branch_init.set_sensitive(self.notbranch)
1049
            self.menuitem_branch_get.set_sensitive(self.notbranch)
1050
            self.menuitem_branch_checkout.set_sensitive(self.notbranch)
1051
            self.menuitem_branch_pull.set_sensitive(not self.notbranch)
1052
            self.menuitem_branch_push.set_sensitive(not self.notbranch)
1053
            self.menuitem_branch_revert.set_sensitive(not self.notbranch)
1054
            self.menuitem_branch_merge.set_sensitive(not self.notbranch)
1055
            self.menuitem_branch_commit.set_sensitive(not self.notbranch)
1056
            self.menuitem_branch_tags.set_sensitive(not self.notbranch)
1057
            self.menuitem_branch_status.set_sensitive(not self.notbranch)
1058
            self.menuitem_branch_missing.set_sensitive(not self.notbranch)
1059
            self.menuitem_branch_conflicts.set_sensitive(not self.notbranch)
1060
            self.menuitem_stats.set_sensitive(not self.notbranch)
1061
            self.menuitem_stats_diff.set_sensitive(not self.notbranch)
1062
            self.menuitem_add_files.set_sensitive(not self.notbranch)
1063
            self.menuitem_remove_files.set_sensitive(not self.notbranch)
1064
            self.menuitem_file_make_directory.set_sensitive(not self.notbranch)
1065
            self.menuitem_file_rename.set_sensitive(not self.notbranch)
1066
            self.menuitem_file_move.set_sensitive(not self.notbranch)
1067
            self.menuitem_file_annotate.set_sensitive(not self.notbranch)
1068
            #self.menutoolbutton_diff.set_sensitive(True)
1069
            self.toolbutton_diff.set_sensitive(not self.notbranch)
1070
            self.toolbutton_log.set_sensitive(not self.notbranch)
1071
            self.toolbutton_commit.set_sensitive(not self.notbranch)
1072
            self.toolbutton_pull.set_sensitive(not self.notbranch)
1073
            self.toolbutton_push.set_sensitive(not self.notbranch)
1074
        else:
1075
            # We're remote
1076
            self.menuitem_branch_init.set_sensitive(False)
1077
            self.menuitem_branch_get.set_sensitive(True)
1078
            self.menuitem_branch_checkout.set_sensitive(True)
1079
            self.menuitem_branch_pull.set_sensitive(False)
1080
            self.menuitem_branch_push.set_sensitive(False)
1081
            self.menuitem_branch_revert.set_sensitive(False)
1082
            self.menuitem_branch_merge.set_sensitive(False)
1083
            self.menuitem_branch_commit.set_sensitive(False)
1084
            self.menuitem_branch_tags.set_sensitive(True)
1085
            self.menuitem_branch_status.set_sensitive(False)
1086
            self.menuitem_branch_missing.set_sensitive(False)
1087
            self.menuitem_branch_conflicts.set_sensitive(False)
1088
            self.menuitem_stats.set_sensitive(True)
1089
            self.menuitem_stats_diff.set_sensitive(False)
1090
            self.menuitem_add_files.set_sensitive(False)
1091
            self.menuitem_remove_files.set_sensitive(False)
1092
            self.menuitem_file_make_directory.set_sensitive(False)
1093
            self.menuitem_file_rename.set_sensitive(False)
1094
            self.menuitem_file_move.set_sensitive(False)
1095
            self.menuitem_file_annotate.set_sensitive(False)
1096
            #self.menutoolbutton_diff.set_sensitive(True)
1097
            self.toolbutton_diff.set_sensitive(False)
1098
            self.toolbutton_log.set_sensitive(True)
1099
            self.toolbutton_commit.set_sensitive(False)
1100
            self.toolbutton_pull.set_sensitive(False)
1101
            self.toolbutton_push.set_sensitive(False)
0.8.95 by Szilveszter Farkas (Phanatic)
Some sensitivity changes; branching (get) fixed.
1102
    
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
1103
    def refresh_left(self):
1104
        """ Refresh the bookmark list. """
1105
        
1106
        # Get TreeStore and clear it
1107
        treestore = self.treeview_left.get_model()
1108
        treestore.clear()
1109
0.8.94 by Szilveszter Farkas (Phanatic)
Cleanups: bookmarks and sensitivity.
1110
        # Re-read preferences
1111
        self.pref.read()
111 by Szilveszter Farkas (Phanatic)
Fixed bug: unable to remove bookmarks (not reported).
1112
        
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
1113
        # Get bookmarks
1114
        bookmarks = self.pref.get_bookmarks()
1115
1116
        # Add them to the TreeStore
1117
        titer = treestore.append(None, [_('Bookmarks'), None])
1118
        for item in bookmarks:
1119
            title = self.pref.get_bookmark_title(item)
1120
            treestore.append(titer, [title, item])
1121
1122
        # Add the TreeStore to the TreeView
1123
        self.treeview_left.set_model(treestore)
1124
1125
        # Expand the tree
1126
        self.treeview_left.expand_all()
1127
1128
    def refresh_right(self, path=None):
1129
        """ Refresh the file list. """
195.1.9 by Szilveszter Farkas (Phanatic)
Browsing remote branches works. Still have to optimize some stuff.
1130
        if not self.remote:
1131
            # We're local
1132
            from bzrlib.workingtree import WorkingTree
1133
    
1134
            if path is None:
1135
                path = self.get_path()
1136
    
1137
            # A workaround for double-clicking Bookmarks
1138
            if not os.path.exists(path):
1139
                return
1140
    
1141
            # Get ListStore and clear it
1142
            liststore = self.treeview_right.get_model()
1143
            liststore.clear()
195.1.17 by Szilveszter Farkas (Phanatic)
Show/hide Status column accordingly.
1144
            
1145
            # Show Status column
1146
            self._tvcolumn_status.set_visible(True)
195.1.9 by Szilveszter Farkas (Phanatic)
Browsing remote branches works. Still have to optimize some stuff.
1147
    
1148
            dirs = []
1149
            files = []
1150
    
1151
            # Fill the appropriate lists
1152
            dotted_files = self.pref.get_preference('dotted_files', 'bool')
1153
            for item in os.listdir(path):
1154
                if not dotted_files and item[0] == '.':
1155
                    continue
1156
                if os.path.isdir(path + os.sep + item):
1157
                    dirs.append(item)
1158
                else:
1159
                    files.append(item)
1160
            
1161
            # Try to open the working tree
1162
            notbranch = False
1163
            try:
1164
                tree1 = WorkingTree.open_containing(path)[0]
1165
            except (bzrerrors.NotBranchError, bzrerrors.NoWorkingTree):
1166
                notbranch = True
1167
            
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
1168
            if not notbranch:
195.1.9 by Szilveszter Farkas (Phanatic)
Browsing remote branches works. Still have to optimize some stuff.
1169
                branch = tree1.branch
1170
                tree2 = tree1.branch.repository.revision_tree(branch.last_revision())
1171
            
1172
                delta = tree1.changes_from(tree2, want_unchanged=True)
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
1173
                
195.1.9 by Szilveszter Farkas (Phanatic)
Browsing remote branches works. Still have to optimize some stuff.
1174
            # Add'em to the ListStore
1175
            for item in dirs:
1176
                statinfo = os.stat(self.path + os.sep + item)
195.1.25 by Szilveszter Farkas (Phanatic)
Fixed some minor things and added file_id to the list model.
1177
                liststore.append([gtk.STOCK_DIRECTORY,
1178
                                  True,
1179
                                  item,
1180
                                  '',
1181
                                  '',
1182
                                  statinfo.st_size,
1183
                                  self._format_size(statinfo.st_size),
1184
                                  statinfo.st_mtime,
1185
                                  self._format_date(statinfo.st_mtime),
1186
                                  ''])
195.1.9 by Szilveszter Farkas (Phanatic)
Browsing remote branches works. Still have to optimize some stuff.
1187
            for item in files:
1188
                status = 'unknown'
195.1.25 by Szilveszter Farkas (Phanatic)
Fixed some minor things and added file_id to the list model.
1189
                fileid = ''
195.1.9 by Szilveszter Farkas (Phanatic)
Browsing remote branches works. Still have to optimize some stuff.
1190
                if not notbranch:
1191
                    filename = tree1.relpath(path + os.sep + item)
126.1.39 by Szilveszter Farkas (Phanatic)
Fix the locking issue with Olive (LP: #91522)
1192
                    
195.1.9 by Szilveszter Farkas (Phanatic)
Browsing remote branches works. Still have to optimize some stuff.
1193
                    try:
1194
                        self.wt.lock_read()
1195
                        
1196
                        for rpath, rpathnew, id, kind, text_modified, meta_modified in delta.renamed:
1197
                            if rpathnew == filename:
1198
                                status = 'renamed'
195.1.25 by Szilveszter Farkas (Phanatic)
Fixed some minor things and added file_id to the list model.
1199
                                fileid = id
195.1.9 by Szilveszter Farkas (Phanatic)
Browsing remote branches works. Still have to optimize some stuff.
1200
                        for rpath, id, kind in delta.added:
1201
                            if rpath == filename:
195.1.25 by Szilveszter Farkas (Phanatic)
Fixed some minor things and added file_id to the list model.
1202
                                status = 'added'
1203
                                fileid = id
195.1.9 by Szilveszter Farkas (Phanatic)
Browsing remote branches works. Still have to optimize some stuff.
1204
                        for rpath, id, kind in delta.removed:
1205
                            if rpath == filename:
1206
                                status = 'removed'
195.1.25 by Szilveszter Farkas (Phanatic)
Fixed some minor things and added file_id to the list model.
1207
                                fileid = id
195.1.9 by Szilveszter Farkas (Phanatic)
Browsing remote branches works. Still have to optimize some stuff.
1208
                        for rpath, id, kind, text_modified, meta_modified in delta.modified:
1209
                            if rpath == filename:
1210
                                status = 'modified'
195.1.25 by Szilveszter Farkas (Phanatic)
Fixed some minor things and added file_id to the list model.
1211
                                fileid = id
195.1.9 by Szilveszter Farkas (Phanatic)
Browsing remote branches works. Still have to optimize some stuff.
1212
                        for rpath, id, kind in delta.unchanged:
1213
                            if rpath == filename:
1214
                                status = 'unchanged'
195.1.25 by Szilveszter Farkas (Phanatic)
Fixed some minor things and added file_id to the list model.
1215
                                fileid = id
195.1.9 by Szilveszter Farkas (Phanatic)
Browsing remote branches works. Still have to optimize some stuff.
1216
                        for rpath, file_class, kind, id, entry in self.wt.list_files():
1217
                            if rpath == filename and file_class == 'I':
1218
                                status = 'ignored'
1219
                    finally:
1220
                        self.wt.unlock()
1221
                
1222
                if status == 'renamed':
1223
                    st = _('renamed')
1224
                elif status == 'removed':
1225
                    st = _('removed')
1226
                elif status == 'added':
1227
                    st = _('added')
1228
                elif status == 'modified':
1229
                    st = _('modified')
1230
                elif status == 'unchanged':
1231
                    st = _('unchanged')
1232
                elif status == 'ignored':
1233
                    st = _('ignored')
1234
                else:
1235
                    st = _('unknown')
1236
                
1237
                statinfo = os.stat(self.path + os.sep + item)
195.1.25 by Szilveszter Farkas (Phanatic)
Fixed some minor things and added file_id to the list model.
1238
                liststore.append([gtk.STOCK_FILE,
1239
                                  False,
1240
                                  item,
1241
                                  st,
1242
                                  status,
1243
                                  statinfo.st_size,
1244
                                  self._format_size(statinfo.st_size),
1245
                                  statinfo.st_mtime,
1246
                                  self._format_date(statinfo.st_mtime),
1247
                                  fileid])
195.1.9 by Szilveszter Farkas (Phanatic)
Browsing remote branches works. Still have to optimize some stuff.
1248
        else:
1249
            # We're remote
1250
            
1251
            # Get ListStore and clear it
1252
            liststore = self.treeview_right.get_model()
1253
            liststore.clear()
1254
            
195.1.17 by Szilveszter Farkas (Phanatic)
Show/hide Status column accordingly.
1255
            # Hide Status column
1256
            self._tvcolumn_status.set_visible(False)
1257
            
195.1.9 by Szilveszter Farkas (Phanatic)
Browsing remote branches works. Still have to optimize some stuff.
1258
            dirs = []
1259
            files = []
1260
            
195.1.15 by Szilveszter Farkas (Phanatic)
Workaround for bug #115209 (in Bazaar itself).
1261
            self._show_stock_image(gtk.STOCK_REFRESH)
1262
            
195.1.9 by Szilveszter Farkas (Phanatic)
Browsing remote branches works. Still have to optimize some stuff.
1263
            for (name, type) in self.remote_entries:
1264
                if type.kind == 'directory':
1265
                    dirs.append(type)
1266
                elif type.kind == 'file':
1267
                    files.append(type)
1268
            
195.1.15 by Szilveszter Farkas (Phanatic)
Workaround for bug #115209 (in Bazaar itself).
1269
            class HistoryCache:
1270
                """ Cache based on revision history. """
1271
                def __init__(self, history):
1272
                    self._history = history
1273
                
1274
                def _lookup_revision(self, revid):
1275
                    for r in self._history:
1276
                        if r.revision_id == revid:
1277
                            return r
1278
                    rev = repo.get_revision(revid)
1279
                    self._history.append(rev)
1280
                    return rev
1281
            
195.1.9 by Szilveszter Farkas (Phanatic)
Browsing remote branches works. Still have to optimize some stuff.
1282
            repo = self.remote_branch.repository
1283
            
195.1.15 by Szilveszter Farkas (Phanatic)
Workaround for bug #115209 (in Bazaar itself).
1284
            revhistory = self.remote_branch.revision_history()
1285
            try:
1286
                revs = repo.get_revisions(revhistory)
1287
                cache = HistoryCache(revs)
1288
            except bzrerrors.InvalidHttpResponse:
1289
                # Fallback to dummy algorithm, because of LP: #115209
1290
                cache = HistoryCache([])
1291
            
195.1.9 by Szilveszter Farkas (Phanatic)
Browsing remote branches works. Still have to optimize some stuff.
1292
            for item in dirs:
1293
                if item.parent_id == self.remote_parent:
195.1.15 by Szilveszter Farkas (Phanatic)
Workaround for bug #115209 (in Bazaar itself).
1294
                    rev = cache._lookup_revision(item.revision)
195.1.9 by Szilveszter Farkas (Phanatic)
Browsing remote branches works. Still have to optimize some stuff.
1295
                    liststore.append([ gtk.STOCK_DIRECTORY,
1296
                                       True,
1297
                                       item.name,
1298
                                       '',
1299
                                       '',
1300
                                       0,
1301
                                       self._format_size(0),
1302
                                       rev.timestamp,
195.1.25 by Szilveszter Farkas (Phanatic)
Fixed some minor things and added file_id to the list model.
1303
                                       self._format_date(rev.timestamp),
1304
                                       ''
195.1.9 by Szilveszter Farkas (Phanatic)
Browsing remote branches works. Still have to optimize some stuff.
1305
                                   ])
195.1.11 by Szilveszter Farkas (Phanatic)
No progess bars, they suck. Use manual gtk loop iteration instead. Also added fancy connection icons to the location bar.
1306
                while gtk.events_pending():
1307
                    gtk.main_iteration()
195.1.9 by Szilveszter Farkas (Phanatic)
Browsing remote branches works. Still have to optimize some stuff.
1308
            
1309
            for item in files:
1310
                if item.parent_id == self.remote_parent:
195.1.15 by Szilveszter Farkas (Phanatic)
Workaround for bug #115209 (in Bazaar itself).
1311
                    rev = cache._lookup_revision(item.revision)
195.1.9 by Szilveszter Farkas (Phanatic)
Browsing remote branches works. Still have to optimize some stuff.
1312
                    liststore.append([ gtk.STOCK_FILE,
1313
                                       False,
1314
                                       item.name,
1315
                                       '',
1316
                                       '',
1317
                                       item.text_size,
1318
                                       self._format_size(item.text_size),
1319
                                       rev.timestamp,
195.1.25 by Szilveszter Farkas (Phanatic)
Fixed some minor things and added file_id to the list model.
1320
                                       self._format_date(rev.timestamp),
1321
                                       item.file_id
195.1.9 by Szilveszter Farkas (Phanatic)
Browsing remote branches works. Still have to optimize some stuff.
1322
                                   ])
195.1.11 by Szilveszter Farkas (Phanatic)
No progess bars, they suck. Use manual gtk loop iteration instead. Also added fancy connection icons to the location bar.
1323
                while gtk.events_pending():
1324
                    gtk.main_iteration()
195.1.15 by Szilveszter Farkas (Phanatic)
Workaround for bug #115209 (in Bazaar itself).
1325
            
1326
            self.image_location_error.destroy()
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
1327
195.1.11 by Szilveszter Farkas (Phanatic)
No progess bars, they suck. Use manual gtk loop iteration instead. Also added fancy connection icons to the location bar.
1328
        # Columns should auto-size
195.6.1 by Szilveszter Farkas (Phanatic)
Implemented sortable columns, and there are also some new columns
1329
        self.treeview_right.columns_autosize()
0.8.94 by Szilveszter Farkas (Phanatic)
Cleanups: bookmarks and sensitivity.
1330
        
0.8.95 by Szilveszter Farkas (Phanatic)
Some sensitivity changes; branching (get) fixed.
1331
        # Set sensitivity
1332
        self.set_sensitivity()
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
1333
1334
    def _harddisks(self):
1335
        """ Returns hard drive letters under Win32. """
1336
        try:
1337
            import win32file
1338
            import string
1339
        except ImportError:
1340
            if sys.platform == 'win32':
1341
                print "pyWin32 modules needed to run Olive on Win32."
1342
                sys.exit(1)
1343
            else:
1344
                pass
1345
        
1346
        driveletters = []
1347
        for drive in string.ascii_uppercase:
1348
            if win32file.GetDriveType(drive+':') == win32file.DRIVE_FIXED:
1349
                driveletters.append(drive+':')
1350
        return driveletters
1351
    
1352
    def gen_hard_selector(self):
1353
        """ Generate the hard drive selector under Win32. """
1354
        drives = self._harddisks()
1355
        for drive in drives:
1356
            self.combobox_drive.append_text(drive)
126.1.4 by Szilveszter Farkas (Phanatic)
Set default drive letter (Fixed: #67924)
1357
        self.combobox_drive.set_active(drives.index(os.getcwd()[0:2]))
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
1358
    
1359
    def _refresh_drives(self, combobox):
126.1.4 by Szilveszter Farkas (Phanatic)
Set default drive letter (Fixed: #67924)
1360
        if self._just_started:
1361
            return
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
1362
        model = combobox.get_model()
1363
        active = combobox.get_active()
1364
        if active >= 0:
1365
            drive = model[active][0]
0.14.11 by Alexander Belchenko
Make change of drive letter on win32 is actually workable
1366
            self.set_path(drive + '\\')
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
1367
            self.refresh_right(drive + '\\')
122 by Szilveszter Farkas (Phanatic)
Do not allow merge if there are local changes (Fixed: #73770).
1368
    
1369
    def check_for_changes(self):
1370
        """ Check whether there were changes in the current working tree. """
1371
        old_tree = self.wt.branch.repository.revision_tree(self.wt.branch.last_revision())
1372
        delta = self.wt.changes_from(old_tree)
1373
1374
        changes = False
1375
        
1376
        if len(delta.added) or len(delta.removed) or len(delta.renamed) or len(delta.modified):
1377
            changes = True
1378
        
1379
        return changes
195.6.1 by Szilveszter Farkas (Phanatic)
Implemented sortable columns, and there are also some new columns
1380
    
1381
    def _sort_filelist_callback(self, model, iter1, iter2, data):
1382
        """ The sort callback for the file list, return values:
1383
        -1: iter1 < iter2
1384
        0: iter1 = iter2
1385
        1: iter1 > iter2
1386
        """
1387
        name1 = model.get_value(iter1, 2)
1388
        name2 = model.get_value(iter2, 2)
1389
        
1390
        if model.get_value(iter1, 1):
1391
            # item1 is a directory
1392
            if not model.get_value(iter2, 1):
1393
                # item2 isn't
1394
                return -1
1395
            else:
1396
                # both of them are directories, we compare their names
1397
                if name1 < name2:
1398
                    return -1
1399
                elif name1 == name2:
1400
                    return 0
1401
                else:
1402
                    return 1
1403
        else:
1404
            # item1 is not a directory
1405
            if model.get_value(iter2, 1):
1406
                # item2 is
1407
                return 1
1408
            else:
1409
                # both of them are files, compare them
1410
                if name1 < name2:
1411
                    return -1
1412
                elif name1 == name2:
1413
                    return 0
1414
                else:
1415
                    return 1
1416
    
1417
    def _format_size(self, size):
1418
        """ Format size to a human readable format. """
1419
        return size
1420
    
1421
    def _format_date(self, timestamp):
1422
        """ Format the time (given in secs) to a human readable format. """
1423
        return time.ctime(timestamp)
195.1.9 by Szilveszter Farkas (Phanatic)
Browsing remote branches works. Still have to optimize some stuff.
1424
    
1425
    def _is_remote_dir(self, location):
1426
        """ Determine whether the given location is a directory or not. """
1427
        if not self.remote:
1428
            # We're in local mode
1429
            return False
1430
        else:
1431
            branch, path = Branch.open_containing(location)
1432
            for (name, type) in self.remote_entries:
1433
                if name == path and type.kind == 'directory':
1434
                    # We got it
1435
                    return True
1436
            # Either it's not a directory or not in the inventory
1437
            return False
195.1.11 by Szilveszter Farkas (Phanatic)
No progess bars, they suck. Use manual gtk loop iteration instead. Also added fancy connection icons to the location bar.
1438
    
1439
    def _show_stock_image(self, stock_id):
1440
        """ Show a stock image next to the location entry. """
1441
        self.image_location_error.destroy()
1442
        self.image_location_error = gtk.image_new_from_stock(stock_id, gtk.ICON_SIZE_BUTTON)
1443
        self.hbox_location.pack_start(self.image_location_error, False, False, 0)
195.1.12 by Szilveszter Farkas (Phanatic)
Display status icons on the left side of the location entry.
1444
        if sys.platform == 'win32':
1445
            self.hbox_location.reorder_child(self.image_location_error, 2)
1446
        else:
1447
            self.hbox_location.reorder_child(self.image_location_error, 1)
195.1.11 by Szilveszter Farkas (Phanatic)
No progess bars, they suck. Use manual gtk loop iteration instead. Also added fancy connection icons to the location bar.
1448
        self.image_location_error.show()
1449
        while gtk.events_pending():
1450
            gtk.main_iteration()
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
1451
0.13.13 by Jelmer Vernooij
Update TODO
1452
import ConfigParser
1453
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
1454
class Preferences:
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
1455
    """ A class which handles Olive's preferences. """
170 by Jelmer Vernooij
Add test argument to Preferences().
1456
    def __init__(self, path=None):
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
1457
        """ Initialize the Preferences class. """
1458
        # Some default options
1459
        self.defaults = { 'strict_commit' : False,
1460
                          'dotted_files'  : False,
1461
                          'window_width'  : 700,
1462
                          'window_height' : 400,
1463
                          'window_x'      : 40,
1464
                          'window_y'      : 40,
1465
                          'paned_position': 200 }
1466
1467
        # Create a config parser object
1468
        self.config = ConfigParser.RawConfigParser()
170 by Jelmer Vernooij
Add test argument to Preferences().
1469
1470
        # Set filename
1471
        if path is None:
1472
            if sys.platform == 'win32':
1473
                # Windows - no dotted files
1474
                self._filename = os.path.expanduser('~/olive.conf')
1475
            else:
1476
                self._filename = os.path.expanduser('~/.olive.conf')
1477
        else:
1478
            self._filename = path
126.1.35 by Szilveszter Farkas (Phanatic)
Make test suite not fail if Olive was run before.
1479
        
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
1480
        # Load the configuration
0.8.93 by Szilveszter Farkas (Phanatic)
Some further cleanups. More to come.
1481
        self.read()
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
1482
        
1483
    def _get_default(self, option):
1484
        """ Get the default option for a preference. """
1485
        try:
1486
            ret = self.defaults[option]
1487
        except KeyError:
1488
            return None
1489
        else:
1490
            return ret
1491
1492
    def refresh(self):
1493
        """ Refresh the configuration. """
1494
        # First write out the changes
1495
        self.write()
1496
        # Then load the configuration again
0.8.93 by Szilveszter Farkas (Phanatic)
Some further cleanups. More to come.
1497
        self.read()
1498
1499
    def read(self):
1500
        """ Just read the configuration. """
111 by Szilveszter Farkas (Phanatic)
Fixed bug: unable to remove bookmarks (not reported).
1501
        # Re-initialize the config parser object to avoid some bugs
1502
        self.config = ConfigParser.RawConfigParser()
170 by Jelmer Vernooij
Add test argument to Preferences().
1503
        self.config.read([self._filename])
0.8.93 by Szilveszter Farkas (Phanatic)
Some further cleanups. More to come.
1504
    
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
1505
    def write(self):
1506
        """ Write the configuration to the appropriate files. """
170 by Jelmer Vernooij
Add test argument to Preferences().
1507
        fp = open(self._filename, 'w')
1508
        self.config.write(fp)
1509
        fp.close()
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
1510
1511
    def get_bookmarks(self):
1512
        """ Return the list of bookmarks. """
1513
        bookmarks = self.config.sections()
1514
        if self.config.has_section('preferences'):
1515
            bookmarks.remove('preferences')
1516
        return bookmarks
1517
1518
    def add_bookmark(self, path):
1519
        """ Add bookmark. """
1520
        try:
1521
            self.config.add_section(path)
1522
        except ConfigParser.DuplicateSectionError:
1523
            return False
1524
        else:
1525
            return True
1526
1527
    def get_bookmark_title(self, path):
1528
        """ Get bookmark title. """
1529
        try:
1530
            ret = self.config.get(path, 'title')
1531
        except ConfigParser.NoOptionError:
1532
            ret = path
1533
        
1534
        return ret
1535
    
1536
    def set_bookmark_title(self, path, title):
1537
        """ Set bookmark title. """
143 by Jelmer Vernooij
More preference tests.
1538
        # FIXME: What if path isn't listed yet?
1539
        # FIXME: Canonicalize paths first?
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
1540
        self.config.set(path, 'title', title)
1541
    
1542
    def remove_bookmark(self, path):
1543
        """ Remove bookmark. """
1544
        return self.config.remove_section(path)
0.13.13 by Jelmer Vernooij
Update TODO
1545
1546
    def set_preference(self, option, value):
1547
        """ Set the value of the given option. """
109 by Szilveszter Farkas (Phanatic)
Fix #70134: Unable to run Olive after maximizing window.
1548
        if value is True:
101 by Szilveszter Farkas (Phanatic)
Show/hide hidden files should work now.
1549
            value = 'yes'
109 by Szilveszter Farkas (Phanatic)
Fix #70134: Unable to run Olive after maximizing window.
1550
        elif value is False:
101 by Szilveszter Farkas (Phanatic)
Show/hide hidden files should work now.
1551
            value = 'no'
1552
        
0.13.13 by Jelmer Vernooij
Update TODO
1553
        if self.config.has_section('preferences'):
1554
            self.config.set('preferences', option, value)
1555
        else:
1556
            self.config.add_section('preferences')
1557
            self.config.set('preferences', option, value)
1558
1559
    def get_preference(self, option, kind='str'):
1560
        """ Get the value of the given option.
1561
        
1562
        :param kind: str/bool/int/float. default: str
1563
        """
1564
        if self.config.has_option('preferences', option):
1565
            if kind == 'bool':
101 by Szilveszter Farkas (Phanatic)
Show/hide hidden files should work now.
1566
                return self.config.getboolean('preferences', option)
0.13.13 by Jelmer Vernooij
Update TODO
1567
            elif kind == 'int':
1568
                return self.config.getint('preferences', option)
1569
            elif kind == 'float':
1570
                return self.config.getfloat('preferences', option)
1571
            else:
1572
                return self.config.get('preferences', option)
1573
        else:
1574
            try:
1575
                return self._get_default(option)
1576
            except KeyError:
1577
                return None
1578