/b-gtk/fix-viz

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