/b-gtk/fix-viz

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/b-gtk/fix-viz
0.8.19 by Szilveszter Farkas (Phanatic)
2006-07-21 Szilveszter Farkas <Szilveszter.Farkas@gmail.com>
1
# Copyright (C) 2006 by Szilveszter Farkas (Phanatic) <szilveszter.farkas@gmail.com>
0.8.46 by Szilveszter Farkas (Phanatic)
Modified OliveDialog class interface; huge cleanups.
2
#
0.8.19 by Szilveszter Farkas (Phanatic)
2006-07-21 Szilveszter Farkas <Szilveszter.Farkas@gmail.com>
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.
0.8.46 by Szilveszter Farkas (Phanatic)
Modified OliveDialog class interface; huge cleanups.
7
#
0.8.19 by Szilveszter Farkas (Phanatic)
2006-07-21 Szilveszter Farkas <Szilveszter.Farkas@gmail.com>
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.
0.8.46 by Szilveszter Farkas (Phanatic)
Modified OliveDialog class interface; huge cleanups.
12
#
0.8.19 by Szilveszter Farkas (Phanatic)
2006-07-21 Szilveszter Farkas <Szilveszter.Farkas@gmail.com>
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
try:
18
    import pygtk
19
    pygtk.require("2.0")
20
except:
21
    pass
0.8.98 by Szilveszter Farkas (Phanatic)
Loads of fixes. Pyflakes cleanup.
22
0.13.11 by Jelmer Vernooij
Bunch of small fixes, cleanups and simplifications.
23
import gtk
24
import gobject
25
import pango
0.8.19 by Szilveszter Farkas (Phanatic)
2006-07-21 Szilveszter Farkas <Szilveszter.Farkas@gmail.com>
26
126.1.10 by Szilveszter Farkas (Phanatic)
Allow to commit single files from the context menu (Fixed: #54983)
27
import os.path
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
28
import re
126.1.10 by Szilveszter Farkas (Phanatic)
Allow to commit single files from the context menu (Fixed: #54983)
29
248 by Jelmer Vernooij
Merge fixes for #127392 and #127381)
30
from bzrlib import errors, osutils
235.1.5 by Mateusz Korniak
Missing mutter import added.
31
from bzrlib.trace import mutter
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
32
from bzrlib.util import bencode
0.8.20 by Szilveszter Farkas (Phanatic)
2006-07-24 Szilveszter Farkas <Szilveszter.Farkas@gmail.com>
33
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
34
from bzrlib.plugins.gtk import _i18n
153 by Jelmer Vernooij
Fix references to dialog.
35
from dialog import error_dialog, question_dialog
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.
36
from errors import show_bzr_error
93.1.6 by Alexander Belchenko
detecting name of glade file doing in separate module (olive.gladefile)
37
158 by Jelmer Vernooij
If available, use NetworkManager to find out whether a commit should be local or not.
38
try:
39
    import dbus
40
    import dbus.glib
180 by Jelmer Vernooij
Don't obtain handle to network manager until it's actually needed.
41
    have_dbus = True
158 by Jelmer Vernooij
If available, use NetworkManager to find out whether a commit should be local or not.
42
except ImportError:
180 by Jelmer Vernooij
Don't obtain handle to network manager until it's actually needed.
43
    have_dbus = False
158 by Jelmer Vernooij
If available, use NetworkManager to find out whether a commit should be local or not.
44
278.1.4 by John Arbash Meinel
Just playing around.
45
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
46
def pending_revisions(wt):
47
    """Return a list of pending merges or None if there are none of them.
48
49
    Arguably this should be a core function, and
50
    ``bzrlib.status.show_pending_merges`` should be built on top of it.
51
52
    :return: [(rev, [children])]
53
    """
54
    parents = wt.get_parent_ids()
55
    if len(parents) < 2:
56
        return None
57
58
    # The basic pending merge algorithm uses the same algorithm as
59
    # bzrlib.status.show_pending_merges
60
    pending = parents[1:]
61
    branch = wt.branch
62
    last_revision = parents[0]
63
64
    if last_revision is not None:
65
        try:
66
            ignore = set(branch.repository.get_ancestry(last_revision,
67
                                                        topo_sorted=False))
68
        except errors.NoSuchRevision:
69
            # the last revision is a ghost : assume everything is new
70
            # except for it
71
            ignore = set([None, last_revision])
72
    else:
73
        ignore = set([None])
74
75
    pm = []
76
    for merge in pending:
77
        ignore.add(merge)
78
        try:
79
            rev = branch.repository.get_revision(merge)
80
            children = []
81
            pm.append((rev, children))
82
83
            # This does need to be topo sorted, so we search backwards
84
            inner_merges = branch.repository.get_ancestry(merge)
85
            assert inner_merges[0] is None
86
            inner_merges.pop(0)
87
            for mmerge in reversed(inner_merges):
88
                if mmerge in ignore:
89
                    continue
90
                rev = branch.repository.get_revision(mmerge)
91
                children.append(rev)
92
93
                ignore.add(mmerge)
94
        except errors.NoSuchRevision:
95
            print "DEBUG: NoSuchRevision:", merge
96
97
    return pm
98
99
135 by Jelmer Vernooij
Throw out the old CommitDialog code and use the new code instead, also for 'gcommit'.
100
class CommitDialog(gtk.Dialog):
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
101
    """Implementation of Commit."""
102
103
    def __init__(self, wt, selected=None, parent=None):
278.1.16 by John Arbash Meinel
Implement the file changes list on top of _iter_changes rather than
104
        gtk.Dialog.__init__(self, title="Commit - Olive",
105
                                  parent=parent,
106
                                  flags=0,
107
                                  buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL))
278.1.24 by John Arbash Meinel
Actually show the commit button.
108
        self._question_dialog = question_dialog
109
278.1.16 by John Arbash Meinel
Implement the file changes list on top of _iter_changes rather than
110
        self._wt = wt
278.1.34 by John Arbash Meinel
Cleanup, we are still ignoring the 'selected' property, and the 'wtpath'
111
        # TODO: Do something with this value, it is used by Olive
112
        #       It used to set all changes but this one to False
278.1.16 by John Arbash Meinel
Implement the file changes list on top of _iter_changes rather than
113
        self._selected = selected
278.1.33 by John Arbash Meinel
Only enable the per-file dialog if 'per_file_commits' is enabled in the config.
114
        self._enable_per_file_commits = True
278.1.43 by John Arbash Meinel
Finish connecting the 'Commit all changes' radio buttons.
115
        self._commit_all_changes = True
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
116
        self.committed_revision_id = None # Nothing has been committed yet
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
117
278.1.16 by John Arbash Meinel
Implement the file changes list on top of _iter_changes rather than
118
        self.setup_params()
119
        self.construct()
120
        self.fill_in_data()
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
121
122
    def setup_params(self):
123
        """Setup the member variables for state."""
124
        self._basis_tree = self._wt.basis_tree()
278.1.12 by John Arbash Meinel
Delay computing the delta, and clean up some of the diff view names.
125
        self._delta = None
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
126
        self._pending = pending_revisions(self._wt)
127
128
        self._is_checkout = (self._wt.branch.get_bound_location() is not None)
129
278.1.14 by John Arbash Meinel
Tests that we fill out the pending list correctly.
130
    def fill_in_data(self):
131
        # Now that we are built, handle changes to the view based on the state
132
        self._fill_in_pending()
278.1.20 by John Arbash Meinel
We always select the All Files record in the files view,
133
        self._fill_in_diff()
278.1.15 by John Arbash Meinel
Hook up the list of modified files.
134
        self._fill_in_files()
278.1.25 by John Arbash Meinel
Add the 'Only Commit Locally' checkbox, we may want to put it elsewhere, though.
135
        self._fill_in_checkout()
278.1.33 by John Arbash Meinel
Only enable the per-file dialog if 'per_file_commits' is enabled in the config.
136
        self._fill_in_per_file_info()
278.1.14 by John Arbash Meinel
Tests that we fill out the pending list correctly.
137
138
    def _fill_in_pending(self):
139
        if not self._pending:
140
            self._pending_box.hide()
141
            return
142
143
        # TODO: We'd really prefer this to be a nested list
144
        for rev, children in self._pending:
145
            rev_info = self._rev_to_pending_info(rev)
278.1.15 by John Arbash Meinel
Hook up the list of modified files.
146
            self._pending_store.append([
278.1.14 by John Arbash Meinel
Tests that we fill out the pending list correctly.
147
                rev_info['revision_id'],
148
                rev_info['date'],
149
                rev_info['committer'],
150
                rev_info['summary'],
151
                ])
152
            for child in children:
153
                rev_info = self._rev_to_pending_info(child)
278.1.15 by John Arbash Meinel
Hook up the list of modified files.
154
                self._pending_store.append([
278.1.14 by John Arbash Meinel
Tests that we fill out the pending list correctly.
155
                    rev_info['revision_id'],
156
                    rev_info['date'],
157
                    rev_info['committer'],
158
                    rev_info['summary'],
159
                    ])
160
        self._pending_box.show()
161
278.1.15 by John Arbash Meinel
Hook up the list of modified files.
162
    def _fill_in_files(self):
278.1.29 by John Arbash Meinel
Start testing with Unicode data.
163
        # We should really use add a progress bar of some kind.
278.1.15 by John Arbash Meinel
Hook up the list of modified files.
164
        # While we fill in the view, hide the store
165
        store = self._files_store
166
        self._treeview_files.set_model(None)
167
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
168
        added = _i18n('added')
169
        removed = _i18n('removed')
170
        renamed = _i18n('renamed')
171
        renamed_and_modified = _i18n('renamed and modified')
172
        modified = _i18n('modified')
173
        kind_changed = _i18n('kind changed')
278.1.15 by John Arbash Meinel
Hook up the list of modified files.
174
278.1.16 by John Arbash Meinel
Implement the file changes list on top of _iter_changes rather than
175
        # The store holds:
278.1.21 by John Arbash Meinel
Start tracking the per-file commit messages.
176
        # [file_id, real path, checkbox, display path, changes type, message]
450 by Aaron Bentley
Update to use new Tree.iter_changes
177
        # iter_changes returns:
278.1.16 by John Arbash Meinel
Implement the file changes list on top of _iter_changes rather than
178
        # (file_id, (path_in_source, path_in_target),
179
        #  changed_content, versioned, parent, name, kind,
180
        #  executable)
181
278.1.35 by John Arbash Meinel
Make use of the 'selected' parameter to CommitDialog.
182
        all_enabled = (self._selected is None)
278.1.20 by John Arbash Meinel
We always select the All Files record in the files view,
183
        # The first entry is always the 'whole tree'
278.1.35 by John Arbash Meinel
Make use of the 'selected' parameter to CommitDialog.
184
        all_iter = store.append([None, None, all_enabled, 'All Files', '', ''])
185
        initial_cursor = store.get_path(all_iter)
278.1.16 by John Arbash Meinel
Implement the file changes list on top of _iter_changes rather than
186
        # should we pass specific_files?
187
        self._wt.lock_read()
188
        self._basis_tree.lock_read()
189
        try:
450 by Aaron Bentley
Update to use new Tree.iter_changes
190
            from diff import iter_changes_to_status
278.1.29 by John Arbash Meinel
Start testing with Unicode data.
191
            for (file_id, real_path, change_type, display_path
450 by Aaron Bentley
Update to use new Tree.iter_changes
192
                ) in iter_changes_to_status(self._basis_tree, self._wt):
278.1.35 by John Arbash Meinel
Make use of the 'selected' parameter to CommitDialog.
193
                if self._selected and real_path != self._selected:
194
                    enabled = False
195
                else:
196
                    enabled = True
197
                item_iter = store.append([
198
                    file_id,
199
                    real_path.encode('UTF-8'),
200
                    enabled,
201
                    display_path.encode('UTF-8'),
202
                    change_type,
203
                    '', # Initial comment
204
                    ])
205
                if self._selected and enabled:
206
                    initial_cursor = store.get_path(item_iter)
278.1.16 by John Arbash Meinel
Implement the file changes list on top of _iter_changes rather than
207
        finally:
208
            self._basis_tree.unlock()
209
            self._wt.unlock()
278.1.15 by John Arbash Meinel
Hook up the list of modified files.
210
211
        self._treeview_files.set_model(store)
278.1.21 by John Arbash Meinel
Start tracking the per-file commit messages.
212
        self._last_selected_file = None
278.1.32 by John Arbash Meinel
Add the Ctrl+n accelerator to jump through the commit messages.
213
        # This sets the cursor, which causes the expander to close, which
214
        # causes the _file_message_text_view to never get realized. So we have
215
        # to give it a little kick, or it warns when we try to grab the focus
278.1.35 by John Arbash Meinel
Make use of the 'selected' parameter to CommitDialog.
216
        self._treeview_files.set_cursor(initial_cursor)
278.1.15 by John Arbash Meinel
Hook up the list of modified files.
217
278.1.32 by John Arbash Meinel
Add the Ctrl+n accelerator to jump through the commit messages.
218
        def _realize_file_message_tree_view(*args):
219
            self._file_message_text_view.realize()
220
        self.connect_after('realize', _realize_file_message_tree_view)
221
278.1.17 by John Arbash Meinel
Add a * reference for why you can't change the commit selection.
222
    def _fill_in_diff(self):
223
        self._diff_view.set_trees(self._wt, self._basis_tree)
224
278.1.25 by John Arbash Meinel
Add the 'Only Commit Locally' checkbox, we may want to put it elsewhere, though.
225
    def _fill_in_checkout(self):
226
        if not self._is_checkout:
227
            self._check_local.hide()
228
            return
229
        if have_dbus:
230
            bus = dbus.SystemBus()
445 by Szilveszter Farkas (Phanatic)
Fix a traceback if NetworkManager is not available (#199513).
231
            try:
232
                proxy_obj = bus.get_object('org.freedesktop.NetworkManager',
233
                                           '/org/freedesktop/NetworkManager')
446 by Szilveszter Farkas (Phanatic)
Hot fix. Sorry dudes.
234
            except dbus.DBusException:
445 by Szilveszter Farkas (Phanatic)
Fix a traceback if NetworkManager is not available (#199513).
235
                mutter("networkmanager not available.")
236
                self._check_local.show()
237
                return
238
            
278.1.25 by John Arbash Meinel
Add the 'Only Commit Locally' checkbox, we may want to put it elsewhere, though.
239
            dbus_iface = dbus.Interface(proxy_obj,
240
                                        'org.freedesktop.NetworkManager')
241
            try:
242
                # 3 is the enum value for STATE_CONNECTED
243
                self._check_local.set_active(dbus_iface.state() != 3)
244
            except dbus.DBusException, e:
245
                # Silently drop errors. While DBus may be
246
                # available, NetworkManager doesn't necessarily have to be
247
                mutter("unable to get networkmanager state: %r" % e)
248
        self._check_local.show()
249
278.1.33 by John Arbash Meinel
Only enable the per-file dialog if 'per_file_commits' is enabled in the config.
250
    def _fill_in_per_file_info(self):
251
        config = self._wt.branch.get_config()
252
        enable_per_file_commits = config.get_user_option('per_file_commits')
253
        if (enable_per_file_commits is None
254
            or enable_per_file_commits.lower()
255
                not in ('y', 'yes', 'on', 'enable', '1', 't', 'true')):
256
            self._enable_per_file_commits = False
257
        else:
258
            self._enable_per_file_commits = True
259
        if not self._enable_per_file_commits:
260
            self._file_message_expander.hide()
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
261
            self._global_message_label.set_markup(_i18n('<b>Commit Message</b>'))
278.1.33 by John Arbash Meinel
Only enable the per-file dialog if 'per_file_commits' is enabled in the config.
262
278.1.12 by John Arbash Meinel
Delay computing the delta, and clean up some of the diff view names.
263
    def _compute_delta(self):
264
        self._delta = self._wt.changes_from(self._basis_tree)
265
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
266
    def construct(self):
267
        """Build up the dialog widgets."""
268
        # The primary pane which splits it into left and right (adjustable)
269
        # sections.
278.1.4 by John Arbash Meinel
Just playing around.
270
        self._hpane = gtk.HPaned()
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
271
272
        self._construct_left_pane()
273
        self._construct_right_pane()
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
274
        self._construct_action_pane()
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
275
276
        self.vbox.pack_start(self._hpane)
277
        self._hpane.show()
278
        self.set_focus(self._global_message_text_view)
279
278.1.32 by John Arbash Meinel
Add the Ctrl+n accelerator to jump through the commit messages.
280
        self._construct_accelerators()
281
        self._set_sizes()
282
283
    def _set_sizes(self):
278.1.17 by John Arbash Meinel
Add a * reference for why you can't change the commit selection.
284
        # This seems like a reasonable default, we might like it to
285
        # be a bit wider, so that by default we can fit an 80-line diff in the
286
        # diff window.
287
        # Alternatively, we should be saving the last position/size rather than
288
        # setting it to a fixed value every time we start up.
289
        screen = self.get_screen()
290
        monitor = 0 # We would like it to be the monitor we are going to
291
                    # display on, but I don't know how to figure that out
292
                    # Only really useful for freaks like me that run dual
293
                    # monitor, with different sizes on the monitors
294
        monitor_rect = screen.get_monitor_geometry(monitor)
295
        width = int(monitor_rect.width * 0.66)
296
        height = int(monitor_rect.height * 0.66)
297
        self.set_default_size(width, height)
278.1.16 by John Arbash Meinel
Implement the file changes list on top of _iter_changes rather than
298
        self._hpane.set_position(300)
299
278.1.32 by John Arbash Meinel
Add the Ctrl+n accelerator to jump through the commit messages.
300
    def _construct_accelerators(self):
301
        group = gtk.AccelGroup()
302
        group.connect_group(gtk.gdk.keyval_from_name('N'),
303
                            gtk.gdk.CONTROL_MASK, 0, self._on_accel_next)
304
        self.add_accel_group(group)
305
500.2.1 by Scott Scriven
Made 'gcommit' ignore the escape key ('close' signal).
306
        # ignore the escape key (avoid closing the window)
500.2.2 by Scott Scriven
Simpler/cleaner way to ignore the 'close' signal.
307
        self.connect_object('close', self.emit_stop_by_name, 'close')
500.2.1 by Scott Scriven
Made 'gcommit' ignore the escape key ('close' signal).
308
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
309
    def _construct_left_pane(self):
278.1.11 by John Arbash Meinel
Worked out the rest of the spacing.
310
        self._left_pane_box = gtk.VBox(homogeneous=False, spacing=5)
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
311
        self._construct_file_list()
312
        self._construct_pending_list()
313
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
314
        self._check_local = gtk.CheckButton(_i18n("_Only commit locally"),
278.1.25 by John Arbash Meinel
Add the 'Only Commit Locally' checkbox, we may want to put it elsewhere, though.
315
                                            use_underline=True)
316
        self._left_pane_box.pack_end(self._check_local, False, False)
317
        self._check_local.set_active(False)
318
278.1.15 by John Arbash Meinel
Hook up the list of modified files.
319
        self._hpane.pack1(self._left_pane_box, resize=False, shrink=False)
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
320
        self._left_pane_box.show()
321
322
    def _construct_right_pane(self):
323
        # TODO: I really want to make it so the diff view gets more space than
324
        # the global commit message, and the per-file commit message gets even
325
        # less. When I did it with wxGlade, I set it to 4 for diff, 2 for
326
        # commit, and 1 for file commit, and it looked good. But I don't seem
327
        # to have a way to do that with the gtk boxes... :( (Which is extra
328
        # weird since wx uses gtk on Linux...)
278.1.10 by John Arbash Meinel
To get the space weighting I wanted, I turned to a Table.
329
        self._right_pane_table = gtk.Table(rows=10, columns=1, homogeneous=False)
278.1.11 by John Arbash Meinel
Worked out the rest of the spacing.
330
        self._right_pane_table.set_row_spacings(5)
331
        self._right_pane_table.set_col_spacings(5)
278.1.10 by John Arbash Meinel
To get the space weighting I wanted, I turned to a Table.
332
        self._right_pane_table_row = 0
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
333
        self._construct_diff_view()
334
        self._construct_file_message()
335
        self._construct_global_message()
336
278.1.10 by John Arbash Meinel
To get the space weighting I wanted, I turned to a Table.
337
        self._right_pane_table.show()
338
        self._hpane.pack2(self._right_pane_table, resize=True, shrink=True)
339
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
340
    def _construct_action_pane(self):
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
341
        self._button_commit = gtk.Button(_i18n("Comm_it"), use_underline=True)
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
342
        self._button_commit.connect('clicked', self._on_commit_clicked)
343
        self._button_commit.set_flags(gtk.CAN_DEFAULT)
278.1.24 by John Arbash Meinel
Actually show the commit button.
344
        self._button_commit.show()
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
345
        self.action_area.pack_end(self._button_commit)
278.1.24 by John Arbash Meinel
Actually show the commit button.
346
        self._button_commit.grab_default()
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
347
278.1.10 by John Arbash Meinel
To get the space weighting I wanted, I turned to a Table.
348
    def _add_to_right_table(self, widget, weight, expanding=False):
349
        """Add another widget to the table
350
351
        :param widget: The object to add
352
        :param weight: How many rows does this widget get to request
353
        :param expanding: Should expand|fill|shrink be set?
354
        """
355
        end_row = self._right_pane_table_row + weight
356
        options = 0
357
        expand_opts = gtk.EXPAND | gtk.FILL | gtk.SHRINK
358
        if expanding:
359
            options = expand_opts
360
        self._right_pane_table.attach(widget, 0, 1,
361
                                      self._right_pane_table_row, end_row,
362
                                      xoptions=expand_opts, yoptions=options)
363
        self._right_pane_table_row = end_row
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
364
365
    def _construct_file_list(self):
278.1.11 by John Arbash Meinel
Worked out the rest of the spacing.
366
        self._files_box = gtk.VBox(homogeneous=False, spacing=0)
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
367
        file_label = gtk.Label(_i18n('Files'))
278.1.41 by John Arbash Meinel
For the moment, just hide the section headings Files and Diff for *.
368
        # file_label.show()
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
369
        self._files_box.pack_start(file_label, expand=False)
370
278.1.42 by John Arbash Meinel
start playing with using a radial box, rather than an entry in the list
371
        self._commit_all_files_radio = gtk.RadioButton(
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
372
            None, _i18n("Commit all changes"))
278.1.42 by John Arbash Meinel
start playing with using a radial box, rather than an entry in the list
373
        self._files_box.pack_start(self._commit_all_files_radio, expand=False)
374
        self._commit_all_files_radio.show()
278.1.43 by John Arbash Meinel
Finish connecting the 'Commit all changes' radio buttons.
375
        self._commit_all_files_radio.connect('toggled',
376
            self._toggle_commit_selection)
278.1.42 by John Arbash Meinel
start playing with using a radial box, rather than an entry in the list
377
        self._commit_selected_radio = gtk.RadioButton(
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
378
            self._commit_all_files_radio, _i18n("Only commit selected changes"))
278.1.42 by John Arbash Meinel
start playing with using a radial box, rather than an entry in the list
379
        self._files_box.pack_start(self._commit_selected_radio, expand=False)
380
        self._commit_selected_radio.show()
278.1.43 by John Arbash Meinel
Finish connecting the 'Commit all changes' radio buttons.
381
        self._commit_selected_radio.connect('toggled',
382
            self._toggle_commit_selection)
383
        if self._pending:
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
384
            self._commit_all_files_radio.set_label(_i18n('Commit all changes*'))
278.1.43 by John Arbash Meinel
Finish connecting the 'Commit all changes' radio buttons.
385
            self._commit_all_files_radio.set_sensitive(False)
386
            self._commit_selected_radio.set_sensitive(False)
278.1.42 by John Arbash Meinel
start playing with using a radial box, rather than an entry in the list
387
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
388
        scroller = gtk.ScrolledWindow()
389
        scroller.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
126.1.1 by Szilveszter Farkas (Phanatic)
New Commit dialog implementation (no more Glade).
390
        self._treeview_files = gtk.TreeView()
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
391
        self._treeview_files.show()
392
        scroller.add(self._treeview_files)
278.1.32 by John Arbash Meinel
Add the Ctrl+n accelerator to jump through the commit messages.
393
        scroller.set_shadow_type(gtk.SHADOW_IN)
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
394
        scroller.show()
395
        self._files_box.pack_start(scroller,
396
                                   expand=True, fill=True)
397
        self._files_box.show()
398
        self._left_pane_box.pack_start(self._files_box)
399
278.1.31 by John Arbash Meinel
We can make bencode work again by a simple decode/encode step.
400
        # Keep note that all strings stored in a ListStore must be UTF-8
401
        # strings. GTK does not support directly setting and restoring Unicode
402
        # objects.
278.1.15 by John Arbash Meinel
Hook up the list of modified files.
403
        liststore = gtk.ListStore(
404
            gobject.TYPE_STRING,  # [0] file_id
405
            gobject.TYPE_STRING,  # [1] real path
406
            gobject.TYPE_BOOLEAN, # [2] checkbox
407
            gobject.TYPE_STRING,  # [3] display path
408
            gobject.TYPE_STRING,  # [4] changes type
278.1.21 by John Arbash Meinel
Start tracking the per-file commit messages.
409
            gobject.TYPE_STRING,  # [5] commit message
278.1.15 by John Arbash Meinel
Hook up the list of modified files.
410
            )
411
        self._files_store = liststore
412
        self._treeview_files.set_model(liststore)
413
        crt = gtk.CellRendererToggle()
278.1.39 by John Arbash Meinel
To disable a checkbox it is set_property('activatable', False),
414
        crt.set_property('activatable', not bool(self._pending))
278.1.15 by John Arbash Meinel
Hook up the list of modified files.
415
        crt.connect("toggled", self._toggle_commit, self._files_store)
278.1.17 by John Arbash Meinel
Add a * reference for why you can't change the commit selection.
416
        if self._pending:
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
417
            name = _i18n('Commit*')
278.1.17 by John Arbash Meinel
Add a * reference for why you can't change the commit selection.
418
        else:
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
419
            name = _i18n('Commit')
278.1.43 by John Arbash Meinel
Finish connecting the 'Commit all changes' radio buttons.
420
        commit_col = gtk.TreeViewColumn(name, crt, active=2)
421
        commit_col.set_visible(False)
422
        self._treeview_files.append_column(commit_col)
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
423
        self._treeview_files.append_column(gtk.TreeViewColumn(_i18n('Path'),
278.1.15 by John Arbash Meinel
Hook up the list of modified files.
424
                                           gtk.CellRendererText(), text=3))
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
425
        self._treeview_files.append_column(gtk.TreeViewColumn(_i18n('Type'),
278.1.15 by John Arbash Meinel
Hook up the list of modified files.
426
                                           gtk.CellRendererText(), text=4))
278.1.17 by John Arbash Meinel
Add a * reference for why you can't change the commit selection.
427
        self._treeview_files.connect('cursor-changed',
428
                                     self._on_treeview_files_cursor_changed)
278.1.15 by John Arbash Meinel
Hook up the list of modified files.
429
430
    def _toggle_commit(self, cell, path, model):
278.1.20 by John Arbash Meinel
We always select the All Files record in the files view,
431
        if model[path][0] is None: # No file_id means 'All Files'
432
            new_val = not model[path][2]
433
            for node in model:
434
                node[2] = new_val
435
        else:
436
            model[path][2] = not model[path][2]
278.1.15 by John Arbash Meinel
Hook up the list of modified files.
437
278.1.43 by John Arbash Meinel
Finish connecting the 'Commit all changes' radio buttons.
438
    def _toggle_commit_selection(self, button):
439
        all_files = self._commit_all_files_radio.get_active()
440
        if self._commit_all_changes != all_files:
441
            checked_col = self._treeview_files.get_column(0)
442
            self._commit_all_changes = all_files
443
            if all_files:
444
                checked_col.set_visible(False)
445
            else:
446
                checked_col.set_visible(True)
447
            renderer = checked_col.get_cell_renderers()[0]
448
            renderer.set_property('activatable', not all_files)
449
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
450
    def _construct_pending_list(self):
451
        # Pending information defaults to hidden, we put it all in 1 box, so
452
        # that we can show/hide all of them at once
453
        self._pending_box = gtk.VBox()
454
        self._pending_box.hide()
455
456
        pending_message = gtk.Label()
457
        pending_message.set_markup(
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
458
            _i18n('<i>* Cannot select specific files when merging</i>'))
278.1.11 by John Arbash Meinel
Worked out the rest of the spacing.
459
        self._pending_box.pack_start(pending_message, expand=False, padding=5)
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
460
        pending_message.show()
461
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
462
        pending_label = gtk.Label(_i18n('Pending Revisions'))
278.1.11 by John Arbash Meinel
Worked out the rest of the spacing.
463
        self._pending_box.pack_start(pending_label, expand=False, padding=0)
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
464
        pending_label.show()
465
466
        scroller = gtk.ScrolledWindow()
467
        scroller.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
468
        self._treeview_pending = gtk.TreeView()
469
        scroller.add(self._treeview_pending)
278.1.32 by John Arbash Meinel
Add the Ctrl+n accelerator to jump through the commit messages.
470
        scroller.set_shadow_type(gtk.SHADOW_IN)
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
471
        scroller.show()
472
        self._pending_box.pack_start(scroller,
278.1.11 by John Arbash Meinel
Worked out the rest of the spacing.
473
                                     expand=True, fill=True, padding=5)
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
474
        self._treeview_pending.show()
475
        self._left_pane_box.pack_start(self._pending_box)
476
278.1.15 by John Arbash Meinel
Hook up the list of modified files.
477
        liststore = gtk.ListStore(gobject.TYPE_STRING, # revision_id
478
                                  gobject.TYPE_STRING, # date
479
                                  gobject.TYPE_STRING, # committer
480
                                  gobject.TYPE_STRING, # summary
278.1.14 by John Arbash Meinel
Tests that we fill out the pending list correctly.
481
                                 )
278.1.15 by John Arbash Meinel
Hook up the list of modified files.
482
        self._pending_store = liststore
278.1.14 by John Arbash Meinel
Tests that we fill out the pending list correctly.
483
        self._treeview_pending.set_model(liststore)
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
484
        self._treeview_pending.append_column(gtk.TreeViewColumn(_i18n('Date'),
278.1.14 by John Arbash Meinel
Tests that we fill out the pending list correctly.
485
                                             gtk.CellRendererText(), text=1))
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
486
        self._treeview_pending.append_column(gtk.TreeViewColumn(_i18n('Committer'),
278.1.14 by John Arbash Meinel
Tests that we fill out the pending list correctly.
487
                                             gtk.CellRendererText(), text=2))
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
488
        self._treeview_pending.append_column(gtk.TreeViewColumn(_i18n('Summary'),
278.1.14 by John Arbash Meinel
Tests that we fill out the pending list correctly.
489
                                             gtk.CellRendererText(), text=3))
490
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
491
    def _construct_diff_view(self):
278.1.12 by John Arbash Meinel
Delay computing the delta, and clean up some of the diff view names.
492
        from diff import DiffView
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
493
278.1.41 by John Arbash Meinel
For the moment, just hide the section headings Files and Diff for *.
494
        # TODO: jam 2007-10-30 The diff label is currently disabled. If we
495
        #       decide that we really don't ever want to display it, we should
496
        #       actually remove it, and other references to it, along with the
497
        #       tests that it is set properly.
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
498
        self._diff_label = gtk.Label(_i18n('Diff for whole tree'))
278.1.11 by John Arbash Meinel
Worked out the rest of the spacing.
499
        self._diff_label.set_alignment(0, 0)
500
        self._right_pane_table.set_row_spacing(self._right_pane_table_row, 0)
278.1.10 by John Arbash Meinel
To get the space weighting I wanted, I turned to a Table.
501
        self._add_to_right_table(self._diff_label, 1, False)
278.1.41 by John Arbash Meinel
For the moment, just hide the section headings Files and Diff for *.
502
        # self._diff_label.show()
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
503
278.1.12 by John Arbash Meinel
Delay computing the delta, and clean up some of the diff view names.
504
        self._diff_view = DiffView()
278.1.10 by John Arbash Meinel
To get the space weighting I wanted, I turned to a Table.
505
        self._add_to_right_table(self._diff_view, 4, True)
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
506
        self._diff_view.show()
507
508
    def _construct_file_message(self):
278.1.9 by John Arbash Meinel
Move all text entry boxes into a ScrolledWindow, so that they don't change size constantly.
509
        scroller = gtk.ScrolledWindow()
510
        scroller.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
511
512
        self._file_message_text_view = gtk.TextView()
513
        scroller.add(self._file_message_text_view)
278.1.32 by John Arbash Meinel
Add the Ctrl+n accelerator to jump through the commit messages.
514
        scroller.set_shadow_type(gtk.SHADOW_IN)
278.1.9 by John Arbash Meinel
Move all text entry boxes into a ScrolledWindow, so that they don't change size constantly.
515
        scroller.show()
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
516
517
        self._file_message_text_view.modify_font(pango.FontDescription("Monospace"))
518
        self._file_message_text_view.set_wrap_mode(gtk.WRAP_WORD)
519
        self._file_message_text_view.set_accepts_tab(False)
520
        self._file_message_text_view.show()
521
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
522
        self._file_message_expander = gtk.Expander(_i18n('File commit message'))
278.1.32 by John Arbash Meinel
Add the Ctrl+n accelerator to jump through the commit messages.
523
        self._file_message_expander.set_expanded(True)
524
        self._file_message_expander.add(scroller)
278.1.10 by John Arbash Meinel
To get the space weighting I wanted, I turned to a Table.
525
        self._add_to_right_table(self._file_message_expander, 1, False)
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
526
        self._file_message_expander.show()
527
528
    def _construct_global_message(self):
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
529
        self._global_message_label = gtk.Label(_i18n('Global Commit Message'))
530
        self._global_message_label.set_markup(
531
            _i18n('<b>Global Commit Message</b>'))
278.1.11 by John Arbash Meinel
Worked out the rest of the spacing.
532
        self._global_message_label.set_alignment(0, 0)
533
        self._right_pane_table.set_row_spacing(self._right_pane_table_row, 0)
278.1.10 by John Arbash Meinel
To get the space weighting I wanted, I turned to a Table.
534
        self._add_to_right_table(self._global_message_label, 1, False)
278.1.11 by John Arbash Meinel
Worked out the rest of the spacing.
535
        # Can we remove the spacing between the label and the box?
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
536
        self._global_message_label.show()
537
278.1.9 by John Arbash Meinel
Move all text entry boxes into a ScrolledWindow, so that they don't change size constantly.
538
        scroller = gtk.ScrolledWindow()
539
        scroller.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
540
541
        self._global_message_text_view = gtk.TextView()
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
542
        self._global_message_text_view.modify_font(pango.FontDescription("Monospace"))
278.1.9 by John Arbash Meinel
Move all text entry boxes into a ScrolledWindow, so that they don't change size constantly.
543
        scroller.add(self._global_message_text_view)
278.1.32 by John Arbash Meinel
Add the Ctrl+n accelerator to jump through the commit messages.
544
        scroller.set_shadow_type(gtk.SHADOW_IN)
278.1.9 by John Arbash Meinel
Move all text entry boxes into a ScrolledWindow, so that they don't change size constantly.
545
        scroller.show()
278.1.10 by John Arbash Meinel
To get the space weighting I wanted, I turned to a Table.
546
        self._add_to_right_table(scroller, 2, True)
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
547
        self._file_message_text_view.set_wrap_mode(gtk.WRAP_WORD)
548
        self._file_message_text_view.set_accepts_tab(False)
549
        self._global_message_text_view.show()
550
278.1.17 by John Arbash Meinel
Add a * reference for why you can't change the commit selection.
551
    def _on_treeview_files_cursor_changed(self, treeview):
278.1.18 by John Arbash Meinel
Start checking the diff view is correct.
552
        treeselection = treeview.get_selection()
278.1.21 by John Arbash Meinel
Start tracking the per-file commit messages.
553
        (model, selection) = treeselection.get_selected()
278.1.17 by John Arbash Meinel
Add a * reference for why you can't change the commit selection.
554
278.1.21 by John Arbash Meinel
Start tracking the per-file commit messages.
555
        if selection is not None:
556
            path, display_path = model.get(selection, 1, 3)
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
557
            self._diff_label.set_text(_i18n('Diff for ') + display_path)
278.1.20 by John Arbash Meinel
We always select the All Files record in the files view,
558
            if path is None:
559
                self._diff_view.show_diff(None)
560
            else:
278.1.29 by John Arbash Meinel
Start testing with Unicode data.
561
                self._diff_view.show_diff([path.decode('UTF-8')])
278.1.21 by John Arbash Meinel
Start tracking the per-file commit messages.
562
            self._update_per_file_info(selection)
563
278.1.32 by John Arbash Meinel
Add the Ctrl+n accelerator to jump through the commit messages.
564
    def _on_accel_next(self, accel_group, window, keyval, modifier):
565
        # We don't really care about any of the parameters, because we know
566
        # where this message came from
567
        tree_selection = self._treeview_files.get_selection()
568
        (model, selection) = tree_selection.get_selected()
569
        if selection is None:
570
            next = None
571
        else:
572
            next = model.iter_next(selection)
573
574
        if next is None:
575
            # We have either made it to the end of the list, or nothing was
576
            # selected. Either way, select All Files, and jump to the global
577
            # commit message.
578
            self._treeview_files.set_cursor((0,))
579
            self._global_message_text_view.grab_focus()
580
        else:
581
            # Set the cursor to this entry, and jump to the per-file commit
582
            # message
583
            self._treeview_files.set_cursor(model.get_path(next))
584
            self._file_message_text_view.grab_focus()
585
278.1.21 by John Arbash Meinel
Start tracking the per-file commit messages.
586
    def _save_current_file_message(self):
587
        if self._last_selected_file is None:
588
            return # Nothing to save
589
        text_buffer = self._file_message_text_view.get_buffer()
590
        cur_text = text_buffer.get_text(text_buffer.get_start_iter(),
591
                                        text_buffer.get_end_iter())
592
        last_selected = self._files_store.get_iter(self._last_selected_file)
593
        self._files_store.set_value(last_selected, 5, cur_text)
594
595
    def _update_per_file_info(self, selection):
596
        # The node is changing, so cache the current message
278.1.33 by John Arbash Meinel
Only enable the per-file dialog if 'per_file_commits' is enabled in the config.
597
        if not self._enable_per_file_commits:
598
            return
599
278.1.21 by John Arbash Meinel
Start tracking the per-file commit messages.
600
        self._save_current_file_message()
601
        text_buffer = self._file_message_text_view.get_buffer()
602
        file_id, display_path, message = self._files_store.get(selection, 0, 3, 5)
603
        if file_id is None: # Whole tree
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
604
            self._file_message_expander.set_label(_i18n('File commit message'))
278.1.21 by John Arbash Meinel
Start tracking the per-file commit messages.
605
            self._file_message_expander.set_expanded(False)
606
            self._file_message_expander.set_sensitive(False)
607
            text_buffer.set_text('')
608
            self._last_selected_file = None
609
        else:
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
610
            self._file_message_expander.set_label(_i18n('Commit message for ')
278.1.21 by John Arbash Meinel
Start tracking the per-file commit messages.
611
                                                  + display_path)
612
            self._file_message_expander.set_expanded(True)
613
            self._file_message_expander.set_sensitive(True)
614
            text_buffer.set_text(message)
615
            self._last_selected_file = self._files_store.get_path(selection)
278.1.17 by John Arbash Meinel
Add a * reference for why you can't change the commit selection.
616
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
617
    def _get_specific_files(self):
278.1.31 by John Arbash Meinel
We can make bencode work again by a simple decode/encode step.
618
        """Return the list of selected paths, and file info.
619
620
        :return: ([unicode paths], [{utf-8 file info}]
621
        """
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
622
        self._save_current_file_message()
623
        files = []
624
        records = iter(self._files_store)
625
        rec = records.next() # Skip the All Files record
626
        assert rec[0] is None, "Are we skipping the wrong record?"
627
628
        file_info = []
629
        for record in records:
278.1.43 by John Arbash Meinel
Finish connecting the 'Commit all changes' radio buttons.
630
            if self._commit_all_changes or record[2]:# [2] checkbox
278.1.29 by John Arbash Meinel
Start testing with Unicode data.
631
                file_id = record[0] # [0] file_id
278.1.31 by John Arbash Meinel
We can make bencode work again by a simple decode/encode step.
632
                path = record[1]    # [1] real path
278.1.29 by John Arbash Meinel
Start testing with Unicode data.
633
                file_message = record[5] # [5] commit message
634
                files.append(path.decode('UTF-8'))
278.1.33 by John Arbash Meinel
Only enable the per-file dialog if 'per_file_commits' is enabled in the config.
635
                if self._enable_per_file_commits and file_message:
278.1.29 by John Arbash Meinel
Start testing with Unicode data.
636
                    # All of this needs to be utf-8 information
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
637
                    file_info.append({'path':path, 'file_id':file_id,
638
                                     'message':file_message})
639
        file_info.sort(key=lambda x:(x['path'], x['file_id']))
278.1.33 by John Arbash Meinel
Only enable the per-file dialog if 'per_file_commits' is enabled in the config.
640
        if self._enable_per_file_commits:
641
            return files, file_info
642
        else:
643
            return files, []
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
644
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
645
    @show_bzr_error
646
    def _on_commit_clicked(self, button):
647
        """ Commit button clicked handler. """
648
        self._do_commit()
649
650
    def _do_commit(self):
278.1.25 by John Arbash Meinel
Add the 'Only Commit Locally' checkbox, we may want to put it elsewhere, though.
651
        message = self._get_global_commit_message()
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
652
653
        if message == '':
654
            response = self._question_dialog(
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
655
                _i18n('Commit with an empty message?'),
656
                _i18n('You can describe your commit intent in the message.'))
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
657
            if response == gtk.RESPONSE_NO:
658
                # Kindly give focus to message area
659
                self._global_message_text_view.grab_focus()
660
                return
661
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
662
        specific_files, file_info = self._get_specific_files()
278.1.28 by John Arbash Meinel
Ensure that we can set per-file messages even during a merge.
663
        if self._pending:
664
            specific_files = None
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
665
278.1.25 by John Arbash Meinel
Add the 'Only Commit Locally' checkbox, we may want to put it elsewhere, though.
666
        local = self._check_local.get_active()
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
667
278.1.26 by John Arbash Meinel
Handle pointless commits and trees with unknown files.
668
        # All we care about is if there is a single unknown, so if this loop is
669
        # entered, then there are unknown files.
670
        # TODO: jam 20071002 It seems like this should cancel the dialog
671
        #       entirely, since there isn't a way for them to add the unknown
672
        #       files at this point.
673
        for path in self._wt.unknowns():
674
            response = self._question_dialog(
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
675
                _i18n("Commit with unknowns?"),
676
                _i18n("Unknown files exist in the working tree. Commit anyway?"))
278.1.26 by John Arbash Meinel
Handle pointless commits and trees with unknown files.
677
            if response == gtk.RESPONSE_NO:
678
                return
679
            break
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
680
278.1.25 by John Arbash Meinel
Add the 'Only Commit Locally' checkbox, we may want to put it elsewhere, though.
681
        rev_id = None
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
682
        revprops = {}
683
        if file_info:
278.1.31 by John Arbash Meinel
We can make bencode work again by a simple decode/encode step.
684
            revprops['file-info'] = bencode.bencode(file_info).decode('UTF-8')
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
685
        try:
686
            rev_id = self._wt.commit(message,
687
                       allow_pointless=False,
688
                       strict=False,
689
                       local=local,
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
690
                       specific_files=specific_files,
691
                       revprops=revprops)
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
692
        except errors.PointlessCommit:
278.1.26 by John Arbash Meinel
Handle pointless commits and trees with unknown files.
693
            response = self._question_dialog(
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
694
                _i18n('Commit with no changes?'),
695
                _i18n('There are no changes in the working tree.'
696
                      ' Do you want to commit anyway?'))
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
697
            if response == gtk.RESPONSE_YES:
698
                rev_id = self._wt.commit(message,
699
                               allow_pointless=True,
700
                               strict=False,
701
                               local=local,
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
702
                               specific_files=specific_files,
703
                               revprops=revprops)
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
704
        self.committed_revision_id = rev_id
705
        self.response(gtk.RESPONSE_OK)
706
278.1.25 by John Arbash Meinel
Add the 'Only Commit Locally' checkbox, we may want to put it elsewhere, though.
707
    def _get_global_commit_message(self):
708
        buf = self._global_message_text_view.get_buffer()
709
        start, end = buf.get_bounds()
710
        return buf.get_text(start, end).decode('utf-8')
711
712
    def _set_global_commit_message(self, message):
713
        """Just a helper for the test suite."""
278.1.29 by John Arbash Meinel
Start testing with Unicode data.
714
        if isinstance(message, unicode):
715
            message = message.encode('UTF-8')
278.1.25 by John Arbash Meinel
Add the 'Only Commit Locally' checkbox, we may want to put it elsewhere, though.
716
        self._global_message_text_view.get_buffer().set_text(message)
717
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
718
    def _set_file_commit_message(self, message):
719
        """Helper for the test suite."""
278.1.29 by John Arbash Meinel
Start testing with Unicode data.
720
        if isinstance(message, unicode):
721
            message = message.encode('UTF-8')
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
722
        self._file_message_text_view.get_buffer().set_text(message)
723
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
724
    @staticmethod
725
    def _rev_to_pending_info(rev):
726
        """Get the information from a pending merge."""
126.1.1 by Szilveszter Farkas (Phanatic)
New Commit dialog implementation (no more Glade).
727
        from bzrlib.osutils import format_date
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
728
        rev_dict = {}
729
        rev_dict['committer'] = re.sub('<.*@.*>', '', rev.committer).strip(' ')
730
        rev_dict['summary'] = rev.get_summary()
731
        rev_dict['date'] = format_date(rev.timestamp,
732
                                       rev.timezone or 0,
733
                                       'original', date_fmt="%Y-%m-%d",
734
                                       show_offset=False)
735
        rev_dict['revision_id'] = rev.revision_id
736
        return rev_dict