/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
19
89 by Jelmer Vernooij
Rename OliveBranch -> BranchDialog.
20
# gettext support
21
import gettext
22
gettext.install('olive-gtk')
23
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
24
try:
25
    import pygtk
26
    pygtk.require("2.0")
27
except:
28
    pass
0.8.92 by Szilveszter Farkas (Phanatic)
Cleanup Jelmer's changes.
29
0.13.11 by Jelmer Vernooij
Bunch of small fixes, cleanups and simplifications.
30
import gtk
31
import gtk.gdk
32
import gtk.glade
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
33
0.8.92 by Szilveszter Farkas (Phanatic)
Cleanup Jelmer's changes.
34
from bzrlib.branch import Branch
126.1.11 by Szilveszter Farkas (Phanatic)
Add revert all functionality and fix another regression.
35
import bzrlib.errors as bzrerrors
0.13.13 by Jelmer Vernooij
Update TODO
36
from bzrlib.workingtree import WorkingTree
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
37
151 by Jelmer Vernooij
Move dialog to top-level directory.
38
from bzrlib.plugins.gtk.dialog import error_dialog, info_dialog, warning_dialog
39
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
40
from guifiles import GLADEFILENAME
0.8.92 by Szilveszter Farkas (Phanatic)
Cleanup Jelmer's changes.
41
151 by Jelmer Vernooij
Move dialog to top-level directory.
42
from bzrlib.plugins.gtk.diff import DiffWindow
149 by Jelmer Vernooij
Move diff to top-level directory as well.
43
from bzrlib.plugins.gtk.viz.branchwin import BranchWindow
44
from bzrlib.plugins.gtk.annotate.gannotate import GAnnotateWindow
45
from bzrlib.plugins.gtk.annotate.config import GAnnotateConfig
46
from bzrlib.plugins.gtk.commit import CommitDialog
47
from bzrlib.plugins.gtk.push import PushDialog
93.1.3 by Alexander Belchenko
olive is able to successfully work without installation
48
126.1.19 by Szilveszter Farkas (Phanatic)
Refactored the Push dialog. Add 'gpush' command.
49
delimiter = ' '
93.1.3 by Alexander Belchenko
olive is able to successfully work without installation
50
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
51
class OliveGtk:
52
    """ The main Olive GTK frontend class. This is called when launching the
53
    program. """
54
    
55
    def __init__(self):
93.1.6 by Alexander Belchenko
detecting name of glade file doing in separate module (olive.gladefile)
56
        self.toplevel = gtk.glade.XML(GLADEFILENAME, 'window_main', 'olive-gtk')
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
57
        
58
        self.window = self.toplevel.get_widget('window_main')
59
        
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
60
        self.pref = Preferences()
102 by Szilveszter Farkas (Phanatic)
Show current path in the statusbar.
61
        
62
        self.path = None
0.13.13 by Jelmer Vernooij
Update TODO
63
64
        # Initialize the statusbar
65
        self.statusbar = self.toplevel.get_widget('statusbar')
66
        self.context_id = self.statusbar.get_context_id('olive')
67
        
68
        # Get the main window
69
        self.window_main = self.toplevel.get_widget('window_main')
70
        # Get the HPaned
71
        self.hpaned_main = self.toplevel.get_widget('hpaned_main')
72
        # Get the TreeViews
73
        self.treeview_left = self.toplevel.get_widget('treeview_left')
74
        self.treeview_right = self.toplevel.get_widget('treeview_right')
75
        # Get some important menu items
76
        self.menuitem_add_files = self.toplevel.get_widget('menuitem_add_files')
77
        self.menuitem_remove_files = self.toplevel.get_widget('menuitem_remove_file')
78
        self.menuitem_file_make_directory = self.toplevel.get_widget('menuitem_file_make_directory')
79
        self.menuitem_file_rename = self.toplevel.get_widget('menuitem_file_rename')
80
        self.menuitem_file_move = self.toplevel.get_widget('menuitem_file_move')
124 by Szilveszter Farkas (Phanatic)
Implemented annotate functionality (Fixed: #73786).
81
        self.menuitem_file_annotate = self.toplevel.get_widget('menuitem_file_annotate')
0.13.13 by Jelmer Vernooij
Update TODO
82
        self.menuitem_view_show_hidden_files = self.toplevel.get_widget('menuitem_view_show_hidden_files')
83
        self.menuitem_branch = self.toplevel.get_widget('menuitem_branch')
84
        self.menuitem_branch_init = self.toplevel.get_widget('menuitem_branch_initialize')
85
        self.menuitem_branch_get = self.toplevel.get_widget('menuitem_branch_get')
86
        self.menuitem_branch_checkout = self.toplevel.get_widget('menuitem_branch_checkout')
87
        self.menuitem_branch_pull = self.toplevel.get_widget('menuitem_branch_pull')
88
        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.
89
        self.menuitem_branch_revert = self.toplevel.get_widget('menuitem_branch_revert')
93 by Szilveszter Farkas (Phanatic)
Began to implement Merge dialog.
90
        self.menuitem_branch_merge = self.toplevel.get_widget('menuitem_branch_merge')
0.13.13 by Jelmer Vernooij
Update TODO
91
        self.menuitem_branch_commit = self.toplevel.get_widget('menuitem_branch_commit')
92
        self.menuitem_branch_status = self.toplevel.get_widget('menuitem_branch_status')
93
        self.menuitem_branch_missing = self.toplevel.get_widget('menuitem_branch_missing_revisions')
94
        self.menuitem_stats = self.toplevel.get_widget('menuitem_stats')
95
        self.menuitem_stats_diff = self.toplevel.get_widget('menuitem_stats_diff')
96
        self.menuitem_stats_log = self.toplevel.get_widget('menuitem_stats_log')
97
        # Get some toolbuttons
98
        #self.menutoolbutton_diff = self.toplevel.get_widget('menutoolbutton_diff')
99
        self.toolbutton_diff = self.toplevel.get_widget('toolbutton_diff')
100
        self.toolbutton_log = self.toplevel.get_widget('toolbutton_log')
101
        self.toolbutton_commit = self.toplevel.get_widget('toolbutton_commit')
102
        self.toolbutton_pull = self.toplevel.get_widget('toolbutton_pull')
103
        self.toolbutton_push = self.toplevel.get_widget('toolbutton_push')
104
        # Get the drive selector
105
        self.combobox_drive = gtk.combo_box_new_text()
106
        self.combobox_drive.connect("changed", self._refresh_drives)
107
        
108
        self.vbox_main_right = self.toplevel.get_widget('vbox_main_right')
109
 
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
110
        
111
        # Dictionary for signal_autoconnect
112
        dic = { "on_window_main_destroy": gtk.main_quit,
0.13.13 by Jelmer Vernooij
Update TODO
113
                "on_window_main_delete_event": self.on_window_main_delete_event,
114
                "on_quit_activate": self.on_window_main_delete_event,
115
                "on_about_activate": self.on_about_activate,
116
                "on_menuitem_add_files_activate": self.on_menuitem_add_files_activate,
117
                "on_menuitem_remove_file_activate": self.on_menuitem_remove_file_activate,
118
                "on_menuitem_file_make_directory_activate": self.on_menuitem_file_make_directory_activate,
119
                "on_menuitem_file_move_activate": self.on_menuitem_file_move_activate,
120
                "on_menuitem_file_rename_activate": self.on_menuitem_file_rename_activate,
124 by Szilveszter Farkas (Phanatic)
Implemented annotate functionality (Fixed: #73786).
121
                "on_menuitem_file_annotate_activate": self.on_menuitem_file_annotate_activate,
0.13.13 by Jelmer Vernooij
Update TODO
122
                "on_menuitem_view_show_hidden_files_activate": self.on_menuitem_view_show_hidden_files_activate,
123
                "on_menuitem_view_refresh_activate": self.on_menuitem_view_refresh_activate,
124
                "on_menuitem_branch_initialize_activate": self.on_menuitem_branch_initialize_activate,
125
                "on_menuitem_branch_get_activate": self.on_menuitem_branch_get_activate,
126
                "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.
127
                "on_menuitem_branch_revert_activate": self.on_menuitem_branch_revert_activate,
93 by Szilveszter Farkas (Phanatic)
Began to implement Merge dialog.
128
                "on_menuitem_branch_merge_activate": self.on_menuitem_branch_merge_activate,
0.13.13 by Jelmer Vernooij
Update TODO
129
                "on_menuitem_branch_commit_activate": self.on_menuitem_branch_commit_activate,
130
                "on_menuitem_branch_push_activate": self.on_menuitem_branch_push_activate,
131
                "on_menuitem_branch_pull_activate": self.on_menuitem_branch_pull_activate,
132
                "on_menuitem_branch_status_activate": self.on_menuitem_branch_status_activate,
133
                "on_menuitem_branch_missing_revisions_activate": self.on_menuitem_branch_missing_revisions_activate,
134
                "on_menuitem_stats_diff_activate": self.on_menuitem_stats_diff_activate,
135
                "on_menuitem_stats_log_activate": self.on_menuitem_stats_log_activate,
136
                "on_menuitem_stats_infos_activate": self.on_menuitem_stats_infos_activate,
137
                "on_toolbutton_refresh_clicked": self.on_menuitem_view_refresh_activate,
138
                "on_toolbutton_log_clicked": self.on_menuitem_stats_log_activate,
139
                #"on_menutoolbutton_diff_clicked": self.on_menuitem_stats_diff_activate,
140
                "on_toolbutton_diff_clicked": self.on_menuitem_stats_diff_activate,
141
                "on_toolbutton_commit_clicked": self.on_menuitem_branch_commit_activate,
142
                "on_toolbutton_pull_clicked": self.on_menuitem_branch_pull_activate,
143
                "on_toolbutton_push_clicked": self.on_menuitem_branch_push_activate,
144
                "on_treeview_right_button_press_event": self.on_treeview_right_button_press_event,
145
                "on_treeview_right_row_activated": self.on_treeview_right_row_activated,
146
                "on_treeview_left_button_press_event": self.on_treeview_left_button_press_event,
147
                "on_treeview_left_row_activated": self.on_treeview_left_row_activated }
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
148
        
149
        # Connect the signals to the handlers
150
        self.toplevel.signal_autoconnect(dic)
151
        
126.1.4 by Szilveszter Farkas (Phanatic)
Set default drive letter (Fixed: #67924)
152
        self._just_started = True
153
        
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
154
        # Apply window size and position
155
        width = self.pref.get_preference('window_width', 'int')
156
        height = self.pref.get_preference('window_height', 'int')
157
        self.window.resize(width, height)
158
        x = self.pref.get_preference('window_x', 'int')
159
        y = self.pref.get_preference('window_y', 'int')
160
        self.window.move(x, y)
161
        # Apply paned position
162
        pos = self.pref.get_preference('paned_position', 'int')
0.13.13 by Jelmer Vernooij
Update TODO
163
        self.hpaned_main.set_position(pos)
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
164
        
165
        # Apply menu to the toolbutton
166
        #menubutton = self.toplevel.get_widget('menutoolbutton_diff')
167
        #menubutton.set_menu(handler.menu.toolbar_diff)
168
        
169
        # Now we can show the window
170
        self.window.show()
171
        
172
        # Show drive selector if under Win32
173
        if sys.platform == 'win32':
0.13.13 by Jelmer Vernooij
Update TODO
174
            self.vbox_main_right.pack_start(self.combobox_drive, False, True, 0)
175
            self.vbox_main_right.reorder_child(self.combobox_drive, 0)
176
            self.combobox_drive.show()
177
            self.gen_hard_selector()
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
178
        
179
        self._load_left()
0.13.13 by Jelmer Vernooij
Update TODO
180
181
        # Apply menu state
182
        self.menuitem_view_show_hidden_files.set_active(self.pref.get_preference('dotted_files', 'bool'))
183
184
        self.set_path(os.getcwd())
0.8.92 by Szilveszter Farkas (Phanatic)
Cleanup Jelmer's changes.
185
        self._load_right()
126.1.4 by Szilveszter Farkas (Phanatic)
Set default drive letter (Fixed: #67924)
186
        
187
        self._just_started = False
0.13.13 by Jelmer Vernooij
Update TODO
188
189
    def set_path(self, path):
190
        self.path = path
191
        self.notbranch = False
102 by Szilveszter Farkas (Phanatic)
Show current path in the statusbar.
192
        
0.13.13 by Jelmer Vernooij
Update TODO
193
        try:
194
            self.wt, self.wtpath = WorkingTree.open_containing(self.path)
126.1.11 by Szilveszter Farkas (Phanatic)
Add revert all functionality and fix another regression.
195
        except (bzrerrors.NotBranchError, bzrerrors.NoWorkingTree):
0.13.13 by Jelmer Vernooij
Update TODO
196
            self.notbranch = True
102 by Szilveszter Farkas (Phanatic)
Show current path in the statusbar.
197
        
198
        self.statusbar.push(self.context_id, path)
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
199
0.13.13 by Jelmer Vernooij
Update TODO
200
    def get_path(self):
201
        return self.path
202
   
203
    def on_about_activate(self, widget):
151 by Jelmer Vernooij
Move dialog to top-level directory.
204
        from bzrlib.plugins.gtk.dialog import about
0.13.13 by Jelmer Vernooij
Update TODO
205
        about()
206
        
207
    def on_menuitem_add_files_activate(self, widget):
208
        """ Add file(s)... menu handler. """
209
        from add import OliveAdd
210
        add = OliveAdd(self.wt, self.wtpath, self.get_selected_right())
211
        add.display()
212
    
213
    def on_menuitem_branch_get_activate(self, widget):
214
        """ Branch/Get... menu handler. """
89 by Jelmer Vernooij
Rename OliveBranch -> BranchDialog.
215
        from branch import BranchDialog
126.1.15 by Szilveszter Farkas (Phanatic)
Refactoring the Branch dialog. We also have a Revision Browser now.
216
        branch = BranchDialog(self.get_path(), self.window)
217
        response = branch.run()
218
        if response != gtk.RESPONSE_NONE:
219
            branch.hide()
220
        
221
            if response == gtk.RESPONSE_OK:
222
                self.refresh_right()
223
            
224
            branch.destroy()
0.13.13 by Jelmer Vernooij
Update TODO
225
    
226
    def on_menuitem_branch_checkout_activate(self, widget):
227
        """ Branch/Checkout... menu handler. """
126.1.18 by Szilveszter Farkas (Phanatic)
Improved Branch dialog. Refactored Checkout dialog.
228
        from checkout import CheckoutDialog
229
        checkout = CheckoutDialog(self.get_path(), self.window)
230
        response = checkout.run()
231
        if response != gtk.RESPONSE_NONE:
232
            checkout.hide()
233
        
234
            if response == gtk.RESPONSE_OK:
235
                self.refresh_right()
236
            
237
            checkout.destroy()
0.13.13 by Jelmer Vernooij
Update TODO
238
    
147 by Jelmer Vernooij
Remove a bunch of duplicate functionality.
239
    @show_bzr_error
0.13.13 by Jelmer Vernooij
Update TODO
240
    def on_menuitem_branch_commit_activate(self, widget):
241
        """ Branch/Commit... menu handler. """
135 by Jelmer Vernooij
Throw out the old CommitDialog code and use the new code instead, also for 'gcommit'.
242
        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).
243
        response = commit.run()
244
        if response != gtk.RESPONSE_NONE:
245
            commit.hide()
246
        
247
            if response == gtk.RESPONSE_OK:
248
                self.refresh_right()
249
            
250
            commit.destroy()
0.13.13 by Jelmer Vernooij
Update TODO
251
    
93 by Szilveszter Farkas (Phanatic)
Began to implement Merge dialog.
252
    def on_menuitem_branch_merge_activate(self, widget):
253
        """ Branch/Merge... menu handler. """
254
        from merge import MergeDialog
122 by Szilveszter Farkas (Phanatic)
Do not allow merge if there are local changes (Fixed: #73770).
255
        
256
        if self.check_for_changes():
257
            error_dialog(_('There are local changes in the branch'),
258
                         _('Please commit or revert the changes before merging.'))
259
        else:
260
            merge = MergeDialog(self.wt, self.wtpath)
261
            merge.display()
93 by Szilveszter Farkas (Phanatic)
Began to implement Merge dialog.
262
0.13.13 by Jelmer Vernooij
Update TODO
263
    def on_menuitem_branch_missing_revisions_activate(self, widget):
264
        """ Branch/Missing revisions menu handler. """
265
        local_branch = self.wt.branch
266
        
267
        other_branch = local_branch.get_parent()
268
        if other_branch is None:
269
            error_dialog(_('Parent location is unknown'),
0.8.94 by Szilveszter Farkas (Phanatic)
Cleanups: bookmarks and sensitivity.
270
                         _('Cannot determine missing revisions if no parent location is known.'))
0.13.13 by Jelmer Vernooij
Update TODO
271
            return
272
        
273
        remote_branch = Branch.open(other_branch)
274
        
275
        if remote_branch.base == local_branch.base:
276
            remote_branch = local_branch
277
278
        ret = len(local_branch.missing_revisions(remote_branch))
279
280
        if ret > 0:
281
            info_dialog(_('There are missing revisions'),
0.8.94 by Szilveszter Farkas (Phanatic)
Cleanups: bookmarks and sensitivity.
282
                        _('%d revision(s) missing.') % ret)
0.13.13 by Jelmer Vernooij
Update TODO
283
        else:
284
            info_dialog(_('Local branch up to date'),
0.8.94 by Szilveszter Farkas (Phanatic)
Cleanups: bookmarks and sensitivity.
285
                        _('There are no missing revisions.'))
0.13.13 by Jelmer Vernooij
Update TODO
286
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.
287
    @show_bzr_error
0.13.13 by Jelmer Vernooij
Update TODO
288
    def on_menuitem_branch_pull_activate(self, widget):
289
        """ Branch/Pull menu handler. """
290
        branch_to = self.wt.branch
291
292
        location = branch_to.get_parent()
293
        if location is None:
294
            error_dialog(_('Parent location is unknown'),
295
                                     _('Pulling is not possible until there is a parent location.'))
296
            return
297
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.
298
        branch_from = Branch.open(location)
0.13.13 by Jelmer Vernooij
Update TODO
299
300
        if branch_to.get_parent() is None:
301
            branch_to.set_parent(branch_from.base)
302
0.8.92 by Szilveszter Farkas (Phanatic)
Cleanup Jelmer's changes.
303
        #old_rh = branch_to.revision_history()
304
        #if tree_to is not None:
305
        #    tree_to.pull(branch_from)
306
        #else:
307
        #    branch_to.pull(branch_from)
0.14.14 by Alexander Belchenko
get number of pulled revision: it's return value of branch.pull() method
308
        ret = branch_to.pull(branch_from)
0.13.13 by Jelmer Vernooij
Update TODO
309
        
310
        info_dialog(_('Pull successful'), _('%d revision(s) pulled.') % ret)
311
    
312
    def on_menuitem_branch_push_activate(self, widget):
313
        """ Branch/Push... menu handler. """
126.1.19 by Szilveszter Farkas (Phanatic)
Refactored the Push dialog. Add 'gpush' command.
314
        push = PushDialog(self.wt.branch, self.window)
315
        response = push.run()
316
        if response != gtk.RESPONSE_NONE:
317
            push.destroy()
0.13.13 by Jelmer Vernooij
Update TODO
318
    
126.1.11 by Szilveszter Farkas (Phanatic)
Add revert all functionality and fix another regression.
319
    @show_bzr_error
320
    def on_menuitem_branch_revert_activate(self, widget):
321
        """ Branch/Revert all changes menu handler. """
322
        ret = self.wt.revert([])
323
        if ret:
324
            warning_dialog(_('Conflicts detected'),
325
                           _('Please have a look at the working tree before continuing.'))
326
        else:
327
            info_dialog(_('Revert successful'),
328
                        _('All files reverted to last revision.'))
329
        self.refresh_right()
330
    
0.13.13 by Jelmer Vernooij
Update TODO
331
    def on_menuitem_branch_status_activate(self, widget):
332
        """ Branch/Status... menu handler. """
333
        from status import OliveStatus
334
        status = OliveStatus(self.wt, self.wtpath)
335
        status.display()
336
    
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.
337
    @show_bzr_error
0.13.13 by Jelmer Vernooij
Update TODO
338
    def on_menuitem_branch_initialize_activate(self, widget):
339
        """ Initialize current directory. """
0.8.92 by Szilveszter Farkas (Phanatic)
Cleanup Jelmer's changes.
340
        import bzrlib.bzrdir as bzrdir
341
        
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.
342
        if not os.path.exists(self.path):
343
            os.mkdir(self.path)
344
 
0.13.13 by Jelmer Vernooij
Update TODO
345
        try:
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.
346
            existing_bzrdir = bzrdir.BzrDir.open(self.path)
126.1.11 by Szilveszter Farkas (Phanatic)
Add revert all functionality and fix another regression.
347
        except bzrerrors.NotBranchError:
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.
348
            bzrdir.BzrDir.create_branch_convenience(self.path)
349
        else:
350
            if existing_bzrdir.has_branch():
351
                if existing_bzrdir.has_workingtree():
126.1.11 by Szilveszter Farkas (Phanatic)
Add revert all functionality and fix another regression.
352
                    raise bzrerrors.AlreadyBranchError(self.path)
0.13.13 by Jelmer Vernooij
Update TODO
353
                else:
126.1.11 by Szilveszter Farkas (Phanatic)
Add revert all functionality and fix another regression.
354
                    raise bzrerrors.BranchExistsWithoutWorkingTree(self.path)
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.
355
            else:
356
                existing_bzrdir.create_branch()
357
                existing_bzrdir.create_workingtree()
358
        info_dialog(_('Initialize successful'),
359
                    _('Directory successfully initialized.'))
360
        self.refresh_right()
0.13.13 by Jelmer Vernooij
Update TODO
361
        
124 by Szilveszter Farkas (Phanatic)
Implemented annotate functionality (Fixed: #73786).
362
    def on_menuitem_file_annotate_activate(self, widget):
363
        """ File/Annotate... menu handler. """
364
        if self.get_selected_right() is None:
365
            error_dialog(_('No file was selected'),
366
                         _('Please select a file from the list.'))
367
            return
368
        
369
        branch = self.wt.branch
370
        file_id = self.wt.path2id(self.wt.relpath(os.path.join(self.path, self.get_selected_right())))
371
        
372
        window = GAnnotateWindow(all=False, plain=False)
373
        window.set_title(os.path.join(self.path, self.get_selected_right()) + " - Annotate")
374
        config = GAnnotateConfig(window)
375
        window.show()
376
        branch.lock_read()
377
        try:
66.2.17 by Aaron Bentley
Update olive to use current bzr.dev API. Used _repo_relpath. Bad phanatic!
378
            window.annotate(self.wt, branch, file_id)
124 by Szilveszter Farkas (Phanatic)
Implemented annotate functionality (Fixed: #73786).
379
        finally:
380
            branch.unlock()
381
    
0.13.13 by Jelmer Vernooij
Update TODO
382
    def on_menuitem_file_make_directory_activate(self, widget):
383
        """ File/Make directory... menu handler. """
384
        from mkdir import OliveMkdir
385
        mkdir = OliveMkdir(self.wt, self.wtpath)
386
        mkdir.display()
387
    
388
    def on_menuitem_file_move_activate(self, widget):
389
        """ File/Move... menu handler. """
390
        from move import OliveMove
391
        move = OliveMove(self.wt, self.wtpath, self.get_selected_right())
392
        move.display()
393
    
394
    def on_menuitem_file_rename_activate(self, widget):
395
        """ File/Rename... menu handler. """
396
        from rename import OliveRename
397
        rename = OliveRename(self.wt, self.wtpath, self.get_selected_right())
398
        rename.display()
399
400
    def on_menuitem_remove_file_activate(self, widget):
401
        """ Remove (unversion) selected file. """
120 by Szilveszter Farkas (Phanatic)
Use OliveRemoveDialog class instead of OliveRemove.
402
        from remove import OliveRemoveDialog
403
        remove = OliveRemoveDialog(self.wt, self.wtpath,
404
                                   selected=self.get_selected_right(),
121 by Szilveszter Farkas (Phanatic)
Use OliveBookmarkDialog instead of OliveBookmark.
405
                                   parent=self.window)
120 by Szilveszter Farkas (Phanatic)
Use OliveRemoveDialog class instead of OliveRemove.
406
        response = remove.run()
407
        
408
        if response != gtk.RESPONSE_NONE:
409
            remove.hide()
410
        
411
            if response == gtk.RESPONSE_OK:
412
                self.set_path(self.path)
413
                self.refresh_right()
414
            
415
            remove.destroy()
0.13.13 by Jelmer Vernooij
Update TODO
416
    
417
    def on_menuitem_stats_diff_activate(self, widget):
418
        """ Statistics/Differences... menu handler. """
419
        window = DiffWindow()
420
        parent_tree = self.wt.branch.repository.revision_tree(self.wt.branch.last_revision())
421
        window.set_diff(self.wt.branch.nick, self.wt, parent_tree)
422
        window.show()
423
    
424
    def on_menuitem_stats_infos_activate(self, widget):
425
        """ Statistics/Informations... menu handler. """
426
        from info import OliveInfo
427
        info = OliveInfo(self.wt)
428
        info.display()
429
    
430
    def on_menuitem_stats_log_activate(self, widget):
431
        """ Statistics/Log... menu handler. """
432
        window = BranchWindow()
433
        window.set_branch(self.wt.branch, self.wt.branch.last_revision(), None)
434
        window.show()
435
    
436
    def on_menuitem_view_refresh_activate(self, widget):
437
        """ View/Refresh menu handler. """
438
        # Refresh the left pane
439
        self.refresh_left()
440
        # Refresh the right pane
441
        self.refresh_right()
442
   
443
    def on_menuitem_view_show_hidden_files_activate(self, widget):
444
        """ View/Show hidden files menu handler. """
0.8.92 by Szilveszter Farkas (Phanatic)
Cleanup Jelmer's changes.
445
        self.pref.set_preference('dotted_files', widget.get_active())
102 by Szilveszter Farkas (Phanatic)
Show current path in the statusbar.
446
        if self.path is not None:
447
            self.refresh_right()
0.13.13 by Jelmer Vernooij
Update TODO
448
449
    def on_treeview_left_button_press_event(self, widget, event):
450
        """ Occurs when somebody right-clicks in the bookmark list. """
451
        if event.button == 3:
452
            # Don't show context with nothing selected
453
            if self.get_selected_left() == None:
454
                return
455
0.8.93 by Szilveszter Farkas (Phanatic)
Some further cleanups. More to come.
456
            # Create a menu
457
            from menu import OliveMenu
121 by Szilveszter Farkas (Phanatic)
Use OliveBookmarkDialog instead of OliveBookmark.
458
            menu = OliveMenu(path=self.get_path(),
459
                             selected=self.get_selected_left(),
460
                             app=self)
0.8.93 by Szilveszter Farkas (Phanatic)
Some further cleanups. More to come.
461
            
462
            menu.left_context_menu().popup(None, None, None, 0,
463
                                           event.time)
0.8.94 by Szilveszter Farkas (Phanatic)
Cleanups: bookmarks and sensitivity.
464
0.13.13 by Jelmer Vernooij
Update TODO
465
    def on_treeview_left_row_activated(self, treeview, path, view_column):
466
        """ Occurs when somebody double-clicks or enters an item in the
467
        bookmark list. """
468
469
        newdir = self.get_selected_left()
470
        if newdir == None:
471
            return
472
473
        self.set_path(newdir)
474
        self.refresh_right()
0.8.94 by Szilveszter Farkas (Phanatic)
Cleanups: bookmarks and sensitivity.
475
0.13.13 by Jelmer Vernooij
Update TODO
476
    def on_treeview_right_button_press_event(self, widget, event):
477
        """ Occurs when somebody right-clicks in the file list. """
478
        if event.button == 3:
0.8.92 by Szilveszter Farkas (Phanatic)
Cleanup Jelmer's changes.
479
            # Create a menu
480
            from menu import OliveMenu
120 by Szilveszter Farkas (Phanatic)
Use OliveRemoveDialog class instead of OliveRemove.
481
            menu = OliveMenu(path=self.get_path(),
482
                             selected=self.get_selected_right(),
483
                             app=self)
0.13.13 by Jelmer Vernooij
Update TODO
484
            # get the menu items
0.8.92 by Szilveszter Farkas (Phanatic)
Cleanup Jelmer's changes.
485
            m_add = menu.ui.get_widget('/context_right/add')
486
            m_remove = menu.ui.get_widget('/context_right/remove')
117 by Szilveszter Farkas (Phanatic)
Rename put into context menu (Fixed: #73774).
487
            m_rename = menu.ui.get_widget('/context_right/rename')
126.1.12 by Szilveszter Farkas (Phanatic)
Added revert functionality to the context menu.
488
            m_revert = menu.ui.get_widget('/context_right/revert')
0.8.92 by Szilveszter Farkas (Phanatic)
Cleanup Jelmer's changes.
489
            m_commit = menu.ui.get_widget('/context_right/commit')
490
            m_diff = menu.ui.get_widget('/context_right/diff')
0.13.13 by Jelmer Vernooij
Update TODO
491
            # check if we're in a branch
492
            try:
493
                from bzrlib.branch import Branch
494
                Branch.open_containing(self.get_path())
0.8.92 by Szilveszter Farkas (Phanatic)
Cleanup Jelmer's changes.
495
                m_add.set_sensitive(True)
496
                m_remove.set_sensitive(True)
117 by Szilveszter Farkas (Phanatic)
Rename put into context menu (Fixed: #73774).
497
                m_rename.set_sensitive(True)
126.1.12 by Szilveszter Farkas (Phanatic)
Added revert functionality to the context menu.
498
                m_revert.set_sensitive(True)
0.8.92 by Szilveszter Farkas (Phanatic)
Cleanup Jelmer's changes.
499
                m_commit.set_sensitive(True)
500
                m_diff.set_sensitive(True)
126.1.11 by Szilveszter Farkas (Phanatic)
Add revert all functionality and fix another regression.
501
            except bzrerrors.NotBranchError:
0.13.13 by Jelmer Vernooij
Update TODO
502
                m_add.set_sensitive(False)
503
                m_remove.set_sensitive(False)
117 by Szilveszter Farkas (Phanatic)
Rename put into context menu (Fixed: #73774).
504
                m_rename.set_sensitive(False)
126.1.12 by Szilveszter Farkas (Phanatic)
Added revert functionality to the context menu.
505
                m_revert.set_sensitive(False)
0.13.13 by Jelmer Vernooij
Update TODO
506
                m_commit.set_sensitive(False)
507
                m_diff.set_sensitive(False)
101 by Szilveszter Farkas (Phanatic)
Show/hide hidden files should work now.
508
0.8.92 by Szilveszter Farkas (Phanatic)
Cleanup Jelmer's changes.
509
            menu.right_context_menu().popup(None, None, None, 0,
510
                                            event.time)
0.13.13 by Jelmer Vernooij
Update TODO
511
        
512
    def on_treeview_right_row_activated(self, treeview, path, view_column):
513
        """ Occurs when somebody double-clicks or enters an item in the
514
        file list. """
0.8.92 by Szilveszter Farkas (Phanatic)
Cleanup Jelmer's changes.
515
        from launch import launch
516
        
0.13.13 by Jelmer Vernooij
Update TODO
517
        newdir = self.get_selected_right()
518
        
519
        if newdir == '..':
520
            self.set_path(os.path.split(self.get_path())[0])
521
        else:
0.14.11 by Alexander Belchenko
Make change of drive letter on win32 is actually workable
522
            fullpath = os.path.join(self.get_path(), newdir)
0.13.13 by Jelmer Vernooij
Update TODO
523
            if os.path.isdir(fullpath):
524
                # selected item is an existant directory
525
                self.set_path(fullpath)
526
            else:
527
                launch(fullpath) 
528
        
529
        self.refresh_right()
530
    
531
    def on_window_main_delete_event(self, widget, event=None):
532
        """ Do some stuff before exiting. """
533
        width, height = self.window_main.get_size()
534
        self.pref.set_preference('window_width', width)
535
        self.pref.set_preference('window_height', height)
536
        x, y = self.window_main.get_position()
537
        self.pref.set_preference('window_x', x)
538
        self.pref.set_preference('window_y', y)
539
        self.pref.set_preference('paned_position',
101 by Szilveszter Farkas (Phanatic)
Show/hide hidden files should work now.
540
                                 self.hpaned_main.get_position())
0.13.13 by Jelmer Vernooij
Update TODO
541
        
542
        self.pref.write()
543
        self.window_main.destroy()
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
544
        
545
    def _load_left(self):
546
        """ Load data into the left panel. (Bookmarks) """
547
        # Create TreeStore
548
        treestore = gtk.TreeStore(str, str)
549
        
550
        # Get bookmarks
0.13.13 by Jelmer Vernooij
Update TODO
551
        bookmarks = self.pref.get_bookmarks()
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
552
        
553
        # Add them to the TreeStore
554
        titer = treestore.append(None, [_('Bookmarks'), None])
555
        for item in bookmarks:
0.13.13 by Jelmer Vernooij
Update TODO
556
            title = self.pref.get_bookmark_title(item)
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
557
            treestore.append(titer, [title, item])
558
        
559
        # Create the column and add it to the TreeView
560
        self.treeview_left.set_model(treestore)
561
        tvcolumn_bookmark = gtk.TreeViewColumn(_('Bookmark'))
562
        self.treeview_left.append_column(tvcolumn_bookmark)
563
        
564
        # Set up the cells
565
        cell = gtk.CellRendererText()
566
        tvcolumn_bookmark.pack_start(cell, True)
567
        tvcolumn_bookmark.add_attribute(cell, 'text', 0)
568
        
569
        # Expand the tree
570
        self.treeview_left.expand_all()
571
0.14.12 by Alexander Belchenko
updir link (..) added always to the top of directories list
572
    def _add_updir_to_dirlist(self, dirlist, curdir):
573
        """Add .. to the top of directories list if we not in root directory
574
91.1.9 by Jelmer Vernooij
Use epydoc style (for consistency with Bazaar).
575
        :param dirlist:     list of directories (modified in place)
576
        :param curdir:      current directory
577
        :return:            nothing
0.14.12 by Alexander Belchenko
updir link (..) added always to the top of directories list
578
        """
579
        if curdir is None:
580
            curdir = self.path
581
582
        if sys.platform == 'win32':
583
            drive, tail = os.path.splitdrive(curdir)
584
            if tail in ('', '/', '\\'):
585
                return
586
        else:
587
            if curdir == '/':
588
                return
589
590
        # insert always as first element
591
        dirlist.insert(0, '..')
592
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
593
    def _load_right(self):
594
        """ Load data into the right panel. (Filelist) """
595
        # Create ListStore
596
        liststore = gtk.ListStore(str, str, str)
597
        
0.14.12 by Alexander Belchenko
updir link (..) added always to the top of directories list
598
        dirs = []
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
599
        files = []
600
        
601
        # Fill the appropriate lists
602
        dotted_files = self.pref.get_preference('dotted_files', 'bool')
0.13.13 by Jelmer Vernooij
Update TODO
603
        for item in os.listdir(self.path):
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
604
            if not dotted_files and item[0] == '.':
605
                continue
0.13.13 by Jelmer Vernooij
Update TODO
606
            if os.path.isdir(self.path + os.sep + item):
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
607
                dirs.append(item)
608
            else:
609
                files.append(item)
610
            
611
        # Sort'em
612
        dirs.sort()
613
        files.sort()
0.14.12 by Alexander Belchenko
updir link (..) added always to the top of directories list
614
615
        # add updir link to dirs
616
        self._add_updir_to_dirlist(dirs, self.path)
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
617
        
0.13.13 by Jelmer Vernooij
Update TODO
618
        if not self.notbranch:
619
            branch = self.wt.branch
620
            tree2 = self.wt.branch.repository.revision_tree(branch.last_revision())
621
        
622
            delta = self.wt.changes_from(tree2, want_unchanged=True)
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
623
        
624
        # Add'em to the ListStore
625
        for item in dirs:    
626
            liststore.append([gtk.STOCK_DIRECTORY, item, ''])
627
        for item in files:
628
            status = 'unknown'
0.13.13 by Jelmer Vernooij
Update TODO
629
            if not self.notbranch:
630
                filename = self.wt.relpath(self.path + os.sep + item)
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
631
                
0.8.98 by Szilveszter Farkas (Phanatic)
Loads of fixes. Pyflakes cleanup.
632
                for rpath, rpathnew, id, kind, text_modified, meta_modified in delta.renamed:
633
                    if rpathnew == filename:
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
634
                        status = 'renamed'
635
                for rpath, id, kind in delta.added:
636
                    if rpath == filename:
637
                        status = 'added'
0.13.10 by Jelmer Vernooij
Don't pass around gladefile all the time.
638
                for rpath, id, kind in delta.removed:
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
639
                    if rpath == filename:
640
                        status = 'removed'
641
                for rpath, id, kind, text_modified, meta_modified in delta.modified:
642
                    if rpath == filename:
643
                        status = 'modified'
644
                for rpath, id, kind in delta.unchanged:
645
                    if rpath == filename:
646
                        status = 'unchanged'
123 by Szilveszter Farkas (Phanatic)
Ignored files are no more shown as unknown (Fixed: #67926).
647
                for rpath, file_class, kind, id, entry in self.wt.list_files():
648
                    if rpath == filename and file_class == 'I':
649
                        status = 'ignored'
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
650
            
651
            #try:
652
            #    status = fileops.status(path + os.sep + item)
653
            #except errors.PermissionDenied:
654
            #    continue
655
            
656
            if status == 'renamed':
657
                st = _('renamed')
658
            elif status == 'removed':
659
                st = _('removed')
660
            elif status == 'added':
661
                st = _('added')
662
            elif status == 'modified':
663
                st = _('modified')
664
            elif status == 'unchanged':
665
                st = _('unchanged')
123 by Szilveszter Farkas (Phanatic)
Ignored files are no more shown as unknown (Fixed: #67926).
666
            elif status == 'ignored':
667
                st = _('ignored')
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
668
            else:
669
                st = _('unknown')
670
            liststore.append([gtk.STOCK_FILE, item, st])
671
        
672
        # Create the columns and add them to the TreeView
673
        self.treeview_right.set_model(liststore)
674
        tvcolumn_filename = gtk.TreeViewColumn(_('Filename'))
675
        tvcolumn_status = gtk.TreeViewColumn(_('Status'))
676
        self.treeview_right.append_column(tvcolumn_filename)
677
        self.treeview_right.append_column(tvcolumn_status)
678
        
679
        # Set up the cells
680
        cellpb = gtk.CellRendererPixbuf()
681
        cell = gtk.CellRendererText()
682
        tvcolumn_filename.pack_start(cellpb, False)
683
        tvcolumn_filename.pack_start(cell, True)
684
        tvcolumn_filename.set_attributes(cellpb, stock_id=0)
685
        tvcolumn_filename.add_attribute(cell, 'text', 1)
686
        tvcolumn_status.pack_start(cell, True)
687
        tvcolumn_status.add_attribute(cell, 'text', 2)
0.8.95 by Szilveszter Farkas (Phanatic)
Some sensitivity changes; branching (get) fixed.
688
        
689
        # Set sensitivity
690
        self.set_sensitivity()
0.13.13 by Jelmer Vernooij
Update TODO
691
        
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
692
    def get_selected_right(self):
693
        """ Get the selected filename. """
694
        treeselection = self.treeview_right.get_selection()
695
        (model, iter) = treeselection.get_selected()
696
        
697
        if iter is None:
698
            return None
699
        else:
700
            return model.get_value(iter, 1)
701
    
702
    def get_selected_left(self):
703
        """ Get the selected bookmark. """
704
        treeselection = self.treeview_left.get_selection()
705
        (model, iter) = treeselection.get_selected()
706
        
707
        if iter is None:
708
            return None
709
        else:
710
            return model.get_value(iter, 1)
711
712
    def set_statusbar(self, message):
713
        """ Set the statusbar message. """
714
        self.statusbar.push(self.context_id, message)
715
    
716
    def clear_statusbar(self):
717
        """ Clean the last message from the statusbar. """
718
        self.statusbar.pop(self.context_id)
719
    
0.8.95 by Szilveszter Farkas (Phanatic)
Some sensitivity changes; branching (get) fixed.
720
    def set_sensitivity(self):
721
        """ Set menu and toolbar sensitivity. """
722
        self.menuitem_branch_init.set_sensitive(self.notbranch)
95 by Szilveszter Farkas (Phanatic)
Added pending merges to Commit dialog. Fixed bug #66091.
723
        self.menuitem_branch_get.set_sensitive(self.notbranch)
0.8.95 by Szilveszter Farkas (Phanatic)
Some sensitivity changes; branching (get) fixed.
724
        self.menuitem_branch_checkout.set_sensitive(self.notbranch)
725
        self.menuitem_branch_pull.set_sensitive(not self.notbranch)
726
        self.menuitem_branch_push.set_sensitive(not self.notbranch)
126.1.11 by Szilveszter Farkas (Phanatic)
Add revert all functionality and fix another regression.
727
        self.menuitem_branch_revert.set_sensitive(not self.notbranch)
93 by Szilveszter Farkas (Phanatic)
Began to implement Merge dialog.
728
        self.menuitem_branch_merge.set_sensitive(not self.notbranch)
0.8.95 by Szilveszter Farkas (Phanatic)
Some sensitivity changes; branching (get) fixed.
729
        self.menuitem_branch_commit.set_sensitive(not self.notbranch)
730
        self.menuitem_branch_status.set_sensitive(not self.notbranch)
731
        self.menuitem_branch_missing.set_sensitive(not self.notbranch)
732
        self.menuitem_stats.set_sensitive(not self.notbranch)
733
        self.menuitem_add_files.set_sensitive(not self.notbranch)
734
        self.menuitem_remove_files.set_sensitive(not self.notbranch)
735
        self.menuitem_file_make_directory.set_sensitive(not self.notbranch)
736
        self.menuitem_file_rename.set_sensitive(not self.notbranch)
737
        self.menuitem_file_move.set_sensitive(not self.notbranch)
124 by Szilveszter Farkas (Phanatic)
Implemented annotate functionality (Fixed: #73786).
738
        self.menuitem_file_annotate.set_sensitive(not self.notbranch)
0.8.95 by Szilveszter Farkas (Phanatic)
Some sensitivity changes; branching (get) fixed.
739
        #self.menutoolbutton_diff.set_sensitive(True)
740
        self.toolbutton_diff.set_sensitive(not self.notbranch)
741
        self.toolbutton_log.set_sensitive(not self.notbranch)
742
        self.toolbutton_commit.set_sensitive(not self.notbranch)
743
        self.toolbutton_pull.set_sensitive(not self.notbranch)
744
        self.toolbutton_push.set_sensitive(not self.notbranch)
745
    
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
746
    def refresh_left(self):
747
        """ Refresh the bookmark list. """
748
        
749
        # Get TreeStore and clear it
750
        treestore = self.treeview_left.get_model()
751
        treestore.clear()
752
0.8.94 by Szilveszter Farkas (Phanatic)
Cleanups: bookmarks and sensitivity.
753
        # Re-read preferences
754
        self.pref.read()
111 by Szilveszter Farkas (Phanatic)
Fixed bug: unable to remove bookmarks (not reported).
755
        
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
756
        # Get bookmarks
757
        bookmarks = self.pref.get_bookmarks()
758
759
        # Add them to the TreeStore
760
        titer = treestore.append(None, [_('Bookmarks'), None])
761
        for item in bookmarks:
762
            title = self.pref.get_bookmark_title(item)
763
            treestore.append(titer, [title, item])
764
765
        # Add the TreeStore to the TreeView
766
        self.treeview_left.set_model(treestore)
767
768
        # Expand the tree
769
        self.treeview_left.expand_all()
770
771
    def refresh_right(self, path=None):
772
        """ Refresh the file list. """
773
        from bzrlib.workingtree import WorkingTree
774
775
        if path is None:
776
            path = self.get_path()
777
778
        # A workaround for double-clicking Bookmarks
779
        if not os.path.exists(path):
780
            return
781
782
        # Get ListStore and clear it
783
        liststore = self.treeview_right.get_model()
784
        liststore.clear()
785
0.14.12 by Alexander Belchenko
updir link (..) added always to the top of directories list
786
        dirs = []
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
787
        files = []
788
789
        # Fill the appropriate lists
790
        dotted_files = self.pref.get_preference('dotted_files', 'bool')
791
        for item in os.listdir(path):
792
            if not dotted_files and item[0] == '.':
793
                continue
794
            if os.path.isdir(path + os.sep + item):
795
                dirs.append(item)
796
            else:
797
                files.append(item)
798
799
        # Sort'em
800
        dirs.sort()
801
        files.sort()
0.14.12 by Alexander Belchenko
updir link (..) added always to the top of directories list
802
803
        # add updir link to dirs
804
        self._add_updir_to_dirlist(dirs, path)
805
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
806
        # Try to open the working tree
807
        notbranch = False
808
        try:
809
            tree1 = WorkingTree.open_containing(path)[0]
126.1.11 by Szilveszter Farkas (Phanatic)
Add revert all functionality and fix another regression.
810
        except (bzrerrors.NotBranchError, bzrerrors.NoWorkingTree):
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
811
            notbranch = True
812
        
813
        if not notbranch:
814
            branch = tree1.branch
815
            tree2 = tree1.branch.repository.revision_tree(branch.last_revision())
816
        
817
            delta = tree1.changes_from(tree2, want_unchanged=True)
123 by Szilveszter Farkas (Phanatic)
Ignored files are no more shown as unknown (Fixed: #67926).
818
            
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
819
        # Add'em to the ListStore
820
        for item in dirs:
821
            liststore.append([gtk.STOCK_DIRECTORY, item, ''])
822
        for item in files:
823
            status = 'unknown'
824
            if not notbranch:
825
                filename = tree1.relpath(path + os.sep + item)
826
                
0.8.98 by Szilveszter Farkas (Phanatic)
Loads of fixes. Pyflakes cleanup.
827
                for rpath, rpathnew, id, kind, text_modified, meta_modified in delta.renamed:
828
                    if rpathnew == filename:
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
829
                        status = 'renamed'
830
                for rpath, id, kind in delta.added:
831
                    if rpath == filename:
0.8.98 by Szilveszter Farkas (Phanatic)
Loads of fixes. Pyflakes cleanup.
832
                        status = 'added'                
89 by Jelmer Vernooij
Rename OliveBranch -> BranchDialog.
833
                for rpath, id, kind in delta.removed:
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
834
                    if rpath == filename:
835
                        status = 'removed'
836
                for rpath, id, kind, text_modified, meta_modified in delta.modified:
837
                    if rpath == filename:
838
                        status = 'modified'
839
                for rpath, id, kind in delta.unchanged:
840
                    if rpath == filename:
841
                        status = 'unchanged'
123 by Szilveszter Farkas (Phanatic)
Ignored files are no more shown as unknown (Fixed: #67926).
842
                for rpath, file_class, kind, id, entry in self.wt.list_files():
843
                    if rpath == filename and file_class == 'I':
844
                        status = 'ignored'
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
845
            
846
            #try:
847
            #    status = fileops.status(path + os.sep + item)
848
            #except errors.PermissionDenied:
849
            #    continue
850
851
            if status == 'renamed':
852
                st = _('renamed')
853
            elif status == 'removed':
854
                st = _('removed')
855
            elif status == 'added':
856
                st = _('added')
857
            elif status == 'modified':
858
                st = _('modified')
859
            elif status == 'unchanged':
860
                st = _('unchanged')
123 by Szilveszter Farkas (Phanatic)
Ignored files are no more shown as unknown (Fixed: #67926).
861
            elif status == 'ignored':
862
                st = _('ignored')
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
863
            else:
864
                st = _('unknown')
865
            liststore.append([gtk.STOCK_FILE, item, st])
866
867
        # Add the ListStore to the TreeView
868
        self.treeview_right.set_model(liststore)
0.8.94 by Szilveszter Farkas (Phanatic)
Cleanups: bookmarks and sensitivity.
869
        
0.8.95 by Szilveszter Farkas (Phanatic)
Some sensitivity changes; branching (get) fixed.
870
        # Set sensitivity
871
        self.set_sensitivity()
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
872
873
    def _harddisks(self):
874
        """ Returns hard drive letters under Win32. """
875
        try:
876
            import win32file
877
            import string
878
        except ImportError:
879
            if sys.platform == 'win32':
880
                print "pyWin32 modules needed to run Olive on Win32."
881
                sys.exit(1)
882
            else:
883
                pass
884
        
885
        driveletters = []
886
        for drive in string.ascii_uppercase:
887
            if win32file.GetDriveType(drive+':') == win32file.DRIVE_FIXED:
888
                driveletters.append(drive+':')
889
        return driveletters
890
    
891
    def gen_hard_selector(self):
892
        """ Generate the hard drive selector under Win32. """
893
        drives = self._harddisks()
894
        for drive in drives:
895
            self.combobox_drive.append_text(drive)
126.1.4 by Szilveszter Farkas (Phanatic)
Set default drive letter (Fixed: #67924)
896
        self.combobox_drive.set_active(drives.index(os.getcwd()[0:2]))
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
897
    
898
    def _refresh_drives(self, combobox):
126.1.4 by Szilveszter Farkas (Phanatic)
Set default drive letter (Fixed: #67924)
899
        if self._just_started:
900
            return
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
901
        model = combobox.get_model()
902
        active = combobox.get_active()
903
        if active >= 0:
904
            drive = model[active][0]
0.14.11 by Alexander Belchenko
Make change of drive letter on win32 is actually workable
905
            self.set_path(drive + '\\')
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
906
            self.refresh_right(drive + '\\')
122 by Szilveszter Farkas (Phanatic)
Do not allow merge if there are local changes (Fixed: #73770).
907
    
908
    def check_for_changes(self):
909
        """ Check whether there were changes in the current working tree. """
910
        old_tree = self.wt.branch.repository.revision_tree(self.wt.branch.last_revision())
911
        delta = self.wt.changes_from(old_tree)
912
913
        changes = False
914
        
915
        if len(delta.added) or len(delta.removed) or len(delta.renamed) or len(delta.modified):
916
            changes = True
917
        
918
        return changes
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
919
0.13.13 by Jelmer Vernooij
Update TODO
920
import ConfigParser
921
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
922
class Preferences:
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
923
    """ A class which handles Olive's preferences. """
924
    def __init__(self):
925
        """ Initialize the Preferences class. """
926
        # Some default options
927
        self.defaults = { 'strict_commit' : False,
928
                          'dotted_files'  : False,
929
                          'window_width'  : 700,
930
                          'window_height' : 400,
931
                          'window_x'      : 40,
932
                          'window_y'      : 40,
933
                          'paned_position': 200 }
934
935
        # Create a config parser object
936
        self.config = ConfigParser.RawConfigParser()
937
        
938
        # Load the configuration
0.8.93 by Szilveszter Farkas (Phanatic)
Some further cleanups. More to come.
939
        self.read()
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
940
        
941
    def _get_default(self, option):
942
        """ Get the default option for a preference. """
943
        try:
944
            ret = self.defaults[option]
945
        except KeyError:
946
            return None
947
        else:
948
            return ret
949
950
    def refresh(self):
951
        """ Refresh the configuration. """
952
        # First write out the changes
953
        self.write()
954
        # Then load the configuration again
0.8.93 by Szilveszter Farkas (Phanatic)
Some further cleanups. More to come.
955
        self.read()
956
957
    def read(self):
958
        """ Just read the configuration. """
111 by Szilveszter Farkas (Phanatic)
Fixed bug: unable to remove bookmarks (not reported).
959
        # Re-initialize the config parser object to avoid some bugs
960
        self.config = ConfigParser.RawConfigParser()
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
961
        if sys.platform == 'win32':
962
            # Windows - no dotted files
963
            self.config.read([os.path.expanduser('~/olive.conf')])
964
        else:
965
            self.config.read([os.path.expanduser('~/.olive.conf')])
0.8.93 by Szilveszter Farkas (Phanatic)
Some further cleanups. More to come.
966
    
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
967
    def write(self):
968
        """ Write the configuration to the appropriate files. """
969
        if sys.platform == 'win32':
970
            # Windows - no dotted files
971
            fp = open(os.path.expanduser('~/olive.conf'), 'w')
972
            self.config.write(fp)
973
            fp.close()
974
        else:
975
            fp = open(os.path.expanduser('~/.olive.conf'), 'w')
976
            self.config.write(fp)
977
            fp.close()
978
979
    def get_bookmarks(self):
980
        """ Return the list of bookmarks. """
981
        bookmarks = self.config.sections()
982
        if self.config.has_section('preferences'):
983
            bookmarks.remove('preferences')
984
        return bookmarks
985
986
    def add_bookmark(self, path):
987
        """ Add bookmark. """
988
        try:
989
            self.config.add_section(path)
990
        except ConfigParser.DuplicateSectionError:
991
            return False
992
        else:
993
            return True
994
995
    def get_bookmark_title(self, path):
996
        """ Get bookmark title. """
997
        try:
998
            ret = self.config.get(path, 'title')
999
        except ConfigParser.NoOptionError:
1000
            ret = path
1001
        
1002
        return ret
1003
    
1004
    def set_bookmark_title(self, path, title):
1005
        """ Set bookmark title. """
143 by Jelmer Vernooij
More preference tests.
1006
        # FIXME: What if path isn't listed yet?
1007
        # FIXME: Canonicalize paths first?
0.8.84 by Szilveszter Farkas (Phanatic)
Huge cleanup after removing backend codebase.
1008
        self.config.set(path, 'title', title)
1009
    
1010
    def remove_bookmark(self, path):
1011
        """ Remove bookmark. """
1012
        return self.config.remove_section(path)
0.13.13 by Jelmer Vernooij
Update TODO
1013
1014
    def set_preference(self, option, value):
1015
        """ Set the value of the given option. """
109 by Szilveszter Farkas (Phanatic)
Fix #70134: Unable to run Olive after maximizing window.
1016
        if value is True:
101 by Szilveszter Farkas (Phanatic)
Show/hide hidden files should work now.
1017
            value = 'yes'
109 by Szilveszter Farkas (Phanatic)
Fix #70134: Unable to run Olive after maximizing window.
1018
        elif value is False:
101 by Szilveszter Farkas (Phanatic)
Show/hide hidden files should work now.
1019
            value = 'no'
1020
        
0.13.13 by Jelmer Vernooij
Update TODO
1021
        if self.config.has_section('preferences'):
1022
            self.config.set('preferences', option, value)
1023
        else:
1024
            self.config.add_section('preferences')
1025
            self.config.set('preferences', option, value)
1026
1027
    def get_preference(self, option, kind='str'):
1028
        """ Get the value of the given option.
1029
        
1030
        :param kind: str/bool/int/float. default: str
1031
        """
1032
        if self.config.has_option('preferences', option):
1033
            if kind == 'bool':
101 by Szilveszter Farkas (Phanatic)
Show/hide hidden files should work now.
1034
                return self.config.getboolean('preferences', option)
0.13.13 by Jelmer Vernooij
Update TODO
1035
            elif kind == 'int':
1036
                return self.config.getint('preferences', option)
1037
            elif kind == 'float':
1038
                return self.config.getfloat('preferences', option)
1039
            else:
1040
                return self.config.get('preferences', option)
1041
        else:
1042
            try:
1043
                return self._get_default(option)
1044
            except KeyError:
1045
                return None
1046