/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
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
306
    def _construct_left_pane(self):
278.1.11 by John Arbash Meinel
Worked out the rest of the spacing.
307
        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.
308
        self._construct_file_list()
309
        self._construct_pending_list()
310
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
311
        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.
312
                                            use_underline=True)
313
        self._left_pane_box.pack_end(self._check_local, False, False)
314
        self._check_local.set_active(False)
315
278.1.15 by John Arbash Meinel
Hook up the list of modified files.
316
        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.
317
        self._left_pane_box.show()
318
319
    def _construct_right_pane(self):
320
        # TODO: I really want to make it so the diff view gets more space than
321
        # the global commit message, and the per-file commit message gets even
322
        # less. When I did it with wxGlade, I set it to 4 for diff, 2 for
323
        # commit, and 1 for file commit, and it looked good. But I don't seem
324
        # to have a way to do that with the gtk boxes... :( (Which is extra
325
        # 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.
326
        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.
327
        self._right_pane_table.set_row_spacings(5)
328
        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.
329
        self._right_pane_table_row = 0
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
330
        self._construct_diff_view()
331
        self._construct_file_message()
332
        self._construct_global_message()
333
278.1.10 by John Arbash Meinel
To get the space weighting I wanted, I turned to a Table.
334
        self._right_pane_table.show()
335
        self._hpane.pack2(self._right_pane_table, resize=True, shrink=True)
336
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
337
    def _construct_action_pane(self):
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
338
        self._button_commit = gtk.Button(_i18n("Comm_it"), use_underline=True)
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
339
        self._button_commit.connect('clicked', self._on_commit_clicked)
340
        self._button_commit.set_flags(gtk.CAN_DEFAULT)
278.1.24 by John Arbash Meinel
Actually show the commit button.
341
        self._button_commit.show()
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
342
        self.action_area.pack_end(self._button_commit)
278.1.24 by John Arbash Meinel
Actually show the commit button.
343
        self._button_commit.grab_default()
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
344
278.1.10 by John Arbash Meinel
To get the space weighting I wanted, I turned to a Table.
345
    def _add_to_right_table(self, widget, weight, expanding=False):
346
        """Add another widget to the table
347
348
        :param widget: The object to add
349
        :param weight: How many rows does this widget get to request
350
        :param expanding: Should expand|fill|shrink be set?
351
        """
352
        end_row = self._right_pane_table_row + weight
353
        options = 0
354
        expand_opts = gtk.EXPAND | gtk.FILL | gtk.SHRINK
355
        if expanding:
356
            options = expand_opts
357
        self._right_pane_table.attach(widget, 0, 1,
358
                                      self._right_pane_table_row, end_row,
359
                                      xoptions=expand_opts, yoptions=options)
360
        self._right_pane_table_row = end_row
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
361
362
    def _construct_file_list(self):
278.1.11 by John Arbash Meinel
Worked out the rest of the spacing.
363
        self._files_box = gtk.VBox(homogeneous=False, spacing=0)
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
364
        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 *.
365
        # file_label.show()
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
366
        self._files_box.pack_start(file_label, expand=False)
367
278.1.42 by John Arbash Meinel
start playing with using a radial box, rather than an entry in the list
368
        self._commit_all_files_radio = gtk.RadioButton(
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
369
            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
370
        self._files_box.pack_start(self._commit_all_files_radio, expand=False)
371
        self._commit_all_files_radio.show()
278.1.43 by John Arbash Meinel
Finish connecting the 'Commit all changes' radio buttons.
372
        self._commit_all_files_radio.connect('toggled',
373
            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
374
        self._commit_selected_radio = gtk.RadioButton(
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
375
            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
376
        self._files_box.pack_start(self._commit_selected_radio, expand=False)
377
        self._commit_selected_radio.show()
278.1.43 by John Arbash Meinel
Finish connecting the 'Commit all changes' radio buttons.
378
        self._commit_selected_radio.connect('toggled',
379
            self._toggle_commit_selection)
380
        if self._pending:
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
381
            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.
382
            self._commit_all_files_radio.set_sensitive(False)
383
            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
384
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
385
        scroller = gtk.ScrolledWindow()
386
        scroller.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
126.1.1 by Szilveszter Farkas (Phanatic)
New Commit dialog implementation (no more Glade).
387
        self._treeview_files = gtk.TreeView()
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
388
        self._treeview_files.show()
389
        scroller.add(self._treeview_files)
278.1.32 by John Arbash Meinel
Add the Ctrl+n accelerator to jump through the commit messages.
390
        scroller.set_shadow_type(gtk.SHADOW_IN)
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
391
        scroller.show()
392
        self._files_box.pack_start(scroller,
393
                                   expand=True, fill=True)
394
        self._files_box.show()
395
        self._left_pane_box.pack_start(self._files_box)
396
278.1.31 by John Arbash Meinel
We can make bencode work again by a simple decode/encode step.
397
        # Keep note that all strings stored in a ListStore must be UTF-8
398
        # strings. GTK does not support directly setting and restoring Unicode
399
        # objects.
278.1.15 by John Arbash Meinel
Hook up the list of modified files.
400
        liststore = gtk.ListStore(
401
            gobject.TYPE_STRING,  # [0] file_id
402
            gobject.TYPE_STRING,  # [1] real path
403
            gobject.TYPE_BOOLEAN, # [2] checkbox
404
            gobject.TYPE_STRING,  # [3] display path
405
            gobject.TYPE_STRING,  # [4] changes type
278.1.21 by John Arbash Meinel
Start tracking the per-file commit messages.
406
            gobject.TYPE_STRING,  # [5] commit message
278.1.15 by John Arbash Meinel
Hook up the list of modified files.
407
            )
408
        self._files_store = liststore
409
        self._treeview_files.set_model(liststore)
410
        crt = gtk.CellRendererToggle()
278.1.39 by John Arbash Meinel
To disable a checkbox it is set_property('activatable', False),
411
        crt.set_property('activatable', not bool(self._pending))
278.1.15 by John Arbash Meinel
Hook up the list of modified files.
412
        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.
413
        if self._pending:
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
414
            name = _i18n('Commit*')
278.1.17 by John Arbash Meinel
Add a * reference for why you can't change the commit selection.
415
        else:
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
416
            name = _i18n('Commit')
278.1.43 by John Arbash Meinel
Finish connecting the 'Commit all changes' radio buttons.
417
        commit_col = gtk.TreeViewColumn(name, crt, active=2)
418
        commit_col.set_visible(False)
419
        self._treeview_files.append_column(commit_col)
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
420
        self._treeview_files.append_column(gtk.TreeViewColumn(_i18n('Path'),
278.1.15 by John Arbash Meinel
Hook up the list of modified files.
421
                                           gtk.CellRendererText(), text=3))
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
422
        self._treeview_files.append_column(gtk.TreeViewColumn(_i18n('Type'),
278.1.15 by John Arbash Meinel
Hook up the list of modified files.
423
                                           gtk.CellRendererText(), text=4))
278.1.17 by John Arbash Meinel
Add a * reference for why you can't change the commit selection.
424
        self._treeview_files.connect('cursor-changed',
425
                                     self._on_treeview_files_cursor_changed)
278.1.15 by John Arbash Meinel
Hook up the list of modified files.
426
427
    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,
428
        if model[path][0] is None: # No file_id means 'All Files'
429
            new_val = not model[path][2]
430
            for node in model:
431
                node[2] = new_val
432
        else:
433
            model[path][2] = not model[path][2]
278.1.15 by John Arbash Meinel
Hook up the list of modified files.
434
278.1.43 by John Arbash Meinel
Finish connecting the 'Commit all changes' radio buttons.
435
    def _toggle_commit_selection(self, button):
436
        all_files = self._commit_all_files_radio.get_active()
437
        if self._commit_all_changes != all_files:
438
            checked_col = self._treeview_files.get_column(0)
439
            self._commit_all_changes = all_files
440
            if all_files:
441
                checked_col.set_visible(False)
442
            else:
443
                checked_col.set_visible(True)
444
            renderer = checked_col.get_cell_renderers()[0]
445
            renderer.set_property('activatable', not all_files)
446
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
447
    def _construct_pending_list(self):
448
        # Pending information defaults to hidden, we put it all in 1 box, so
449
        # that we can show/hide all of them at once
450
        self._pending_box = gtk.VBox()
451
        self._pending_box.hide()
452
453
        pending_message = gtk.Label()
454
        pending_message.set_markup(
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
455
            _i18n('<i>* Cannot select specific files when merging</i>'))
278.1.11 by John Arbash Meinel
Worked out the rest of the spacing.
456
        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.
457
        pending_message.show()
458
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
459
        pending_label = gtk.Label(_i18n('Pending Revisions'))
278.1.11 by John Arbash Meinel
Worked out the rest of the spacing.
460
        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.
461
        pending_label.show()
462
463
        scroller = gtk.ScrolledWindow()
464
        scroller.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
465
        self._treeview_pending = gtk.TreeView()
466
        scroller.add(self._treeview_pending)
278.1.32 by John Arbash Meinel
Add the Ctrl+n accelerator to jump through the commit messages.
467
        scroller.set_shadow_type(gtk.SHADOW_IN)
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
468
        scroller.show()
469
        self._pending_box.pack_start(scroller,
278.1.11 by John Arbash Meinel
Worked out the rest of the spacing.
470
                                     expand=True, fill=True, padding=5)
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
471
        self._treeview_pending.show()
472
        self._left_pane_box.pack_start(self._pending_box)
473
278.1.15 by John Arbash Meinel
Hook up the list of modified files.
474
        liststore = gtk.ListStore(gobject.TYPE_STRING, # revision_id
475
                                  gobject.TYPE_STRING, # date
476
                                  gobject.TYPE_STRING, # committer
477
                                  gobject.TYPE_STRING, # summary
278.1.14 by John Arbash Meinel
Tests that we fill out the pending list correctly.
478
                                 )
278.1.15 by John Arbash Meinel
Hook up the list of modified files.
479
        self._pending_store = liststore
278.1.14 by John Arbash Meinel
Tests that we fill out the pending list correctly.
480
        self._treeview_pending.set_model(liststore)
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
481
        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.
482
                                             gtk.CellRendererText(), text=1))
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
483
        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.
484
                                             gtk.CellRendererText(), text=2))
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
485
        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.
486
                                             gtk.CellRendererText(), text=3))
487
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
488
    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.
489
        from diff import DiffView
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
490
278.1.41 by John Arbash Meinel
For the moment, just hide the section headings Files and Diff for *.
491
        # TODO: jam 2007-10-30 The diff label is currently disabled. If we
492
        #       decide that we really don't ever want to display it, we should
493
        #       actually remove it, and other references to it, along with the
494
        #       tests that it is set properly.
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
495
        self._diff_label = gtk.Label(_i18n('Diff for whole tree'))
278.1.11 by John Arbash Meinel
Worked out the rest of the spacing.
496
        self._diff_label.set_alignment(0, 0)
497
        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.
498
        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 *.
499
        # self._diff_label.show()
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
500
278.1.12 by John Arbash Meinel
Delay computing the delta, and clean up some of the diff view names.
501
        self._diff_view = DiffView()
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_view, 4, True)
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
503
        self._diff_view.show()
504
505
    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.
506
        scroller = gtk.ScrolledWindow()
507
        scroller.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
508
509
        self._file_message_text_view = gtk.TextView()
510
        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.
511
        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.
512
        scroller.show()
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
513
514
        self._file_message_text_view.modify_font(pango.FontDescription("Monospace"))
515
        self._file_message_text_view.set_wrap_mode(gtk.WRAP_WORD)
516
        self._file_message_text_view.set_accepts_tab(False)
517
        self._file_message_text_view.show()
518
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
519
        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.
520
        self._file_message_expander.set_expanded(True)
521
        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.
522
        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.
523
        self._file_message_expander.show()
524
525
    def _construct_global_message(self):
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
526
        self._global_message_label = gtk.Label(_i18n('Global Commit Message'))
527
        self._global_message_label.set_markup(
528
            _i18n('<b>Global Commit Message</b>'))
278.1.11 by John Arbash Meinel
Worked out the rest of the spacing.
529
        self._global_message_label.set_alignment(0, 0)
530
        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.
531
        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.
532
        # 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.
533
        self._global_message_label.show()
534
278.1.9 by John Arbash Meinel
Move all text entry boxes into a ScrolledWindow, so that they don't change size constantly.
535
        scroller = gtk.ScrolledWindow()
536
        scroller.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
537
538
        self._global_message_text_view = gtk.TextView()
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
539
        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.
540
        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.
541
        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.
542
        scroller.show()
278.1.10 by John Arbash Meinel
To get the space weighting I wanted, I turned to a Table.
543
        self._add_to_right_table(scroller, 2, True)
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
544
        self._file_message_text_view.set_wrap_mode(gtk.WRAP_WORD)
545
        self._file_message_text_view.set_accepts_tab(False)
546
        self._global_message_text_view.show()
547
278.1.17 by John Arbash Meinel
Add a * reference for why you can't change the commit selection.
548
    def _on_treeview_files_cursor_changed(self, treeview):
278.1.18 by John Arbash Meinel
Start checking the diff view is correct.
549
        treeselection = treeview.get_selection()
278.1.21 by John Arbash Meinel
Start tracking the per-file commit messages.
550
        (model, selection) = treeselection.get_selected()
278.1.17 by John Arbash Meinel
Add a * reference for why you can't change the commit selection.
551
278.1.21 by John Arbash Meinel
Start tracking the per-file commit messages.
552
        if selection is not None:
553
            path, display_path = model.get(selection, 1, 3)
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
554
            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,
555
            if path is None:
556
                self._diff_view.show_diff(None)
557
            else:
278.1.29 by John Arbash Meinel
Start testing with Unicode data.
558
                self._diff_view.show_diff([path.decode('UTF-8')])
278.1.21 by John Arbash Meinel
Start tracking the per-file commit messages.
559
            self._update_per_file_info(selection)
560
278.1.32 by John Arbash Meinel
Add the Ctrl+n accelerator to jump through the commit messages.
561
    def _on_accel_next(self, accel_group, window, keyval, modifier):
562
        # We don't really care about any of the parameters, because we know
563
        # where this message came from
564
        tree_selection = self._treeview_files.get_selection()
565
        (model, selection) = tree_selection.get_selected()
566
        if selection is None:
567
            next = None
568
        else:
569
            next = model.iter_next(selection)
570
571
        if next is None:
572
            # We have either made it to the end of the list, or nothing was
573
            # selected. Either way, select All Files, and jump to the global
574
            # commit message.
575
            self._treeview_files.set_cursor((0,))
576
            self._global_message_text_view.grab_focus()
577
        else:
578
            # Set the cursor to this entry, and jump to the per-file commit
579
            # message
580
            self._treeview_files.set_cursor(model.get_path(next))
581
            self._file_message_text_view.grab_focus()
582
278.1.21 by John Arbash Meinel
Start tracking the per-file commit messages.
583
    def _save_current_file_message(self):
584
        if self._last_selected_file is None:
585
            return # Nothing to save
586
        text_buffer = self._file_message_text_view.get_buffer()
587
        cur_text = text_buffer.get_text(text_buffer.get_start_iter(),
588
                                        text_buffer.get_end_iter())
589
        last_selected = self._files_store.get_iter(self._last_selected_file)
590
        self._files_store.set_value(last_selected, 5, cur_text)
591
592
    def _update_per_file_info(self, selection):
593
        # 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.
594
        if not self._enable_per_file_commits:
595
            return
596
278.1.21 by John Arbash Meinel
Start tracking the per-file commit messages.
597
        self._save_current_file_message()
598
        text_buffer = self._file_message_text_view.get_buffer()
599
        file_id, display_path, message = self._files_store.get(selection, 0, 3, 5)
600
        if file_id is None: # Whole tree
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
601
            self._file_message_expander.set_label(_i18n('File commit message'))
278.1.21 by John Arbash Meinel
Start tracking the per-file commit messages.
602
            self._file_message_expander.set_expanded(False)
603
            self._file_message_expander.set_sensitive(False)
604
            text_buffer.set_text('')
605
            self._last_selected_file = None
606
        else:
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
607
            self._file_message_expander.set_label(_i18n('Commit message for ')
278.1.21 by John Arbash Meinel
Start tracking the per-file commit messages.
608
                                                  + display_path)
609
            self._file_message_expander.set_expanded(True)
610
            self._file_message_expander.set_sensitive(True)
611
            text_buffer.set_text(message)
612
            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.
613
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
614
    def _get_specific_files(self):
278.1.31 by John Arbash Meinel
We can make bencode work again by a simple decode/encode step.
615
        """Return the list of selected paths, and file info.
616
617
        :return: ([unicode paths], [{utf-8 file info}]
618
        """
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
619
        self._save_current_file_message()
620
        files = []
621
        records = iter(self._files_store)
622
        rec = records.next() # Skip the All Files record
623
        assert rec[0] is None, "Are we skipping the wrong record?"
624
625
        file_info = []
626
        for record in records:
278.1.43 by John Arbash Meinel
Finish connecting the 'Commit all changes' radio buttons.
627
            if self._commit_all_changes or record[2]:# [2] checkbox
278.1.29 by John Arbash Meinel
Start testing with Unicode data.
628
                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.
629
                path = record[1]    # [1] real path
278.1.29 by John Arbash Meinel
Start testing with Unicode data.
630
                file_message = record[5] # [5] commit message
631
                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.
632
                if self._enable_per_file_commits and file_message:
278.1.29 by John Arbash Meinel
Start testing with Unicode data.
633
                    # All of this needs to be utf-8 information
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
634
                    file_info.append({'path':path, 'file_id':file_id,
635
                                     'message':file_message})
636
        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.
637
        if self._enable_per_file_commits:
638
            return files, file_info
639
        else:
640
            return files, []
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
641
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
642
    @show_bzr_error
643
    def _on_commit_clicked(self, button):
644
        """ Commit button clicked handler. """
645
        self._do_commit()
646
647
    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.
648
        message = self._get_global_commit_message()
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
649
650
        if message == '':
651
            response = self._question_dialog(
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
652
                _i18n('Commit with an empty message?'),
653
                _i18n('You can describe your commit intent in the message.'))
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
654
            if response == gtk.RESPONSE_NO:
655
                # Kindly give focus to message area
656
                self._global_message_text_view.grab_focus()
657
                return
658
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
659
        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.
660
        if self._pending:
661
            specific_files = None
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
662
278.1.25 by John Arbash Meinel
Add the 'Only Commit Locally' checkbox, we may want to put it elsewhere, though.
663
        local = self._check_local.get_active()
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
664
278.1.26 by John Arbash Meinel
Handle pointless commits and trees with unknown files.
665
        # All we care about is if there is a single unknown, so if this loop is
666
        # entered, then there are unknown files.
667
        # TODO: jam 20071002 It seems like this should cancel the dialog
668
        #       entirely, since there isn't a way for them to add the unknown
669
        #       files at this point.
670
        for path in self._wt.unknowns():
671
            response = self._question_dialog(
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
672
                _i18n("Commit with unknowns?"),
673
                _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.
674
            if response == gtk.RESPONSE_NO:
675
                return
676
            break
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
677
278.1.25 by John Arbash Meinel
Add the 'Only Commit Locally' checkbox, we may want to put it elsewhere, though.
678
        rev_id = None
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
679
        revprops = {}
680
        if file_info:
278.1.31 by John Arbash Meinel
We can make bencode work again by a simple decode/encode step.
681
            revprops['file-info'] = bencode.bencode(file_info).decode('UTF-8')
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
682
        try:
683
            rev_id = self._wt.commit(message,
684
                       allow_pointless=False,
685
                       strict=False,
686
                       local=local,
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
687
                       specific_files=specific_files,
688
                       revprops=revprops)
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
689
        except errors.PointlessCommit:
278.1.26 by John Arbash Meinel
Handle pointless commits and trees with unknown files.
690
            response = self._question_dialog(
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
691
                _i18n('Commit with no changes?'),
692
                _i18n('There are no changes in the working tree.'
693
                      ' Do you want to commit anyway?'))
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
694
            if response == gtk.RESPONSE_YES:
695
                rev_id = self._wt.commit(message,
696
                               allow_pointless=True,
697
                               strict=False,
698
                               local=local,
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
699
                               specific_files=specific_files,
700
                               revprops=revprops)
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
701
        self.committed_revision_id = rev_id
702
        self.response(gtk.RESPONSE_OK)
703
278.1.25 by John Arbash Meinel
Add the 'Only Commit Locally' checkbox, we may want to put it elsewhere, though.
704
    def _get_global_commit_message(self):
705
        buf = self._global_message_text_view.get_buffer()
706
        start, end = buf.get_bounds()
707
        return buf.get_text(start, end).decode('utf-8')
708
709
    def _set_global_commit_message(self, message):
710
        """Just a helper for the test suite."""
278.1.29 by John Arbash Meinel
Start testing with Unicode data.
711
        if isinstance(message, unicode):
712
            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.
713
        self._global_message_text_view.get_buffer().set_text(message)
714
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
715
    def _set_file_commit_message(self, message):
716
        """Helper for the test suite."""
278.1.29 by John Arbash Meinel
Start testing with Unicode data.
717
        if isinstance(message, unicode):
718
            message = message.encode('UTF-8')
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
719
        self._file_message_text_view.get_buffer().set_text(message)
720
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
721
    @staticmethod
722
    def _rev_to_pending_info(rev):
723
        """Get the information from a pending merge."""
126.1.1 by Szilveszter Farkas (Phanatic)
New Commit dialog implementation (no more Glade).
724
        from bzrlib.osutils import format_date
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
725
        rev_dict = {}
726
        rev_dict['committer'] = re.sub('<.*@.*>', '', rev.committer).strip(' ')
727
        rev_dict['summary'] = rev.get_summary()
728
        rev_dict['date'] = format_date(rev.timestamp,
729
                                       rev.timezone or 0,
730
                                       'original', date_fmt="%Y-%m-%d",
731
                                       show_offset=False)
732
        rev_dict['revision_id'] = rev.revision_id
733
        return rev_dict