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