#
#
# add_file "monotone-viz.png"
# content [41853635f2bb5932843f444ed771d8567293aac6]
#
# add_file "monotone-viz.svg"
# content [973e3787f47c4a046492a95282b7569ce0268179]
#
# patch "AdvancedFind.pm"
# from [a90d12286cf6e8c1f007258d4f1f47132ad31ad6]
# to [e9ff33befd44ace6ba5b2ae8f19ba741aec3842c]
#
# patch "Annotate.pm"
# from [3d84076dd913242ae97ac02928f0c9c06d135bb0]
# to [c6d0364b1eb14d721a0ea41ddbd5bdad8be6ff92]
#
# patch "ChangeLog.pm"
# from [29bfd342dd8c58bec9de9a76117d716d1d751ec1]
# to [ee5aff7fcef19a382436ed70b03e97622c3e6203]
#
# patch "ComboAutoCompletion.pm"
# from [e937b0a45f4630b3d66c78facb6bd46424e5ff6e]
# to [2acc9ad8ef8ac0c2baba340449aaf332e0b14bfb]
#
# patch "FindText.pm"
# from [fb45334bd2a8c0fd1882b6db0f809ea7a4d4263c]
# to [a39b09074fbe7e628f6e4d00dff7bc185b76518d]
#
# patch "Globals.pm"
# from [ecdab5e2efb3efb1365114eebe1a8c78f69fde70]
# to [66eff7abeb8443d29387430e0272aa8422d870ae]
#
# patch "History.pm"
# from [af7d6fa7f0a54b077395133175779100bfb733c3]
# to [8b6634e67b518d62381d23706d63705c8275c5ff]
#
# patch "Utilities.pm"
# from [ed70fcf9cb4926124ffacfaaf44c0496b7556ff8]
# to [bd2f0818e5f09a128c1ca297bb6612181d50ea1e]
#
# patch "mtn-browse"
# from [26de6cb7a6b55cd1d37820d87d2a2c45b65f6b06]
# to [bcf437debb1b500536ecc393c8aaa5521bd62266]
#
# patch "mtn-browse.glade"
# from [56a671155946b9d7d2878ecdc2e1fdf3e5cddb43]
# to [b87a22f4310537a066635f9e4aa8554dd053f606]
#
# set "monotone-viz.png"
# attr "mtn:manual_merge"
# value "true"
#
============================================================
# monotone-viz.png is binary
============================================================
--- monotone-viz.svg 973e3787f47c4a046492a95282b7569ce0268179
+++ monotone-viz.svg 973e3787f47c4a046492a95282b7569ce0268179
@@ -0,0 +1,200 @@
+
+
+
============================================================
--- AdvancedFind.pm a90d12286cf6e8c1f007258d4f1f47132ad31ad6
+++ AdvancedFind.pm e9ff33befd44ace6ba5b2ae8f19ba741aec3842c
@@ -94,9 +94,8 @@ sub advanced_find($$$)
my($browser, $revision_id, $branches) = @_;
my($advanced_find,
- $height,
$new,
- $width);
+ $ret_val);
# Look for an unused window first.
@@ -127,6 +126,10 @@ sub advanced_find($$$)
# Update the window's internal state.
{
+
+ my($height,
+ $width);
+
local $advanced_find->{in_cb} = 1;
$advanced_find->{selected} = 0;
@@ -160,14 +163,14 @@ sub advanced_find($$$)
# Now actually update it with any preset values.
$advanced_find->{branch_combo_details}->{preset} = 1;
- $advanced_find->{branch_combo_details}->{completed} =
- $browser->{branch_combo_details}->{completed};
+ $advanced_find->{branch_combo_details}->{complete} =
+ $browser->{branch_combo_details}->{complete};
$advanced_find->{branch_combo_details}->{value} =
$browser->{branch_combo_details}->{value};
$advanced_find->{revision_combo_details}->{preset} = 1;
- $advanced_find->{revision_combo_details}->{completed} =
- $browser->{revision_combo_details}->{completed};
+ $advanced_find->{revision_combo_details}->{complete} =
+ $browser->{revision_combo_details}->{complete};
$advanced_find->{revision_combo_details}->{value} =
$browser->{revision_combo_details}->{value};
@@ -175,6 +178,7 @@ sub advanced_find($$$)
set_active($browser->{tagged_tick}->get_active());
&{$advanced_find->{update_handler}}($advanced_find, NEW_FIND);
+
}
# Handle all events until the dialog is dismissed.
@@ -223,13 +227,13 @@ sub advanced_find($$$)
if ($found);
push(@$branches, "") if (scalar(@$branches) == 0);
- return 1;
+ $ret_val = 1;
}
- else
- {
- return;
- }
+ $advanced_find->{mtn} = undef;
+
+ return $ret_val;
+
}
#
##############################################################################
@@ -256,8 +260,7 @@ sub create_advanced_find_window()
$instance = {};
$instance->{type} = $window_type;
- $instance->{glade} =
- Gtk2::GladeXML->new("../mtn-browse.glade", $window_type);
+ $instance->{glade} = Gtk2::GladeXML->new($glade_file, $window_type);
# Flag to stop recursive calling of callbacks.
@@ -274,7 +277,6 @@ sub create_advanced_find_window()
# Get the widgets that we are interested in.
$instance->{window} = $instance->{glade}->get_widget($window_type);
- $instance->{window}->set_icon($app_icon);
$instance->{appbar} = $instance->{glade}->get_widget("appbar");
$instance->{simple_query_radiobutton} =
$instance->{glade}->get_widget("simple_query_radiobutton");
@@ -734,7 +736,7 @@ sub update_advanced_find_state($$)
}
else
{
- $advanced_find->{branch_combo_details}->{completed} = 0;
+ $advanced_find->{branch_combo_details}->{complete} = 0;
$advanced_find->{branch_combo_details}->{value} = "";
}
@@ -783,13 +785,13 @@ sub update_advanced_find_state($$)
}
else
{
- $advanced_find->{revision_combo_details}->{completed} = 0;
+ $advanced_find->{revision_combo_details}->{complete} = 0;
$advanced_find->{revision_combo_details}->{value} = "";
}
# Get the new list of revisions.
- if ($advanced_find->{branch_combo_details}->{completed})
+ if ($advanced_find->{branch_combo_details}->{complete})
{
$advanced_find->{appbar}->set_status("Fetching revision list");
gtk2_update();
@@ -876,14 +878,15 @@ sub update_advanced_find_state($$)
gtk2_update();
if ($advanced_find->{simple_query_radiobutton}->get_active())
{
- if ($advanced_find->{revision_combo_details}->{completed})
+ if ($advanced_find->{revision_combo_details}->{complete})
{
get_revision_ids($advanced_find, address@hidden);
}
}
else
{
- my $query;
+ my($err,
+ $query);
$query = $advanced_find->{search_term_combo}->child()->get_text();
# Remember the user can type in any old rubbish with advanced
@@ -909,10 +912,13 @@ sub update_advanced_find_state($$)
{
$advanced_find->{mtn}->select(address@hidden, $query);
};
+ $err = $@;
+ Monotone::AutomateStdio->register_error_handler
+ ("both", \&mtn_error_handler);
# If the query was valid the store it in the history.
- if (! $@)
+ if ($err eq "")
{
my $found;
if (scalar(@revision_ids) == 0)
@@ -951,8 +957,6 @@ sub update_advanced_find_state($$)
}
}
}
- Monotone::AutomateStdio->register_error_handler
- ("both", \&mtn_error_handler);
}
$advanced_find->{mtn}->toposort(address@hidden, @revision_ids);
@@ -1010,6 +1014,9 @@ sub update_advanced_find_state($$)
# Scroll back up to the top left.
+ $advanced_find->{details_buffer}->
+ place_cursor($advanced_find->{details_buffer}->
+ get_start_iter());
if ($advanced_find->{details_scrolledwindow}->realized())
{
$advanced_find->{details_scrolledwindow}->
============================================================
--- Annotate.pm 3d84076dd913242ae97ac02928f0c9c06d135bb0
+++ Annotate.pm c6d0364b1eb14d721a0ea41ddbd5bdad8be6ff92
@@ -176,6 +176,8 @@ sub display_annotation($$$)
# Make sure we are at the top.
+ $instance->{annotation_buffer}->
+ place_cursor($instance->{annotation_buffer}->get_start_iter());
$instance->{annotation_scrolledwindow}->get_vadjustment()->set_value(0);
$instance->{annotation_scrolledwindow}->get_hadjustment()->set_value(0);
$instance->{appbar}->set_progress_percentage(0);
@@ -227,8 +229,7 @@ sub get_annotation_window()
{
$instance = {};
$instance->{type} = $window_type;
- $instance->{glade} =
- Gtk2::GladeXML->new("../mtn-browse.glade", $window_type);
+ $instance->{glade} = Gtk2::GladeXML->new($glade_file, $window_type);
# Flag to stop recursive calling of callbacks.
@@ -241,7 +242,6 @@ sub get_annotation_window()
# Get the widgets that we are interested in.
$instance->{window} = $instance->{glade}->get_widget($window_type);
- $instance->{window}->set_icon($app_icon);
$instance->{appbar} = $instance->{glade}->get_widget("appbar");
$instance->{annotation_textview} =
$instance->{glade}->get_widget("annotation_textview");
============================================================
--- ChangeLog.pm 29bfd342dd8c58bec9de9a76117d716d1d751ec1
+++ ChangeLog.pm ee5aff7fcef19a382436ed70b03e97622c3e6203
@@ -94,6 +94,8 @@ sub display_change_log($$;$$)
address@hidden,
$text_colour ? $text_colour : "",
address@hidden);
+ $instance->{changelog_buffer}->
+ place_cursor($instance->{changelog_buffer}->get_start_iter());
if ($instance->{changelog_scrolledwindow}->realized())
{
$instance->{changelog_scrolledwindow}->get_vadjustment()->set_value(0);
@@ -143,8 +145,7 @@ sub get_change_log_window()
{
$instance = {};
$instance->{type} = $window_type;
- $instance->{glade} =
- Gtk2::GladeXML->new("../mtn-browse.glade", $window_type);
+ $instance->{glade} = Gtk2::GladeXML->new($glade_file, $window_type);
# Flag to stop recursive calling of callbacks.
@@ -157,7 +158,6 @@ sub get_change_log_window()
# Get the widgets that we are interested in.
$instance->{window} = $instance->{glade}->get_widget($window_type);
- $instance->{window}->set_icon($app_icon);
$instance->{changelog_textview} =
$instance->{glade}->get_widget("changelog_textview");
$instance->{changelog_scrolledwindow} =
============================================================
--- ComboAutoCompletion.pm e937b0a45f4630b3d66c78facb6bd46424e5ff6e
+++ ComboAutoCompletion.pm 2acc9ad8ef8ac0c2baba340449aaf332e0b14bfb
@@ -114,7 +114,7 @@ sub combo_changed_cb($$)
if ($value eq $item)
{
$combo_details->{value} = $value;
- $combo_details->{completed} = 1;
+ $combo_details->{complete} = 1;
$instance->{appbar}->clear_stack();
&{$instance->{update_handler}}($instance, $change_state);
last;
@@ -156,12 +156,12 @@ sub combo_key_release_event_cb($$$)
my($change_state,
$combo,
$combo_details,
- $completed,
+ $complete,
$completion,
$item,
$len,
$name,
- $old_completed,
+ $old_complete,
$old_value,
$value);
@@ -194,8 +194,8 @@ sub combo_key_release_event_cb($$$)
# The user has typed something in then validate it and auto-complete it if
# necessary.
- $completed = 0;
- $old_completed = $combo_details->{completed};
+ $complete = 0;
+ $old_complete = $combo_details->{complete};
$old_value = $combo_details->{value};
$value = $widget->get_text();
if ($value ne $old_value)
@@ -219,7 +219,7 @@ sub combo_key_release_event_cb($$$)
if ($combo_details->{completion}->get_completion($value,
\$completion,
- \$completed))
+ \$complete))
{
$instance->{appbar}->clear_stack();
}
@@ -235,7 +235,7 @@ sub combo_key_release_event_cb($$$)
}
$combo_details->{value} = $value;
- $combo_details->{completed} = $completed;
+ $combo_details->{complete} = $complete;
# Update the pulldown choices.
@@ -243,14 +243,13 @@ sub combo_key_release_event_cb($$$)
foreach $item (@{$combo_details->{list}})
{
$combo->append_text($item) if ($value eq substr($item, 0, $len));
- $combo_details->{completed} = 1
- if (! $completed && $value eq $item);
+ $combo_details->{complete} = 1 if (! $complete && $value eq $item);
}
# Update the window state on a significant change.
&{$instance->{update_handler}}($instance, $change_state)
- if ($combo_details->{completed} != $old_completed
+ if ($combo_details->{complete} != $old_complete
|| $combo_details->{value} ne $old_value);
}
============================================================
--- FindText.pm fb45334bd2a8c0fd1882b6db0f809ea7a4d4263c
+++ FindText.pm a39b09074fbe7e628f6e4d00dff7bc185b76518d
@@ -239,8 +239,7 @@ sub get_find_text_window($$)
$new = 1;
$instance = {};
$instance->{type} = $window_type;
- $instance->{glade} =
- Gtk2::GladeXML->new("../mtn-browse.glade", $window_type);
+ $instance->{glade} = Gtk2::GladeXML->new($glade_file, $window_type);
# Flag to stop recursive calling of callbacks.
@@ -253,7 +252,6 @@ sub get_find_text_window($$)
# Get the widgets that we are interested in.
$instance->{window} = $instance->{glade}->get_widget($window_type);
- $instance->{window}->set_icon($app_icon);
$instance->{main_vbox} = $instance->{glade}->get_widget("main_vbox");
$instance->{find_combo} =
$instance->{glade}->get_widget("find_comboboxentry");
============================================================
--- Globals.pm ecdab5e2efb3efb1365114eebe1a8c78f69fde70
+++ Globals.pm 66eff7abeb8443d29387430e0272aa8422d870ae
@@ -81,6 +81,30 @@ use constant SELECTED_REVISION_CHANGED =
| DISPLAY_OF_FILE);
use constant SELECTED_REVISION_CHANGED => (REVISION_DETAILS);
+# Location of the Glade UI XML file for mtn-browse.
+
+our $glade_file;
+
+# Location of the temporary working directory.
+
+our $tmp_dir;
+
+# List of window instances.
+
+our @windows;
+
+# Assorted pixmaps.
+
+our $line_image;
+
+# The busy cursor to use for the mouse.
+
+our $busy_cursor;
+
+# The tooltips widget.
+
+our $tooltips;
+
# Text viewable application mime types.
our @text_viewable_app_mime_types =
@@ -101,7 +125,7 @@ our @text_viewable_app_mime_types =
x-troff
xhtml+xml);
-# Supported text mime types (used for syntax highlighting.
+# Supported text mime types (used for syntax highlighting).
our @text_mime_types =
(
@@ -131,23 +155,6 @@ our @text_mime_types =
}
);
-# List of window instances.
-
-our @windows;
-
-# Assorted pixmaps.
-
-our($app_icon,
- $line_image);
-
-# The busy cursor to use for the mouse.
-
-our $busy_cursor;
-
-# The tooltips widget.
-
-our $tooltips;
-
# ***** PACKAGE INFORMATION *****
use base qw(Exporter);
@@ -169,12 +176,13 @@ our %EXPORT_TAGS = (constants => [qw(ALL
REVISION_DETAILS
REVISION_LIST
SELECTED_REVISION_CHANGED)],
- variables => [qw($app_icon
- $busy_cursor
+ variables => [qw($busy_cursor
+ $glade_file
$line_image
- $tooltips
@text_mime_types
@text_viewable_app_mime_types
+ $tmp_dir
+ $tooltips
@windows)]);
our @EXPORT = qw();
Exporter::export_ok_tags(qw(constants variables));
============================================================
--- History.pm af7d6fa7f0a54b077395133175779100bfb733c3
+++ History.pm 8b6634e67b518d62381d23706d63705c8275c5ff
@@ -256,6 +256,8 @@ sub display_revision_change_history($$)
# Make sure we are at the top.
+ $instance->{history_buffer}->
+ place_cursor($instance->{history_buffer}->get_start_iter());
$instance->{history_scrolledwindow}->get_vadjustment()->set_value(0);
$instance->{history_scrolledwindow}->get_hadjustment()->set_value(0);
$instance->{appbar}->set_progress_percentage(0);
@@ -445,6 +447,8 @@ sub display_file_change_history($$$)
# Make sure we are at the top.
+ $instance->{history_buffer}->
+ place_cursor($instance->{history_buffer}->get_start_iter());
$instance->{history_scrolledwindow}->get_vadjustment()->set_value(0);
$instance->{history_scrolledwindow}->get_hadjustment()->set_value(0);
$instance->{appbar}->set_progress_percentage(0);
@@ -633,6 +637,274 @@ sub compare_button_clicked_cb($$)
#
##############################################################################
#
+# Routine - compare_revisions
+#
+# Description - Compares and then displays the differeneces between the two
+# specified revisions, optionally restricting it to the
+# specified file.
+#
+# Data - $mtn : The Monotone instance handle that is to be
+# used to do the comparison.
+# $revision_id_1 : The first revision id that is to be
+# compared.
+# $revision_id_2 : The second revision id that is to be
+# compared.
+# $file_name : Either the name of the file that the
+# revision comparison should be restricted
+# to or undef for a full revision
+# comparison.
+#
+##############################################################################
+
+
+
+sub compare_revisions($$$;$)
+{
+
+ my($mtn, $revision_id_1, $revision_id_2, $file_name) = @_;
+
+ my($char,
+ @files,
+ $i,
+ $instance,
+ $is_binary,
+ $iter,
+ $len,
+ $line,
+ @lines,
+ $max_len,
+ $name,
+ $padding,
+ $rest);
+
+ $instance = get_revision_comparison_window();
+ local $instance->{in_cb} = 1;
+
+ $instance->{window}->set_title("Differences Between Revisions "
+ . $revision_id_1
+ . " And "
+ . $revision_id_2);
+ if (defined($file_name))
+ {
+ $instance->{comparison_label}->set_markup("File Comparison");
+ }
+ else
+ {
+ $instance->{comparison_label}->
+ set_markup("Revision Comparison");
+ }
+ $instance->{window}->show_all();
+
+ make_busy($instance, 1);
+ $instance->{appbar}->push("");
+ gtk2_update();
+
+ $instance->{mtn} = $mtn;
+ $instance->{red_revision_id} = $revision_id_1;
+ $instance->{green_revision_id} = $revision_id_2;
+
+ # Get Monotone to do the comparison.
+
+ $instance->{appbar}->set_status("Calculating differences");
+ gtk2_update();
+ mtn_diff(address@hidden,
+ $mtn->get_db_name(),
+ $revision_id_1,
+ $revision_id_2,
+ $file_name);
+
+ # Find the longest line for future padding.
+
+ $max_len = 0;
+ foreach my $line (@lines)
+ {
+ ($char, $rest) = unpack("a1a*", $line);
+ $rest =~ s/\s+$//o;
+ $rest = expand($rest);
+ $max_len = $len if (($len = length($rest)) > $max_len);
+ $line = $char . $rest;
+ }
+
+ # Display the result, highlighting according to the diff output. Remember
+ # the first two lines are just empty comment lines.
+
+ $instance->{appbar}->set_status("Formatting and displaying differences");
+ gtk2_update();
+ $padding = " " x $max_len;
+ $line = substr(" Summary" . $padding, 0, $max_len);
+ $instance->{comparison_buffer}->insert_with_tags_by_name
+ ($instance->{comparison_buffer}->get_end_iter(),
+ $line . "\n",
+ "compare-info");
+ for ($i = 1; $i <= $#lines; ++ $i)
+ {
+
+ # Deal with the initial comment lines that summarise the entire set of
+ # differences between the revisions.
+
+ if ($lines[$i] =~ m/^\#/o)
+ {
+ $line = substr($lines[$i], 1);
+ $instance->{comparison_buffer}->insert
+ ($instance->{comparison_buffer}->get_end_iter(),
+ $line . "\n");
+ }
+
+ # Deal with lines that introduces a new file comparison.
+
+ elsif ($lines[$i] =~ m/^==/o)
+ {
+
+ # Print separator.
+
+ $instance->{comparison_buffer}->
+ insert_pixbuf($instance->{comparison_buffer}->get_end_iter(),
+ $line_image);
+ $instance->{comparison_buffer}->
+ insert($instance->{comparison_buffer}->get_end_iter(),
+ "\n");
+
+ # Extract the file name, if this doesn't work then it is probably a
+ # comment stating that the file is binary.
+
+ ++ $i;
+ ($name) = ($lines[$i] =~ m/^--- (.+)\s+[0-9a-f]{40}$/o);
+ if (defined($name))
+ {
+ $is_binary = 0;
+ }
+ else
+ {
+ ($name) = ($lines[$i] =~ m/^\# (.+) is binary$/o);
+ $is_binary = 1;
+ }
+
+ # Print out the details for the first file.
+
+ $line = substr(substr($lines[$i], $is_binary ? 1 : 3) . $padding,
+ 0,
+ $max_len);
+ $instance->{comparison_buffer}->insert_with_tags_by_name
+ ($instance->{comparison_buffer}->get_end_iter(),
+ $line . "\n",
+ "compare-first-file-info");
+
+ # Store the file name and the starting line number so that the user
+ # can later jump straight to it using the file combobox.
+
+ $iter = $instance->{comparison_buffer}->get_end_iter();
+ $iter->backward_line();
+ $instance->{comparison_buffer}->create_mark($name, $iter, FALSE);
+ push(@files, {file_name => $name, line_nr => $iter->get_line()});
+
+ # Print out the details for the second file if there is one.
+
+ if (! $is_binary)
+ {
+ ++ $i;
+ $line = substr(substr($lines[$i], 3) . $padding, 0, $max_len);
+ $instance->{comparison_buffer}->insert_with_tags_by_name
+ ($instance->{comparison_buffer}->get_end_iter(),
+ $line . "\n",
+ "compare-second-file-info");
+ }
+
+ }
+
+ # Deal with difference context lines.
+
+ elsif ($lines[$i] =~ m/^@@/o)
+ {
+ $line = substr(substr($lines[$i], 2) . $padding, 0, $max_len);
+ $instance->{comparison_buffer}->insert_with_tags_by_name
+ ($instance->{comparison_buffer}->get_end_iter(),
+ $line . "\n",
+ "compare-info");
+ }
+
+ # Deal with - change lines.
+
+ elsif ($lines[$i] =~ m/^-/o)
+ {
+ $line = substr(substr($lines[$i], 1) . $padding, 0, $max_len);
+ $instance->{comparison_buffer}->insert_with_tags_by_name
+ ($instance->{comparison_buffer}->get_end_iter(),
+ $line . "\n",
+ "compare-first-file");
+ }
+
+ # Deal with + change lines.
+
+ elsif ($lines[$i] =~ m/^\+/o)
+ {
+ $line = substr(substr($lines[$i], 1) . $padding, 0, $max_len);
+ $instance->{comparison_buffer}->insert_with_tags_by_name
+ ($instance->{comparison_buffer}->get_end_iter(),
+ $line . "\n",
+ "compare-second-file");
+ }
+
+ # Print out the rest.
+
+ else
+ {
+ $line = substr($lines[$i], 1);
+ $instance->{comparison_buffer}->insert
+ ($instance->{comparison_buffer}->get_end_iter(),
+ $line . "\n");
+ }
+
+ if (($i % 100) == 0)
+ {
+ $instance->{appbar}->set_progress_percentage
+ (($i + 1) / scalar(@lines));
+ gtk2_update();
+ }
+
+ }
+
+ # Delete the trailing newline.
+
+ $iter = $instance->{comparison_buffer}->get_end_iter();
+ $instance->{comparison_buffer}->delete
+ ($iter, $instance->{comparison_buffer}->get_end_iter())
+ if ($iter->backward_char());
+
+ # Populate the file combobox.
+
+ $instance->{appbar}->set_progress_percentage(0);
+ $instance->{appbar}->set_status("Populating file list");
+ gtk2_update();
+ @files = sort({ $a->{file_name} cmp $b->{file_name} } @files);
+ $i = 1;
+ $instance->{file_combo}->get_model()->clear();
+ foreach my $file (@files)
+ {
+ $instance->{file_combo}->get_model()->set
+ ($instance->{file_combo}->get_model()->append(),
+ CLS_NAME_COLUMN, $file->{file_name},
+ CLS_LINE_NR_COLUMN, $file->{line_nr});
+ $instance->{appbar}->set_progress_percentage($i ++ / scalar(@files));
+ gtk2_update();
+ }
+ $instance->{appbar}->set_progress_percentage(0);
+ $instance->{appbar}->set_status("");
+ gtk2_update();
+
+ # Make sure we are at the top.
+
+ $instance->{comparison_buffer}->
+ place_cursor($instance->{comparison_buffer}->get_start_iter());
+ $instance->{comparison_scrolledwindow}->get_vadjustment()->set_value(0);
+ $instance->{comparison_scrolledwindow}->get_hadjustment()->set_value(0);
+
+ $instance->{appbar}->pop();
+ make_busy($instance, 0);
+
+}
+#
+##############################################################################
+#
# Routine - file_comparison_combobox_changed_cb
#
# Description - Callback routine called when the user changes the value of
@@ -756,8 +1028,7 @@ sub get_history_window()
{
$instance = {};
$instance->{type} = $window_type;
- $instance->{glade} =
- Gtk2::GladeXML->new("../mtn-browse.glade", $window_type);
+ $instance->{glade} = Gtk2::GladeXML->new($glade_file, $window_type);
# Flag to stop recursive calling of callbacks.
@@ -770,7 +1041,6 @@ sub get_history_window()
# Get the widgets that we are interested in.
$instance->{window} = $instance->{glade}->get_widget($window_type);
- $instance->{window}->set_icon($app_icon);
$instance->{appbar} = $instance->{glade}->get_widget("appbar");
$instance->{history_label} =
$instance->{glade}->get_widget("history_label");
@@ -799,6 +1069,7 @@ sub get_history_window()
local $instance->{in_cb} = 1;
$widget->hide();
$instance->{history_buffer}->set_text("");
+ $instance->{mtn} = undef;
return TRUE;
},
$instance);
@@ -982,8 +1253,7 @@ sub get_revision_comparison_window()
{
$instance = {};
$instance->{type} = $window_type;
- $instance->{glade} =
- Gtk2::GladeXML->new("../mtn-browse.glade", $window_type);
+ $instance->{glade} = Gtk2::GladeXML->new($glade_file, $window_type);
# Flag to stop recursive calling of callbacks.
@@ -1005,7 +1275,6 @@ sub get_revision_comparison_window()
# Get the widgets that we are interested in.
$instance->{window} = $instance->{glade}->get_widget($window_type);
- $instance->{window}->set_icon($app_icon);
$instance->{appbar} = $instance->{glade}->get_widget("appbar");
$instance->{comparison_label} =
$instance->{glade}->get_widget("comparison_label");
@@ -1031,6 +1300,7 @@ sub get_revision_comparison_window()
$widget->hide();
$instance->{file_combo}->get_model()->clear();
$instance->{comparison_buffer}->set_text("");
+ $instance->{mtn} = undef;
return TRUE;
},
$instance);
@@ -1087,272 +1357,6 @@ sub get_revision_comparison_window()
#
##############################################################################
#
-# Routine - compare_revisions
-#
-# Description - Compares and then displays the differeneces between the two
-# specified revisions, optionally restricting it to the
-# specified file.
-#
-# Data - $mtn : The Monotone instance handle that is to be
-# used to do the comparison.
-# $revision_id_1 : The first revision id that is to be
-# compared.
-# $revision_id_2 : The second revision id that is to be
-# compared.
-# $file_name : Either the name of the file that the
-# revision comparison should be restricted
-# to or undef for a full revision
-# comparison.
-#
-##############################################################################
-
-
-
-sub compare_revisions($$$;$)
-{
-
- my($mtn, $revision_id_1, $revision_id_2, $file_name) = @_;
-
- my($char,
- @files,
- $i,
- $instance,
- $is_binary,
- $iter,
- $len,
- $line,
- @lines,
- $max_len,
- $name,
- $padding,
- $rest);
-
- $instance = get_revision_comparison_window();
- local $instance->{in_cb} = 1;
-
- $instance->{window}->set_title("Differences Between Revisions "
- . $revision_id_1
- . " And "
- . $revision_id_2);
- if (defined($file_name))
- {
- $instance->{comparison_label}->set_markup("File Comparison");
- }
- else
- {
- $instance->{comparison_label}->
- set_markup("Revision Comparison");
- }
- $instance->{window}->show_all();
-
- make_busy($instance, 1);
- $instance->{appbar}->push("");
- gtk2_update();
-
- $instance->{mtn} = $mtn;
- $instance->{red_revision_id} = $revision_id_1;
- $instance->{green_revision_id} = $revision_id_2;
-
- # Get Monotone to do the comparison.
-
- $instance->{appbar}->set_status("Calculating differences");
- gtk2_update();
- mtn_diff(address@hidden,
- $mtn->get_db_name(),
- $revision_id_1,
- $revision_id_2,
- $file_name);
-
- # Find the longest line for future padding.
-
- $max_len = 0;
- foreach my $line (@lines)
- {
- ($char, $rest) = unpack("a1a*", $line);
- $rest =~ s/\s+$//o;
- $rest = expand($rest);
- $max_len = $len if (($len = length($rest)) > $max_len);
- $line = $char . $rest;
- }
-
- # Display the result, highlighting according to the diff output. Remember
- # the first two lines are just empty comment lines.
-
- $instance->{appbar}->set_status("Formatting and displaying differences");
- gtk2_update();
- $padding = " " x $max_len;
- $line = substr(" Summary" . $padding, 0, $max_len);
- $instance->{comparison_buffer}->insert_with_tags_by_name
- ($instance->{comparison_buffer}->get_end_iter(),
- $line . "\n",
- "compare-info");
- for ($i = 1; $i <= $#lines; ++ $i)
- {
-
- # Deal with the initial comment lines that summarise the entire set of
- # differences between the revisions.
-
- if ($lines[$i] =~ m/^\#/o)
- {
- $line = substr($lines[$i], 1);
- $instance->{comparison_buffer}->insert
- ($instance->{comparison_buffer}->get_end_iter(),
- $line . "\n");
- }
-
- # Deal with lines that introduces a new file comparison.
-
- elsif ($lines[$i] =~ m/^==/o)
- {
-
- # Print separator.
-
- $instance->{comparison_buffer}->
- insert_pixbuf($instance->{comparison_buffer}->get_end_iter(),
- $line_image);
- $instance->{comparison_buffer}->
- insert($instance->{comparison_buffer}->get_end_iter(),
- "\n");
-
- # Extract the file name, if this doesn't work then it is probably a
- # comment stating that the file is binary.
-
- ++ $i;
- ($name) = ($lines[$i] =~ m/^--- (.+)\s+[0-9a-f]{40}$/o);
- if (defined($name))
- {
- $is_binary = 0;
- }
- else
- {
- ($name) = ($lines[$i] =~ m/^\# (.+) is binary$/o);
- $is_binary = 1;
- }
-
- # Print out the details for the first file.
-
- $line = substr(substr($lines[$i], $is_binary ? 1 : 3) . $padding,
- 0,
- $max_len);
- $instance->{comparison_buffer}->insert_with_tags_by_name
- ($instance->{comparison_buffer}->get_end_iter(),
- $line . "\n",
- "compare-first-file-info");
-
- # Store the file name and the starting line number so that the user
- # can later jump straight to it using the file combobox.
-
- $iter = $instance->{comparison_buffer}->get_end_iter();
- $iter->backward_line();
- $instance->{comparison_buffer}->create_mark($name, $iter, FALSE);
- push(@files, {file_name => $name, line_nr => $iter->get_line()});
-
- # Print out the details for the second file if there is one.
-
- if (! $is_binary)
- {
- ++ $i;
- $line = substr(substr($lines[$i], 3) . $padding, 0, $max_len);
- $instance->{comparison_buffer}->insert_with_tags_by_name
- ($instance->{comparison_buffer}->get_end_iter(),
- $line . "\n",
- "compare-second-file-info");
- }
-
- }
-
- # Deal with difference context lines.
-
- elsif ($lines[$i] =~ m/^@@/o)
- {
- $line = substr(substr($lines[$i], 2) . $padding, 0, $max_len);
- $instance->{comparison_buffer}->insert_with_tags_by_name
- ($instance->{comparison_buffer}->get_end_iter(),
- $line . "\n",
- "compare-info");
- }
-
- # Deal with - change lines.
-
- elsif ($lines[$i] =~ m/^-/o)
- {
- $line = substr(substr($lines[$i], 1) . $padding, 0, $max_len);
- $instance->{comparison_buffer}->insert_with_tags_by_name
- ($instance->{comparison_buffer}->get_end_iter(),
- $line . "\n",
- "compare-first-file");
- }
-
- # Deal with + change lines.
-
- elsif ($lines[$i] =~ m/^\+/o)
- {
- $line = substr(substr($lines[$i], 1) . $padding, 0, $max_len);
- $instance->{comparison_buffer}->insert_with_tags_by_name
- ($instance->{comparison_buffer}->get_end_iter(),
- $line . "\n",
- "compare-second-file");
- }
-
- # Print out the rest.
-
- else
- {
- $line = substr($lines[$i], 1);
- $instance->{comparison_buffer}->insert
- ($instance->{comparison_buffer}->get_end_iter(),
- $line . "\n");
- }
-
- if (($i % 100) == 0)
- {
- $instance->{appbar}->set_progress_percentage
- (($i + 1) / scalar(@lines));
- gtk2_update();
- }
-
- }
-
- # Delete the trailing newline.
-
- $iter = $instance->{comparison_buffer}->get_end_iter();
- $instance->{comparison_buffer}->delete
- ($iter, $instance->{comparison_buffer}->get_end_iter())
- if ($iter->backward_char());
-
- # Populate the file combobox.
-
- $instance->{appbar}->set_progress_percentage(0);
- $instance->{appbar}->set_status("Populating file list");
- gtk2_update();
- @files = sort({ $a->{file_name} cmp $b->{file_name} } @files);
- $i = 1;
- $instance->{file_combo}->get_model()->clear();
- foreach my $file (@files)
- {
- $instance->{file_combo}->get_model()->set
- ($instance->{file_combo}->get_model()->append(),
- CLS_NAME_COLUMN, $file->{file_name},
- CLS_LINE_NR_COLUMN, $file->{line_nr});
- $instance->{appbar}->set_progress_percentage($i ++ / scalar(@files));
- gtk2_update();
- }
- $instance->{appbar}->set_progress_percentage(0);
- $instance->{appbar}->set_status("");
- gtk2_update();
-
- # Make sure we are at the top.
-
- $instance->{comparison_scrolledwindow}->get_vadjustment()->set_value(0);
- $instance->{comparison_scrolledwindow}->get_hadjustment()->set_value(0);
-
- $instance->{appbar}->pop();
- make_busy($instance, 0);
-
-}
-#
-##############################################################################
-#
# Routine - mtn_diff
#
# Description - Compare two the specified two revisions, optionally
============================================================
--- Utilities.pm ed70fcf9cb4926124ffacfaaf44c0496b7556ff8
+++ Utilities.pm bd2f0818e5f09a128c1ca297bb6612181d50ea1e
@@ -50,6 +50,7 @@ sub generate_revision_report($$$$;$);
sub create_format_tags($);
sub generate_revision_report($$$$;$);
+sub generate_tmp_path($);
sub get_dir_contents($$$);
sub get_revision_ids($$);
sub glade_signal_autoconnect($$);
@@ -261,6 +262,53 @@ sub generate_revision_report($$$$;$)
#
##############################################################################
#
+# Routine - generate_tmp_path
+#
+# Description - Generate a unique and temporary path for the specified file
+# name. The file name is included in the result and will be
+# unchanged.
+#
+# Data - $file_name : The file name component that is to be used.
+# Return Value : The full, unique, temporary path on success,
+# otherwise undef on failure.
+#
+##############################################################################
+
+
+
+sub generate_tmp_path($)
+{
+
+ my $file_name = $_[0];
+
+ my($path,
+ $i);
+
+ # Loop through looking for a temporary subdirectory not containing the
+ # specified file.
+
+ for ($i = 0; ; ++ $i)
+ {
+ if (-d ($tmp_dir . "/" . $i))
+ {
+ if (! -e ($path = $tmp_dir . "/" . $i . "/" . $file_name))
+ {
+ return $path;
+ }
+ }
+ else
+ {
+ return unless mkdir($tmp_dir . "/" . $i);
+ return $tmp_dir . "/" . $i . "/" . $file_name;
+ }
+ }
+
+ return;
+
+}
+#
+##############################################################################
+#
# Routine - run_command
#
# Description - Run the specified command and return its output.
@@ -485,7 +533,7 @@ sub get_revision_ids($$)
my($instance, $revision_ids) = @_;
@$revision_ids=();
- return unless ($instance->{revision_combo_details}->{completed});
+ return unless ($instance->{revision_combo_details}->{complete});
if ($instance->{tagged_tick}->get_active())
{
$instance->{mtn}->
============================================================
--- mtn-browse 26de6cb7a6b55cd1d37820d87d2a2c45b65f6b06
+++ mtn-browse bcf437debb1b500536ecc393c8aaa5521bd62266
@@ -43,7 +43,11 @@ require 5.008;
require 5.008;
-use lib "/home/aecoope/perl";
+BEGIN
+{
+ use constant LIB_PATH => "/home/aecoope/perl";
+}
+use lib LIB_PATH;
use strict;
# ***** REQUIRED PACKAGES *****
@@ -51,20 +55,18 @@ use File::Basename;
# Standard Perl and CPAN modules.
use File::Basename;
+use File::Temp;
use Glib qw(FALSE TRUE);
use Gnome2;
use Gnome2::VFS -init;
use Gtk2 -init;
-set_locale Gtk2;
-init Gtk2;
use Gtk2::GladeXML;
use Gtk2::Helper;
use Gtk2::Pango;
use Gtk2::SourceView;
+use IO::File;
use IPC::Open3;
-use Monotone::AutomateStdio;
-use POSIX qw(:errno_h :sys_wait_h);
-use POSIX qw(strftime);
+use POSIX qw(:errno_h :sys_wait_h strftime);
use Symbol qw(gensym);
use Text::Tabs;
@@ -72,6 +74,10 @@ use Data::Dumper;
use Data::Dumper;
+# Monotone AutomateStdio module.
+
+use Monotone::AutomateStdio;
+
# Modules specific to this application.
use Globals qw(:constants :variables);
@@ -104,19 +110,28 @@ sub annotate_button_clicked_cb($$);
sub advanced_find_button_clicked_cb($$);
sub annotate_button_clicked_cb($$);
+sub close_toolbutton_clicked_cb($$);
sub directory_up_button_clicked_cb($$);
sub file_change_history_button_clicked_cb($$);
sub get_browser_window(;$$$$$);
+sub help_toolbutton_clicked_cb($$);
sub main_window_delete_event_cb($$$);
sub manifest_browser_treeview_cursor_changed_cb($$);
sub manifest_browser_treeview_row_activated_cb($$$$);
+sub monotone_viz_button_clicked_cb($$);
sub mtn_error_handler($$);
+sub new_toolbutton_clicked_cb($$);
+sub open_toolbutton_clicked_cb($$);
+sub preferences_toolbutton_clicked_cb($$);
+sub properties_toolbutton_clicked_cb($$);
sub revision_change_history_button_clicked_cb($$);
sub revision_change_log_button_clicked_cb($$);
+sub save_as_button_clicked_cb($$);
sub search_text_button_clicked_cb($$);
sub setup_sigchld_handler($);
sub sigchld_handler();
sub update_browser_state($$);
+sub view_button_clicked_cb($$);
#
##############################################################################
#
@@ -133,19 +148,80 @@ sub update_browser_state($$);
{
- # Initialise the libraries and generate the interface.
+ my($branch,
+ $browser,
+ $mtn,
+ $revision_id);
+ # Initialise stuff.
+
+ set_locale Gtk2;
Gnome2::Program->init("mtn-browse", 0.1);
+ setup_sigchld_handler(\&sigchld_handler);
+ $glade_file = LIB_PATH . "/UI/mtn-browse.glade";
+ $tooltips = Gtk2::Tooltips->new();
+ $line_image = Gtk2::Gdk::Pixbuf->new_from_file(LIB_PATH . "/UI/line.png");
+
+ # Create the temporary working directory.
+
+ eval
+ {
+ $tmp_dir = File::Temp::tempdir("mtn-browse_XXXXXXXXXX",
+ TMPDIR => 1,
+ CLEANUP => 1);
+ };
+ if ($@ ne "")
+ {
+ my $dialog = Gtk2::MessageDialog->new
+ (undef,
+ ["modal"],
+ "error",
+ "close",
+ sprintf("%s\nThis is fatal, I am going to exit.", $@));
+ $dialog->run();
+ $dialog->destroy();
+ exit(1);
+ }
+
+ # Attempt to create an mtn handle, if it fails then assume that we are not
+ # inside a workspace. However if it does work then pre-load the browser
+ # with the relevant branch and revision.
+
+ eval
+ {
+ $mtn = Monotone::AutomateStdio->new();
+ $mtn->get_option(\$branch, "branch");
+ $mtn->get_base_revision_id(\$revision_id);
+ };
+
+ # Set up the error handlers for the Monotone library.
+
Monotone::AutomateStdio->register_error_handler("both",
\&mtn_error_handler);
- setup_sigchld_handler(\&sigchld_handler);
- $tooltips = Gtk2::Tooltips->new();
- $app_icon = Gtk2::Gdk::Pixbuf->new_from_file("../mtn-browse.png");
- $line_image = Gtk2::Gdk::Pixbuf->new_from_file("../line.png");
- get_browser_window(Monotone::AutomateStdio->new());
- # get_browser_window();
- # get_browser_window();
+ # Create the browser window and display it. Please note that updating the
+ # browser to reflect the current workspace is done in an idle handler so
+ # that control can be handed over to Gtk2 before updating the display.
+
+ $browser = get_browser_window($mtn);
+ if (defined($mtn))
+ {
+ Glib::Idle->add
+ (sub {
+ my $browser = $_[0];
+
+ $browser->{branch_combo_details}->{preset} = 1;
+ $browser->{branch_combo_details}->{value} = $branch;
+ $browser->{revision_combo_details}->{preset} = 1;
+ $browser->{revision_combo_details}->{value} = $revision_id;
+ $browser->{tagged_tick}->set_active(FALSE);
+ &{$browser->{update_handler}}($browser, ALL_CHANGED);
+
+ return FALSE;
+ },
+ $browser);
+ }
+
# Hand control over to Gtk2.
Gtk2->main();
@@ -166,6 +242,277 @@ sub update_browser_state($$);
#
##############################################################################
#
+# Routine - new_toolbutton_clicked_cb
+#
+# Description - Callback routine called when the user clicks on the
+# new toolbutton in a main browser window.
+#
+# Data - $widget : The widget object that received the signal.
+# $browser : The browser instance that is associated with
+# this widget.
+#
+##############################################################################
+
+
+
+sub new_toolbutton_clicked_cb($$)
+{
+
+ my($widget, $browser) = @_;
+
+ return if ($browser->{in_cb});
+ local $browser->{in_cb} = 1;
+
+ # Simply get a new/unused browser window and display it.
+
+ get_browser_window();
+
+}
+#
+##############################################################################
+#
+# Routine - open_toolbutton_clicked_cb
+#
+# Description - Callback routine called when the user clicks on the
+# open toolbutton in a main browser window.
+#
+# Data - $widget : The widget object that received the signal.
+# $browser : The browser instance that is associated with
+# this widget.
+#
+##############################################################################
+
+
+
+sub open_toolbutton_clicked_cb($$)
+{
+
+ my($widget, $browser) = @_;
+
+ return if ($browser->{in_cb});
+ local $browser->{in_cb} = 1;
+
+ my($chooser_dialog,
+ $done);
+
+ $chooser_dialog = Gtk2::FileChooserDialog->new("Open Database",
+ $browser->{window},
+ "open",
+ "gtk-cancel" => "cancel",
+ "gtk-open" => "ok");
+
+ do
+ {
+ if ($chooser_dialog->run() eq "ok")
+ {
+
+ my ($err,
+ $fh,
+ $file_name,
+ $mtn);
+
+ $file_name = $chooser_dialog->get_filename();
+
+ # The user has selected a file. First make sure we can open it for
+ # reading (I know I could use the -r test but this takes care of
+ # any other unforeseen access problems as well).
+
+ if (! defined($fh = IO::File->new($file_name, "r")))
+ {
+ my $dialog = Gtk2::MessageDialog->new
+ ($browser->{window},
+ ["modal"],
+ "warning",
+ "close",
+ $!);
+ $dialog->run();
+ $dialog->destroy();
+ }
+ else
+ {
+
+ $fh->close();
+ $fh = undef;
+
+ # Ok it is a readable file, try and open it but deal with any
+ # errors in a nicer way than normal.
+
+ Monotone::AutomateStdio->register_error_handler("both");
+ eval
+ {
+ $mtn = Monotone::AutomateStdio->new($file_name);
+ };
+ $err = $@;
+ Monotone::AutomateStdio->register_error_handler
+ ("both", \&mtn_error_handler);
+ if ($err ne "")
+ {
+ my $dialog = Gtk2::MessageDialog->new
+ ($browser->{window},
+ ["modal"],
+ "warning",
+ "close",
+ "Not a valid Monotone database");
+ $dialog->run();
+ $dialog->destroy();
+ }
+ else
+ {
+
+ # Seems to be ok so update the browser with the new
+ # database.
+
+ $browser->{mtn} = $mtn;
+ &{$browser->{update_handler}}($browser, DATABASE_CHANGED);
+ $done = 1;
+
+ }
+
+ }
+
+ }
+ else
+ {
+ $done = 1;
+ }
+ }
+ while (! $done);
+
+ $chooser_dialog->destroy();
+
+}
+#
+##############################################################################
+#
+# Routine - close_toolbutton_clicked_cb
+#
+# Description - Callback routine called when the user clicks on the
+# close toolbutton in a main browser window.
+#
+# Data - $widget : The widget object that received the signal.
+# $browser : The browser instance that is associated with
+# this widget.
+#
+##############################################################################
+
+
+
+sub close_toolbutton_clicked_cb($$)
+{
+
+ my($widget, $browser) = @_;
+
+ return if ($browser->{in_cb});
+ local $browser->{in_cb} = 1;
+
+ # Simply reset the browser's Monotone instance and update its display.
+
+ $browser->{mtn} = undef;
+ &{$browser->{update_handler}}($browser, DATABASE_CHANGED);
+
+}
+#
+##############################################################################
+#
+# Routine - properties_toolbutton_clicked_cb
+#
+# Description - Callback routine called when the user clicks on the
+# properties toolbutton in a main browser window.
+#
+# Data - $widget : The widget object that received the signal.
+# $browser : The browser instance that is associated with
+# this widget.
+#
+##############################################################################
+
+
+
+sub properties_toolbutton_clicked_cb($$)
+{
+
+ my($widget, $browser) = @_;
+
+ return if ($browser->{in_cb});
+ local $browser->{in_cb} = 1;
+
+ my $dialog = Gtk2::MessageDialog->new($browser->{window},
+ ["modal"],
+ "info",
+ "close",
+ "Not implemented");
+ $dialog->run();
+ $dialog->destroy();
+
+}
+#
+##############################################################################
+#
+# Routine - preferences_toolbutton_clicked_cb
+#
+# Description - Callback routine called when the user clicks on the
+# preferences toolbutton in a main browser window.
+#
+# Data - $widget : The widget object that received the signal.
+# $browser : The browser instance that is associated with
+# this widget.
+#
+##############################################################################
+
+
+
+sub preferences_toolbutton_clicked_cb($$)
+{
+
+ my($widget, $browser) = @_;
+
+ return if ($browser->{in_cb});
+ local $browser->{in_cb} = 1;
+
+ my $dialog = Gtk2::MessageDialog->new($browser->{window},
+ ["modal"],
+ "info",
+ "close",
+ "Not implemented");
+ $dialog->run();
+ $dialog->destroy();
+
+}
+#
+##############################################################################
+#
+# Routine - help_toolbutton_clicked_cb
+#
+# Description - Callback routine called when the user clicks on the
+# help toolbutton in a main browser window.
+#
+# Data - $widget : The widget object that received the signal.
+# $browser : The browser instance that is associated with
+# this widget.
+#
+##############################################################################
+
+
+
+sub help_toolbutton_clicked_cb($$)
+{
+
+ my($widget, $browser) = @_;
+
+ return if ($browser->{in_cb});
+ local $browser->{in_cb} = 1;
+
+ my $dialog = Gtk2::MessageDialog->new($browser->{window},
+ ["modal"],
+ "info",
+ "close",
+ "Not implemented");
+ $dialog->run();
+ $dialog->destroy();
+
+}
+#
+##############################################################################
+#
# Routine - tagged_checkbutton_toggled_cb
#
# Description - Callback routine called when the user changes the value of
@@ -228,7 +575,7 @@ sub advanced_find_button_clicked_cb($$)
$preset_branch = 1;
$state = BRANCH_CHANGED;
- if ($browser->{branch_combo_details}->{completed})
+ if ($browser->{branch_combo_details}->{complete})
{
foreach my $name (@branches)
{
@@ -329,6 +676,56 @@ sub revision_change_log_button_clicked_c
#
##############################################################################
#
+# Routine - monotone_viz_button_clicked_cb
+#
+# Description - Callback routine called when the user clicks on the
+# monotone-viz button in a main browser window.
+#
+# Data - $widget : The widget object that received the signal.
+# $browser : The browser instance that is associated with
+# this widget.
+#
+##############################################################################
+
+
+
+sub monotone_viz_button_clicked_cb($$)
+{
+
+ my($widget, $browser) = @_;
+
+ return if ($browser->{in_cb});
+ local $browser->{in_cb} = 1;
+
+ my($cmd,
+ $db_name);
+
+ # Build up the monotone-viz command, we need the database name and then
+ # optionally the branch and revision ids.
+
+ $cmd = "monotone-viz ";
+ if (! defined($db_name = $browser->{mtn}->get_db_name()))
+ {
+ $browser->{mtn}->get_option(\$db_name, "database");
+ }
+ $cmd .= $db_name;
+ if ($browser->{branch_combo_details}->{complete})
+ {
+ $cmd .= " " . $browser->{branch_combo_details}->{value};
+ if ($browser->{revision_combo_details}->{complete})
+ {
+ $cmd .= " " . $browser->{revision_combo_details}->{value};
+ }
+ }
+
+ # Launch Monotone-Viz.
+
+ system($cmd . " &");
+
+}
+#
+##############################################################################
+#
# Routine - directory_up_button_clicked_cb
#
# Description - Callback routine called when the user clicks on the up
@@ -364,7 +761,7 @@ sub directory_up_button_clicked_cb($$)
$value = dirname($value);
$value = "" if ($value eq ".");
$browser->{directory_combo_details}->{value} = $value;
- $browser->{directory_combo_details}->{completed} = 1;
+ $browser->{directory_combo_details}->{complete} = 1;
$len = length($value);
if ($len < $old_len)
{
@@ -411,6 +808,189 @@ sub search_text_button_clicked_cb($$)
#
##############################################################################
#
+# Routine - save_as_button_clicked_cb
+#
+# Description - Callback routine called when the user clicks on the save as
+# button in a main browser window.
+#
+# Data - $widget : The widget object that received the signal.
+# $browser : The browser instance that is associated with
+# this widget.
+#
+##############################################################################
+
+
+
+sub save_as_button_clicked_cb($$)
+{
+
+ my($widget, $browser) = @_;
+
+ return if ($browser->{in_cb});
+ local $browser->{in_cb} = 1;
+
+ my($chooser_dialog,
+ $continue,
+ $done);
+
+ $chooser_dialog = Gtk2::FileChooserDialog->new("Save As",
+ $browser->{window},
+ "save",
+ "gtk-cancel" => "cancel",
+ "gtk-save" => "ok");
+ $chooser_dialog->set_current_name
+ ($browser->{file_being_viewed}->{short_name});
+
+ do
+ {
+ if ($chooser_dialog->run() eq "ok")
+ {
+
+ my ($data,
+ $fh,
+ $file_name);
+
+ $continue = 1;
+ $file_name = $chooser_dialog->get_filename();
+
+ # See if the file exists, if so then get a confirmation from the
+ # user.
+
+ if (-e $file_name)
+ {
+ my $dialog = Gtk2::MessageDialog->new
+ ($browser->{window},
+ ["modal"],
+ "question",
+ "yes-no",
+ "File already exists.\nDo you want to replace it?");
+ $dialog->set_title("Confirm");
+ $continue = 0 if ($dialog->run() ne "yes");
+ $dialog->destroy();
+ }
+
+ if ($continue)
+ {
+
+ # Attempt to save the contents to the file.
+
+ if (! defined($fh = IO::File->new($file_name, "w")))
+ {
+ my $dialog = Gtk2::MessageDialog->new
+ ($browser->{window},
+ ["modal"],
+ "warning",
+ "close",
+ $!);
+ $dialog->run();
+ $dialog->destroy();
+ }
+ else
+ {
+ $browser->{mtn}->get_file(\$data,
+ $browser->{file_being_viewed}->
+ {manifest_entry}->{file_id});
+ $fh->print($data);
+ $fh->close();
+ $done = 1;
+ }
+
+ }
+
+ }
+ else
+ {
+ $done = 1;
+ }
+ }
+ while (! $done);
+
+ $chooser_dialog->destroy();
+
+}
+#
+##############################################################################
+#
+# Routine - view_button_clicked_cb
+#
+# Description - Callback routine called when the user clicks on the view
+# button in a main browser window.
+#
+# Data - $widget : The widget object that received the signal.
+# $browser : The browser instance that is associated with
+# this widget.
+#
+##############################################################################
+
+
+
+sub view_button_clicked_cb($$)
+{
+
+ my($widget, $browser) = @_;
+
+ return if ($browser->{in_cb});
+ local $browser->{in_cb} = 1;
+
+ my($data,
+ $editor,
+ $fh,
+ $file_name);
+
+ if (! ($file_name =
+ generate_tmp_path($browser->{file_being_viewed}->{short_name})))
+ {
+ my $dialog = Gtk2::MessageDialog->new
+ ($browser->{window},
+ ["modal"],
+ "warning",
+ "Cannot generate temporary file name",
+ $!);
+ $dialog->run();
+ $dialog->destroy();
+ return;
+ }
+
+ # Attempt to save the contents to the file.
+
+ if (! defined($fh = IO::File->new($file_name, "w")))
+ {
+ my $dialog = Gtk2::MessageDialog->new
+ ($browser->{window},
+ ["modal"],
+ "warning",
+ "close",
+ $!);
+ $dialog->run();
+ $dialog->destroy();
+ return;
+ }
+ $browser->{mtn}->get_file(\$data,
+ $browser->{file_being_viewed}->
+ {manifest_entry}->{file_id});
+ $fh->print($data);
+ $fh->close();
+ $fh = undef;
+
+ # Load into an editor.
+
+ if (exists($ENV{EDITOR})
+ && ($ENV{EDITOR} eq "emacs"
+ || $ENV{EDITOR} eq "xemacs"
+ || $ENV{EDITOR} eq "gvim"))
+ {
+ $editor = $ENV{EDITOR};
+ }
+ else
+ {
+ $editor = "xterm -e vi";
+ }
+ system($editor . " " . $file_name . " &");
+
+}
+#
+##############################################################################
+#
# Routine - annotate_button_clicked_cb
#
# Description - Callback routine called when the user clicks on the
@@ -569,7 +1149,7 @@ sub manifest_browser_treeview_row_activa
if (defined($manifest_entry) && $manifest_entry->{type} eq "directory")
{
$browser->{directory_combo_details}->{value} = $manifest_entry->{name};
- $browser->{directory_combo_details}->{completed} = 1;
+ $browser->{directory_combo_details}->{complete} = 1;
$browser->{directory_combo}->child()->
set_text($manifest_entry->{name});
$browser->{appbar}->clear_stack();
@@ -697,8 +1277,7 @@ sub get_browser_window(;$$$$$)
$browser = {};
$browser->{type} = $window_type;
$browser->{mtn} = $mtn;
- $browser->{glade} =
- Gtk2::GladeXML->new("../mtn-browse.glade", $window_type);
+ $browser->{glade} = Gtk2::GladeXML->new($glade_file, $window_type);
# Flag to stop recursive calling of callbacks.
@@ -715,9 +1294,12 @@ sub get_browser_window(;$$$$$)
# Get the widgets that we are interested in.
$browser->{window} = $browser->{glade}->get_widget($window_type);
- $browser->{window}->set_icon($app_icon);
$browser->{appbar} = $browser->{glade}->get_widget("appbar");
$browser->{main_vbox} = $browser->{glade}->get_widget("main_vbox");
+ $browser->{close_toolbutton} =
+ $browser->{glade}->get_widget("close_toolbutton");
+ $browser->{properties_toolbutton} =
+ $browser->{glade}->get_widget("properties_toolbutton");
$browser->{branch_combo} =
$browser->{glade}->get_widget("branch_comboboxentry");
$browser->{revision_combo} =
@@ -942,6 +1524,12 @@ sub get_browser_window(;$$$$$)
&{$browser->{update_handler}}($browser, ALL_CHANGED);
}
+ # Make sure that the branch comboboxentry has the focus and not the bonobo
+ # dock.
+
+ $browser->{branch_combo}->child()->grab_focus();
+ $browser->{branch_combo}->child()->set_position(-1);
+
return $browser;
}
@@ -974,10 +1562,14 @@ sub update_browser_state($$)
if (! defined($browser->{mtn}))
{
+ $browser->{close_toolbutton}->set_sensitive(FALSE);
+ $browser->{properties_toolbutton}->set_sensitive(FALSE);
$browser->{main_vbox}->set_sensitive(FALSE);
}
else
{
+ $browser->{close_toolbutton}->set_sensitive(TRUE);
+ $browser->{properties_toolbutton}->set_sensitive(TRUE);
$browser->{main_vbox}->set_sensitive(TRUE);
}
@@ -993,12 +1585,12 @@ sub update_browser_state($$)
$browser->{branch_combo_details}->{completion} = undef;
if ($browser->{branch_combo_details}->{preset})
{
- $browser->{branch_combo_details}->{completed} = 1;
+ $browser->{branch_combo_details}->{complete} = 1;
$browser->{branch_combo_details}->{preset} = 0;
}
else
{
- $browser->{branch_combo_details}->{completed} = 0;
+ $browser->{branch_combo_details}->{complete} = 0;
$browser->{branch_combo_details}->{value} = "";
}
if (! defined($browser->{mtn}))
@@ -1055,18 +1647,18 @@ sub update_browser_state($$)
$browser->{revision_combo_details}->{completion} = undef;
if ($browser->{revision_combo_details}->{preset})
{
- $browser->{revision_combo_details}->{completed} = 1;
+ $browser->{revision_combo_details}->{complete} = 1;
$browser->{revision_combo_details}->{preset} = 0;
}
else
{
- $browser->{revision_combo_details}->{completed} = 0;
+ $browser->{revision_combo_details}->{complete} = 0;
$browser->{revision_combo_details}->{value} = "";
}
# Get the new list of revisions.
- if ($browser->{branch_combo_details}->{completed})
+ if ($browser->{branch_combo_details}->{complete})
{
$browser->{appbar}->set_status("Fetching revision list");
gtk2_update();
@@ -1144,12 +1736,12 @@ sub update_browser_state($$)
$browser->{directory_combo_details}->{completion} = undef;
if ($browser->{directory_combo_details}->{preset})
{
- $browser->{directory_combo_details}->{completed} = 1;
+ $browser->{directory_combo_details}->{complete} = 1;
$browser->{revision_combo_details}->{preset} = 0;
}
else
{
- $browser->{directory_combo_details}->{completed} = 0;
+ $browser->{directory_combo_details}->{complete} = 0;
$browser->{directory_combo_details}->{value} = "";
}
set_label_value($browser->{revision_id_label}, "");
@@ -1164,7 +1756,7 @@ sub update_browser_state($$)
$browser->{appbar}->set_status("Fetching manifest");
gtk2_update();
- if ($browser->{revision_combo_details}->{completed})
+ if ($browser->{revision_combo_details}->{complete})
{
my @revision_ids;
get_revision_ids($browser, address@hidden);
@@ -1186,7 +1778,7 @@ sub update_browser_state($$)
($browser->{window}, ["modal"], "info", "close", $message);
$dialog->run();
$dialog->destroy();
- $browser->{revision_combo_details}->{completed} = 0;
+ $browser->{revision_combo_details}->{complete} = 0;
$browser->{revision_combo_details}->{value} = "";
$browser->{revision_combo}->child()->set_text("");
}
@@ -1251,7 +1843,7 @@ sub update_browser_state($$)
foreach my $widget (@{$browser->{revision_sensitive_group}})
{
$widget->
- set_sensitive($browser->{revision_combo_details}->{completed});
+ set_sensitive($browser->{revision_combo_details}->{complete});
}
gtk2_update();
@@ -1277,7 +1869,7 @@ sub update_browser_state($$)
# Get the contents of the new directory.
- if ($browser->{directory_combo_details}->{completed}
+ if ($browser->{directory_combo_details}->{complete}
|| $browser->{directory_combo_details}->{value} eq "")
{
get_dir_contents($browser->{directory_combo_details}->{value},
@@ -1721,7 +2313,7 @@ sub sigchld_handler()
foreach my $window (@windows)
{
- if (exists($window->{mtn})
+ if (exists($window->{mtn}) && defined($window->{mtn})
&& $window->{mtn}->get_pid() == $pid)
{
$window->{mtn}->closedown();
============================================================
--- mtn-browse.glade 56a671155946b9d7d2878ecdc2e1fdf3e5cddb43
+++ mtn-browse.glade b87a22f4310537a066635f9e4aa8554dd053f606
@@ -15,6 +15,7 @@
550
True
False
+ mtn-browse.png
True
False
False
@@ -24,17 +25,17 @@
-
+
True
True
-
+