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