#
#
# patch "AdvancedFind.pm"
# from [4057f374a82a5720b9654a9a3ab11fa5c8e08d7b]
# to [9ecb0053b5bb0b7e821572fa740b04a014c9dbc8]
#
# patch "Globals.pm"
# from [a24f4acd16f3849fa802bbfdc496d61483b22ac3]
# to [210c3971b3ca55744f8e3ae4c40f42395e326d77]
#
# patch "History.pm"
# from [ee85354b0b069da7197afafbfa22e1307e389ea6]
# to [0a0f559ca522cea54e20bdcbf6eccbaf983bb936]
#
# patch "Preferences.pm"
# from [592b6d26869b985da23d12a7cf365c9aeea1fe9a]
# to [9582cfdd83a9f9ef8af46a0c1fc17a6d460119d4]
#
# patch "Utilities.pm"
# from [458875b2f3623c910d08ea3aa72d8729b4fec91b]
# to [d4930c03d430af5ac4a2d0dcf1cb3d7d5a898c27]
#
# patch "mtn-browse"
# from [e0a9d3e52bf31b902b4b351e04438ec745d22ac6]
# to [88920cff112f114139d36a0ba7cecbc14b305bca]
#
# patch "mtn-browse.glade"
# from [7e503af1903439bbf47468d917f692db3bea8ec4]
# to [e108526a6ed91bc84238ac6586567a7c53b196ea]
#
============================================================
--- AdvancedFind.pm 4057f374a82a5720b9654a9a3ab11fa5c8e08d7b
+++ AdvancedFind.pm 9ecb0053b5bb0b7e821572fa740b04a014c9dbc8
@@ -791,45 +791,13 @@ sub update_advanced_find_state($$)
{
$advanced_find->{appbar}->set_status("Fetching revision list");
gtk2_update();
-
- # Get either a list of tags or revision ids depending upon what the
- # user has chosen.
-
- if ($advanced_find->{tagged_checkbutton}->get_active())
- {
- my(%dup_list,
- @list);
- $advanced_find->{mtn}->
- tags(address@hidden,
- $advanced_find->{branch_combo_details}->{value});
- $advanced_find->{appbar}->set_progress_percentage(0.5);
- gtk2_update();
- foreach my $item (@list)
- {
- if (! exists($dup_list{$item->{tag}}))
- {
- push(@revision_list, $item->{tag});
- $dup_list{$item->{tag}} = 1;
- }
- }
- }
- else
- {
- $advanced_find->{mtn}->
- select(address@hidden,
- "b:" . $advanced_find->{branch_combo_details}->
- {value});
- $advanced_find->{appbar}->set_progress_percentage(0.33);
- gtk2_update();
- $advanced_find->{mtn}->toposort(address@hidden,
- @revision_list);
- $advanced_find->{appbar}->set_progress_percentage(0.66);
- gtk2_update();
- splice(@revision_list, 0, scalar(@revision_list) - 100);
- @revision_list = reverse(@revision_list);
- }
- $advanced_find->{appbar}->set_progress_percentage(1);
- gtk2_update();
+ get_branch_revisions($advanced_find->{mtn},
+ $advanced_find->{branch_combo_details}->
+ {value},
+ $advanced_find->{tagged_checkbutton}->
+ get_active(),
+ $advanced_find->{appbar},
+ address@hidden);
}
$advanced_find->{revision_combo_details}->{list} = address@hidden;
============================================================
--- Globals.pm a24f4acd16f3849fa802bbfdc496d61483b22ac3
+++ Globals.pm 210c3971b3ca55744f8e3ae4c40f42395e326d77
@@ -96,55 +96,13 @@ our $tmp_dir;
our $tmp_dir;
-# Text viewable application mime types.
+# The user's preferences data.
-our @text_viewable_app_mime_types =
- qw(postscript
- rtf
- x-awk
- x-cgi
- x-csh
- x-glade
- x-java
- x-javascript
- x-jbuilder-project
- x-perl
- x-php
- x-python
- x-shellscript
- x-troff-man
- x-troff
- xhtml+xml);
+our $user_preferences;
-# Supported text mime types (used for syntax highlighting).
+# The MIME type file name pattern match table.
-our @text_mime_types =
- (
- {
- pattern => qr/.*\.c$/o,
- type => "text/x-csrc"
- },
- {
- pattern => qr/.*\.(C)|(cc)|(cp)|(cpp)|(CPP)|(cxx)|(c\+\+)$/o,
- type => "text/x-c++src"
- },
- {
- pattern => qr/.*\.(h)|(hh)|(H)$/o,
- type => "text/x-c++hdr"
- },
- {
- pattern => qr/.*\.h$/o,
- type => "text/x-chdr"
- },
- {
- pattern => qr/(^[Mm]akefile(\.[^.]+)?)|(.*\.mk)$/o,
- type => "text/x-makefile"
- },
- {
- pattern => qr/.*/o,
- type => "text/plain"
- }
- );
+our $mime_match_table;
# ***** PACKAGE INFORMATION *****
@@ -167,11 +125,11 @@ our %EXPORT_TAGS = (constants => [qw(ALL
SELECTED_REVISION_CHANGED)],
variables => [qw($glade_file
$line_image
+ $mime_match_table
$mono_font
- @text_mime_types
- @text_viewable_app_mime_types
$tmp_dir
- $tooltips)]);
+ $tooltips
+ $user_preferences)]);
our @EXPORT = qw();
Exporter::export_ok_tags(qw(constants variables));
our $VERSION = 0.1;
============================================================
--- History.pm ee85354b0b069da7197afafbfa22e1307e389ea6
+++ History.pm 0a0f559ca522cea54e20bdcbf6eccbaf983bb936
@@ -705,8 +705,8 @@ sub compare_revisions($$$;$)
gtk2_update();
$instance->{mtn} = $mtn;
- $instance->{red_revision_id} = $revision_id_1;
- $instance->{green_revision_id} = $revision_id_2;
+ $instance->{revision_id_1} = $revision_id_1;
+ $instance->{revision_id_2} = $revision_id_2;
# Get Monotone to do the comparison.
@@ -792,7 +792,7 @@ sub compare_revisions($$$;$)
$instance->{comparison_buffer}->insert_with_tags_by_name
($instance->{comparison_buffer}->get_end_iter(),
$line . "\n",
- "compare-first-file-info");
+ "compare-file-info-1");
# Store the file name and the starting line number so that the user
# can later jump straight to it using the file combobox.
@@ -811,7 +811,7 @@ sub compare_revisions($$$;$)
$instance->{comparison_buffer}->insert_with_tags_by_name
($instance->{comparison_buffer}->get_end_iter(),
$line . "\n",
- "compare-second-file-info");
+ "compare-file-info-2");
}
}
@@ -835,7 +835,7 @@ sub compare_revisions($$$;$)
$instance->{comparison_buffer}->insert_with_tags_by_name
($instance->{comparison_buffer}->get_end_iter(),
$line . "\n",
- "compare-first-file");
+ "compare-file-1");
}
# Deal with + change lines.
@@ -846,7 +846,7 @@ sub compare_revisions($$$;$)
$instance->{comparison_buffer}->insert_with_tags_by_name
($instance->{comparison_buffer}->get_end_iter(),
$line . "\n",
- "compare-second-file");
+ "compare-file-2");
}
# Print out the rest.
@@ -975,15 +975,15 @@ sub coloured_revision_change_log_button_
# Work out what revision id to use.
- if ($widget == $instance->{red_revision_change_log_button})
+ if ($widget == $instance->{revision_change_log_1_button})
{
- $revision_id = $instance->{red_revision_id};
- $colour = "red";
+ $revision_id = $instance->{revision_id_1};
+ $colour = "compare-1";
}
else
{
- $revision_id = $instance->{green_revision_id};
- $colour = "green";
+ $revision_id = $instance->{revision_id_2};
+ $colour = "compare-2";
}
# Display the full revision change log.
@@ -1240,7 +1240,9 @@ sub get_revision_comparison_window()
"file_comparison_combobox",
"comparison_textview",
"comparison_scrolledwindow",
- "red_revision_change_log_button")
+ "revision_change_log_1_button",
+ "revision_change_log_1_button_label",
+ "revision_change_log_2_button_label")
{
$instance->{$widget} = $instance->{glade}->get_widget($widget);
}
@@ -1281,6 +1283,17 @@ sub get_revision_comparison_window()
create_format_tags($instance->{comparison_buffer});
$instance->{comparison_textview}->modify_font($mono_font);
+ # Setup the revision log button coloured labels.
+
+ $instance->{revision_change_log_1_button_label}->
+ set_markup("Revision Change Log");
+ $instance->{revision_change_log_2_button_label}->
+ set_markup("Revision Change Log");
+
# Register the window for management.
$wm->manage($instance, $window_type, $instance->{stop_button});
============================================================
--- Preferences.pm 592b6d26869b985da23d12a7cf365c9aeea1fe9a
+++ Preferences.pm 9582cfdd83a9f9ef8af46a0c1fc17a6d460119d4
@@ -61,10 +61,31 @@ use constant PREFERENCES_FORMAT_VERSION
use constant PREFERENCES_FORMAT_VERSION => 1;
+# Text viewable application mime types.
+
+my @text_viewable_app_mime_types =
+ qw(postscript
+ rtf
+ x-awk
+ x-cgi
+ x-csh
+ x-glade
+ x-java
+ x-javascript
+ x-jbuilder-project
+ x-perl
+ x-php
+ x-python
+ x-shellscript
+ x-troff-man
+ x-troff
+ xhtml+xml);
+
# ***** FUNCTIONAL PROTOTYPES FOR THIS FILE *****
# Public routines.
+sub build_mime_match_table($);
sub load_preferences();
sub preferences($);
sub save_preferences($);
@@ -93,8 +114,10 @@ sub save_preferences_from_gui($);
# Description - Displays the preferences dialog window and then lets the
# user change the application preferences.
#
-# Data - $browser : The browser instance that called up the
-# preferences dialog window.
+# Data - $browser : The browser instance that called up the
+# preferences dialog window.
+# Return Value : True if the preferences were changed,
+# otherwise false if they were left unaltered.
#
##############################################################################
@@ -171,6 +194,8 @@ sub preferences($)
$instance->{file_name_patterns_liststore}->clear();
$instance->{preferences} = undef;
+ return $instance->{preferences_changed};
+
}
#
##############################################################################
@@ -237,12 +262,12 @@ sub load_preferences()
bg => "SteelBlue"},
annotate_text_2 => {fg => "MidnightBlue",
bg => "SkyBlue"},
- cmp_revision_1 => {fg => "DarkGreen",
+ cmp_revision_1 => {fg => "DarkRed",
+ bg => "MistyRose1",
+ hl => "IndianRed1"},
+ cmp_revision_2 => {fg => "DarkGreen",
bg => "DarkSeaGreen1",
- hl => "SpringGreen1"},
- cmp_revision_2 => {fg => "DarkRed",
- bg => "MistyRose1",
- hl => "IndianRed1"}},
+ hl => "SpringGreen1"}},
mime_table => $mime_table);
}
@@ -293,6 +318,46 @@ sub save_preferences($)
#
##############################################################################
#
+# Routine - build_mime_match_table
+#
+# Description - Build a regular expression pattern matching table for
+# working out the MIME type of a file from its file name.
+#
+# Data - $mime_info_table : A reference to the MIME information
+# table on which the pattern matching
+# table is to be based.
+# Return Value : A reference to the newly created pattern
+# matching table.
+#
+##############################################################################
+
+
+
+sub build_mime_match_table($)
+{
+
+ my $mime_info_table = $_[0];
+
+ my($re_str,
+ @table);
+
+ foreach my $entry (@$mime_info_table)
+ {
+ foreach my $file_glob (@{$entry->{file_name_patterns}})
+ {
+ $re_str = file_glob_to_regexp($file_glob);
+ push(@table,
+ {re => qr/$re_str/,
+ details => $entry});
+ }
+ }
+
+ return address@hidden;
+
+}
+#
+##############################################################################
+#
# Routine - database_browse_button_clicked_cb
#
# Description - Callback routine called when the user clicks on the browse
@@ -315,92 +380,11 @@ sub database_browse_button_clicked_cb($$
return if ($instance->{in_cb});
local $instance->{in_cb} = 1;
- my($chooser_dialog,
- $done);
+ my $file_name;
- $chooser_dialog = Gtk2::FileChooserDialog->new("Open Database",
- $instance->{window},
- "open",
- "gtk-cancel" => "cancel",
- "gtk-open" => "ok");
+ $instance->{database_entry}->set_text($file_name)
+ if (open_database($instance->{window}, undef, \$file_name));
- 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
- ($instance->{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
- ($instance->{window},
- ["modal"],
- "warning",
- "close",
- "Not a valid Monotone database.");
- $dialog->run();
- $dialog->destroy();
- }
- else
- {
-
- # Seems to be ok so update the related entry widget.
-
- $instance->{database_entry}->set_text($file_name);
- $done = 1;
-
- }
-
- }
-
- }
- else
- {
- $done = 1;
- }
- }
- while (! $done);
-
- $chooser_dialog->destroy();
-
}
#
##############################################################################
@@ -607,7 +591,7 @@ sub add_file_name_pattern_button_clicked
foreach my $entry (@{$instance->{preferences}->{mime_table}})
{
- if (scalar(grep(/\Q$pattern\E/, @{$entry->{file_name_patterns}})) > 0)
+ if (grep(/\Q$pattern\E/, @{$entry->{file_name_patterns}}) > 0)
{
$match = $entry->{name};
last;
@@ -755,8 +739,10 @@ sub get_preferences_window($$)
"auto_select_checkbutton",
"tagged_lists_limit_spinbutton",
"tagged_lists_sort_cronologically_radiobutton",
+ "tagged_lists_sort_by_name_radiobutton",
"id_lists_limit_spinbutton",
"id_lists_sort_cronologically_radiobutton",
+ "id_lists_sort_by_id_radiobutton",
# Appearance pane widgets.
@@ -908,7 +894,7 @@ sub get_preferences_window($$)
}
$instance->{done} = 0;
- $instance->{preferences_changed} = 0;
+ $instance->{preferences_changed} = undef;
$instance->{selected_file_name_pattern} = undef;
$instance->{selected_mime_types_entry} = undef;
$instance->{selected_mime_types_path} = undef;
@@ -947,14 +933,26 @@ sub load_preferences_into_gui($)
TRUE : FALSE);
$instance->{tagged_lists_limit_spinbutton}->
set_value($instance->{preferences}->{query}->{tagged}->{limit});
- $instance->{tagged_lists_sort_cronologically_radiobutton}->
- set_active($instance->{preferences}->{query}->{tagged}->
- {sort_cronologically} ? TRUE : FALSE);
+ if ($instance->{preferences}->{query}->{tagged}->{sort_cronologically})
+ {
+ $instance->{tagged_lists_sort_cronologically_radiobutton}->
+ set_active(TRUE);
+ }
+ else
+ {
+ $instance->{tagged_lists_sort_by_name_radiobutton}->set_active(TRUE);
+ }
$instance->{id_lists_limit_spinbutton}->
set_value($instance->{preferences}->{query}->{id}->{limit});
- $instance->{id_lists_sort_cronologically_radiobutton}->
- set_active($instance->{preferences}->{query}->{id}->
- {sort_cronologically} ? TRUE : FALSE);
+ if ($instance->{preferences}->{query}->{id}->{sort_cronologically})
+ {
+ $instance->{id_lists_sort_cronologically_radiobutton}->
+ set_active(TRUE);
+ }
+ else
+ {
+ $instance->{id_lists_sort_by_id_radiobutton}->set_active(TRUE);
+ }
# Do the appearance pane.
@@ -1150,10 +1148,13 @@ sub initialise_mime_info_table()
sub initialise_mime_info_table()
{
- my($pattern,
+ my($display_internally,
+ $pattern,
$globs_file,
$line,
%lookup,
+ $part,
+ $syntax_highlight,
@table,
$type);
@@ -1183,10 +1184,26 @@ sub initialise_mime_info_table()
}
else
{
+ $display_internally = $syntax_highlight = 0;
+ if ($type =~ m/^application\/.+$/o)
+ {
+ ($part) = ($type =~ m/^application\/(.+)$/o);
+ $display_internally = $syntax_highlight = 1
+ if (grep(/\Q$part\E/, @text_viewable_app_mime_types)
+ > 0);
+ }
+ elsif ($type =~ m/^image\/.+$/o)
+ {
+ $display_internally = 1;
+ }
+ elsif ($type =~ m/^text\/.+$/o)
+ {
+ $display_internally = $syntax_highlight = 1;
+ }
$lookup{$type} = {name => $type,
file_name_patterns => [$pattern],
- display_internally => 0,
- syntax_highlight => 0,
+ display_internally => $display_internally,
+ syntax_highlight => $syntax_highlight,
helper_application => ""};
push(@table, $lookup{$type});
}
@@ -1334,6 +1351,8 @@ sub file_glob_to_regexp($)
}
}
+ $re_text .= "\$";
+
return $re_text;
}
============================================================
--- Utilities.pm 458875b2f3623c910d08ea3aa72d8729b4fec91b
+++ Utilities.pm d4930c03d430af5ac4a2d0dcf1cb3d7d5a898c27
@@ -50,12 +50,16 @@ sub create_format_tags($);
sub colour_to_string($);
sub create_format_tags($);
+sub data_is_binary($);
sub generate_revision_report($$$$;$);
sub generate_tmp_path($);
+sub get_branch_revisions($$$$$);
sub get_dir_contents($$$);
sub get_revision_ids($$);
sub glade_signal_autoconnect($$);
sub gtk2_update();
+sub hex_dump($);
+sub open_database($$$);
sub run_command($@);
sub set_label_value($$);
#
@@ -512,97 +516,321 @@ sub get_dir_contents($$$)
#
##############################################################################
#
-# Routine - get_revision_ids
+# Routine - open_database
#
-# Description - Return the currently selected revision id, whether this is
-# specified via a tag or as a revision id.
+# Description - Allows the user to select a Monotone Database and then
+# opens it, making sure that it is a valid database or
+# dealing with the consequences if it isn't.
#
-# Data - $instance : The window instance.
-# $revision_ids : The list of selected revision ids. Normally
-# the list will have at most one element but
-# may contain more if the tag isn't unique on
-# the current branch.
+# Data - $parent : The parent window for any dialogs that are
+# to be displayed.
+# $mtn : A reference to a variable that is to contain
+# the newly created Monotone::AutomateStdio
+# object. This parameter can be undef if the
+# object is not required.
+# $file_name : A reference to a variable that is to contain
+# the full file name of the selected database.
+# This parameter can be undef if the file name
+# is not required.
+# Return Value : True on success, otherwise false on
+# cancellation.
#
##############################################################################
-sub get_revision_ids($$)
+sub open_database($$$)
{
- my($instance, $revision_ids) = @_;
+ my($parent, $mtn, $file_name) = @_;
- @$revision_ids=();
- return unless ($instance->{revision_combo_details}->{complete});
- if ($instance->{tagged_checkbutton}->get_active())
+ my($chooser_dialog,
+ $done,
+ $ret_val);
+
+ $chooser_dialog = Gtk2::FileChooserDialog->new("Open Database",
+ $parent,
+ "open",
+ "gtk-cancel" => "cancel",
+ "gtk-open" => "ok");
+
+ do
{
- $instance->{mtn}->
- select($revision_ids,
- "t:" . $instance->{revision_combo_details}->{value});
+ if ($chooser_dialog->run() eq "ok")
+ {
+
+ my ($err,
+ $fh,
+ $fname,
+ $mtn_obj);
+
+ $fname = $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($fname, "r")))
+ {
+ my $dialog = Gtk2::MessageDialog->new
+ ($parent,
+ ["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_obj = Monotone::AutomateStdio->new($fname);
+ };
+ $err = $@;
+ Monotone::AutomateStdio->register_error_handler
+ ("both", \&mtn_error_handler);
+ if ($err ne "")
+ {
+ my $dialog = Gtk2::MessageDialog->new
+ ($parent,
+ ["modal"],
+ "warning",
+ "close",
+ "Not a valid Monotone database.");
+ $dialog->run();
+ $dialog->destroy();
+ }
+ else
+ {
+
+ # Seems to be ok so tell the caller.
+
+ $$mtn = $mtn_obj if (defined($mtn));
+ $$file_name = $fname if (defined($file_name));
+ $done = $ret_val = 1;
+
+ }
+
+ }
+
+ }
+ else
+ {
+ $done = 1;
+ }
}
- else
- {
- push(@$revision_ids, $instance->{revision_combo_details}->{value});
- }
+ while (! $done);
+ $chooser_dialog->destroy();
+
+ return $ret_val;
+
}
#
##############################################################################
#
-# Routine - glade_signal_autoconnect
+# Routine - get_branch_revisions
#
-# Description - This routine uses the Glade library to connect up all the
-# registered signal handlers to their related widgets.
+# Description - Get a list of revision ids or tags for the specified branch
+# that take into account the user's preferences for ordering
+# and the maximum number of revisions to display.
#
-# Data - $glade : The Glade object describing the widgets that
-# are to have their signal handlers
-# registered.
-# $client_data : The client data that is to be passed into
-# each callback routine when it is called.
+# Data - $mtn : The Monotone database handle that is to be
+# used.
+# $branch : The name of the branch that revisions are to
+# be found for.
+# $tags : True if the list of revisions are to be tags,
+# otherwise false if they are to be ids.
+# $appbar : If defined, the application progress bar
+# widget that is to be updated with the progress
+# of this operation. It is assumed that the
+# progress is set at 0 and will end up being set
+# to 1.
+# $revisions : A reference to a list that is to contain the
+# resultant list of sorted revision tags or ids.
#
##############################################################################
-sub glade_signal_autoconnect($$)
+sub get_branch_revisions($$$$$)
{
- my($glade, $client_data) = @_;
+ my($mtn, $branch, $tags, $appbar, $revisions) = @_;
- $glade->signal_autoconnect
- (sub {
- my($callback_name, $widget, $signal_name, $signal_data,
- $connect_object, $after, $user_data) = @_;
- my $func = $after ? "signal_connect_after" : "signal_connect";
- $widget->$func($signal_name,
- $callback_name,
- $connect_object ? $connect_object : $user_data); },
- $client_data);
+ @$revisions = ();
+ if ($tags)
+ {
+
+ my(@certs,
+ @list,
+ %seen);
+
+ # Get the list of revision tags.
+
+ $mtn->tags(address@hidden, $branch);
+ $appbar->set_progress_percentage(0.5) if (defined($appbar));
+ gtk2_update();
+
+ # Dedupe it.
+
+ @list = grep({ ! $seen{$_->{tag}} ++ } @list);
+
+ # Sort it by date if necessary (because it needs to be truncated or
+ # that's how the user wants it sorted).
+
+ if (($user_preferences->{query}->{tagged}->{limit} > 0
+ && scalar(@list) > $user_preferences->{query}->{tagged}->{limit})
+ || $user_preferences->{query}->{tagged}->{sort_cronologically})
+ {
+ @list = sort({
+ foreach my $rec ($a, $b)
+ {
+ if (! exists($rec->{date}))
+ {
+ $mtn->certs(address@hidden,
+ $rec->{revision_id});
+ foreach my $cert (@certs)
+ {
+ if ($cert->{name} eq "date")
+ {
+ $rec->{date} = $cert->{value};
+ last;
+ }
+ }
+ }
+ }
+ $b->{date} cmp $a->{date};
+ }
+ @list);
+ }
+
+ # Truncate the list if necessary.
+
+ if ($user_preferences->{query}->{tagged}->{limit} > 0
+ && scalar(@list) > $user_preferences->{query}->{tagged}->{limit})
+ {
+ splice(@list, $user_preferences->{query}->{tagged}->{limit});
+ }
+
+ # Extract the list of tags.
+
+ @$revisions = map({ $_->{tag} } @list);
+
+ # Sort alphabetically if required.
+
+ @$revisions = sort(@$revisions)
+ if (! $user_preferences->{query}->{tagged}->{sort_cronologically});
+
+ }
+ else
+ {
+
+ # Get the list of revision ids.
+
+ $mtn->select($revisions, "b:" . $branch);
+
+ # Does it need truncating?
+
+ if ($user_preferences->{query}->{id}->{limit} == 0
+ || scalar(@$revisions)
+ <= $user_preferences->{query}->{id}->{limit})
+ {
+
+ # No so simply sort it.
+
+ if ($user_preferences->{query}->{id}->{sort_cronologically})
+ {
+ $appbar->set_progress_percentage(0.33) if (defined($appbar));
+ gtk2_update();
+ $mtn->toposort($revisions, @$revisions);
+ $appbar->set_progress_percentage(0.66) if (defined($appbar));
+ gtk2_update();
+ @$revisions = reverse(@$revisions);
+ }
+ else
+ {
+ $appbar->set_progress_percentage(0.5) if (defined($appbar));
+ gtk2_update();
+ @$revisions = sort(@$revisions);
+ }
+
+ }
+ else
+ {
+
+ # Yes so truncate and then sort it.
+
+ $appbar->set_progress_percentage(0.33) if (defined($appbar));
+ gtk2_update();
+ $mtn->toposort($revisions, @$revisions);
+ $appbar->set_progress_percentage(0.66) if (defined($appbar));
+ splice(@$revisions,
+ 0,
+ scalar(@$revisions)
+ - $user_preferences->{query}->{id}->{limit});
+ if ($user_preferences->{query}->{id}->{sort_cronologically})
+ {
+ @$revisions = reverse(@$revisions);
+ }
+ else
+ {
+ @$revisions = sort(@$revisions);
+ }
+
+ }
+
+ }
+
+ $appbar->set_progress_percentage(1) if (defined($appbar));
+ gtk2_update();
+
}
#
##############################################################################
#
-# Routine - gtk2_update
+# Routine - get_revision_ids
#
-# Description - Process all outstanding Gtk2 toolkit events. This is used
-# to update the GUI whilst the application is busy doing
-# something.
+# Description - Return the currently selected revision id, whether this is
+# specified via a tag or as a revision id.
#
-# Data - None.
+# Data - $instance : The window instance.
+# $revision_ids : The list of selected revision ids. Normally
+# the list will have at most one element but
+# may contain more if the tag isn't unique on
+# the current branch.
#
##############################################################################
-sub gtk2_update()
+sub get_revision_ids($$)
{
- return if (Gtk2->main_level() == 0);
- while (Gtk2->events_pending())
+ my($instance, $revision_ids) = @_;
+
+ @$revision_ids=();
+ return unless ($instance->{revision_combo_details}->{complete});
+ if ($instance->{tagged_checkbutton}->get_active())
{
- Gtk2->main_iteration();
+ $instance->{mtn}->
+ select($revision_ids,
+ "t:" . $instance->{revision_combo_details}->{value});
}
+ else
+ {
+ push(@$revision_ids, $instance->{revision_combo_details}->{value});
+ }
}
#
@@ -625,6 +853,8 @@ sub create_format_tags($)
my $text_buffer = $_[0];
+ my $colours = $user_preferences->{colours};
+
# Normal Black text, assorted styles, on a white background.
$text_buffer->create_tag("normal", "weight" => PANGO_WEIGHT_NORMAL);
@@ -635,83 +865,142 @@ sub create_format_tags($)
"weight" => PANGO_WEIGHT_BOLD,
"style" => "italic");
- # Green text, assorted styles, on a white background.
+ # Set up the colour and style schemes for file comparison and annotation.
- $text_buffer->create_tag("green", "foreground" => "DarkGreen");
- $text_buffer->create_tag("bold-green",
- "weight" => PANGO_WEIGHT_BOLD,
- "foreground" => "DarkGreen");
- $text_buffer->create_tag("italics-green",
- "style" => "italic",
- "foreground" => "DarkGreen");
- $text_buffer->create_tag("bold-italics-green",
- "weight" => PANGO_WEIGHT_BOLD,
- "style" => "italic",
- "foreground" => "DarkGreen");
+ foreach my $i (1 .. 2)
+ {
+ my $clr = $user_preferences->{colours}->{"cmp_revision_" . $i};
+ $text_buffer->create_tag("compare-" . $i,
+ "foreground" => $clr->{fg});
+ $text_buffer->create_tag("bold-compare-" . $i,
+ "weight" => PANGO_WEIGHT_BOLD,
+ "foreground" => $clr->{fg});
+ $text_buffer->create_tag("italics-compare-" . $i,
+ "style" => "italic",
+ "foreground" => $clr->{fg});
+ $text_buffer->create_tag("bold-italics-compare-" . $i,
+ "weight" => PANGO_WEIGHT_BOLD,
+ "style" => "italic",
+ "foreground" => $clr->{fg});
+ $text_buffer->create_tag("compare-file-" . $i,
+ "foreground" => $clr->{fg},
+ "background" => $clr->{bg});
+ $text_buffer->create_tag("compare-file-info-" . $i,
+ "weight" => PANGO_WEIGHT_BOLD,
+ "foreground" => $clr->{hl},
+ "background" => "DarkSlateGrey");
+ foreach my $prefix ("annotate_prefix_", "annotate_text_")
+ {
+ my $tag = $prefix;
+ $tag =~ s/_/-/go;
+ $clr = $user_preferences->{colours}->{$prefix . $i};
+ $text_buffer->create_tag($tag . $i,
+ "foreground" => $clr->{fg},
+ "background" => $clr->{bg});
+ }
+ }
- # Red text, assorted styles, on a white background.
-
- $text_buffer->create_tag("red", "foreground" => "DarkRed");
- $text_buffer->create_tag("bold-red",
- "weight" => PANGO_WEIGHT_BOLD,
- "foreground" => "DarkRed");
- $text_buffer->create_tag("italics-red",
- "style" => "italic",
- "foreground" => "DarkRed");
- $text_buffer->create_tag("bold-italics-red",
- "weight" => PANGO_WEIGHT_BOLD,
- "style" => "italic",
- "foreground" => "DarkRed");
-
# Yellow text on a grey background.
$text_buffer->create_tag("compare-info",
"foreground" => "Yellow",
"background" => "LightSlateGrey");
- # Red text, assorted styles, on pink and grey backgrounds.
+}
+#
+##############################################################################
+#
+# Routine - hex_dump
+#
+# Description - Generates a hexadecimal dump of the specified data.
+#
+# Data - $data : A reference to the data that is to be hex
+# dumped.
+# Return Value : A reference to the resultant hex dump as a
+# string.
+#
+##############################################################################
- $text_buffer->create_tag("compare-first-file",
- "foreground" => "DarkRed",
- "background" => "MistyRose1");
- $text_buffer->create_tag("compare-first-file-info",
- "weight" => PANGO_WEIGHT_BOLD,
- "foreground" => "IndianRed1",
- "background" => "DarkSlateGrey");
- # Green text, assorted styles, on light green and grey backgrounds.
- $text_buffer->create_tag("compare-second-file",
- "foreground" => "DarkGreen",
- "background" => "DarkSeaGreen1");
- $text_buffer->create_tag("compare-second-file-info",
- "weight" => PANGO_WEIGHT_BOLD,
- "foreground" => "SpringGreen1",
- "background" => "DarkSlateGrey");
+sub hex_dump($)
+{
- # Blue text, assorted shades, on assorted blue backgrounds.
+ my $data = $_[0];
- $text_buffer->create_tag("annotate-prefix-1",
- "foreground" => "AliceBlue",
- "background" => "CadetBlue");
- $text_buffer->create_tag("annotate-text-1",
- "foreground" => "MidnightBlue",
- "background" => "PaleTurquoise");
+ my ($buffer,
+ $counter,
+ @line);
- # Blue text, assorted shades, on assorted blue backgrounds (slightly darker
- # than the previous group).
+ $counter = 0;
+ foreach my $byte (split(//, $$data))
+ {
+ ++ $counter;
+ push(@line, $byte);
+ $buffer .= sprintf("%02X ", ord($byte));
+ $buffer .= " " if (($counter % 8) == 0);
+ if (($counter % 16) == 0)
+ {
+ foreach my $byte2 (@line)
+ {
+ $buffer .= ($byte2 =~ m/[[:print:]]/) ? (" " . $byte2) : " .";
+ }
+ $buffer .= "\n";
+ @line = ();
+ }
+ }
- $text_buffer->create_tag("annotate-prefix-2",
- "foreground" => "AliceBlue",
- "background" => "SteelBlue");
- $text_buffer->create_tag("annotate-text-2",
- "foreground" => "MidnightBlue",
- "background" => "SkyBlue");
+ # If the last line is incomplete then finish it off.
+ if (scalar(@line) > 0)
+ {
+ $buffer .= " " x (16 - scalar(@line));
+ $buffer .= " " if (scalar(@line) < 8);
+ $buffer .= " ";
+ foreach my $byte2 (@line)
+ {
+ $buffer .= ($byte2 =~ m/[[:print:]]/) ? (" " . $byte2) : " .";
+ }
+ $buffer .= "\n";
+ }
+
+ return \$buffer;
+
}
#
##############################################################################
#
+# Routine - data_is_binary
+#
+# Description - Determines whether the specified string contains binary
+# data.
+#
+# Data - $data : A reference to the data that is to be
+# tested.
+# Return Value : True if the data is binary, otherwise false
+# if it is predominantly textual.
+#
+##############################################################################
+
+
+
+sub data_is_binary($)
+{
+
+ my $data = $_[0];
+
+ my $non_printable;
+
+ $non_printable = grep(/[^[:print:][:space:]]/, split(//, $$data));
+
+ return 1 if (((100 * $non_printable) / length($$data)) > 20);
+
+ return;
+
+}
+#
+##############################################################################
+#
# Routine - colour_to_string
#
# Description - Returns a string representing the specified
@@ -762,5 +1051,64 @@ sub set_label_value($$)
$tooltips->set_tip($widget->parent(), $value);
}
+#
+##############################################################################
+#
+# Routine - glade_signal_autoconnect
+#
+# Description - This routine uses the Glade library to connect up all the
+# registered signal handlers to their related widgets.
+#
+# Data - $glade : The Glade object describing the widgets that
+# are to have their signal handlers
+# registered.
+# $client_data : The client data that is to be passed into
+# each callback routine when it is called.
+#
+##############################################################################
+
+
+sub glade_signal_autoconnect($$)
+{
+
+ my($glade, $client_data) = @_;
+
+ $glade->signal_autoconnect
+ (sub {
+ my($callback_name, $widget, $signal_name, $signal_data,
+ $connect_object, $after, $user_data) = @_;
+ my $func = $after ? "signal_connect_after" : "signal_connect";
+ $widget->$func($signal_name,
+ $callback_name,
+ $connect_object ? $connect_object : $user_data); },
+ $client_data);
+
+}
+#
+##############################################################################
+#
+# Routine - gtk2_update
+#
+# Description - Process all outstanding Gtk2 toolkit events. This is used
+# to update the GUI whilst the application is busy doing
+# something.
+#
+# Data - None.
+#
+##############################################################################
+
+
+
+sub gtk2_update()
+{
+
+ return if (Gtk2->main_level() == 0);
+ while (Gtk2->events_pending())
+ {
+ Gtk2->main_iteration();
+ }
+
+}
+
1;
============================================================
--- mtn-browse e0a9d3e52bf31b902b4b351e04438ec745d22ac6
+++ mtn-browse 88920cff112f114139d36a0ba7cecbc14b305bca
@@ -118,6 +118,7 @@ sub directory_up_button_clicked_cb($$);
sub annotate_button_clicked_cb($$);
sub close_toolbutton_clicked_cb($$);
sub directory_up_button_clicked_cb($$);
+sub display_file($$);
sub file_change_history_button_clicked_cb($$);
sub get_browser_window(;$$$$$);
sub help_toolbutton_clicked_cb($$);
@@ -167,9 +168,32 @@ sub view_button_clicked_cb($$);
setup_sigchld_handler(\&sigchld_handler);
$glade_file = LIB_PATH . "/UI/mtn-browse.glade";
$tooltips = Gtk2::Tooltips->new();
- $mono_font = Gtk2::Pango::FontDescription->from_string("monospace 10");
$line_image = Gtk2::Gdk::Pixbuf->new_from_file(LIB_PATH . "/UI/line.png");
+ # Load in user preferences.
+
+ eval
+ {
+ $user_preferences = load_preferences();
+ $mime_match_table =
+ build_mime_match_table($user_preferences->{mime_table});
+ };
+ if ($@ ne "")
+ {
+ chomp($@);
+ my $dialog = Gtk2::MessageDialog->new
+ ($browser->{window},
+ ["modal"],
+ "warning",
+ "close",
+ sprintf("Your preferences cannot be loaded:\n%s", $@));
+ $dialog->run();
+ $dialog->destroy();
+ exit(1);
+ }
+ $mono_font = Gtk2::Pango::FontDescription->
+ from_string($user_preferences->{fixed_font});
+
# Create the temporary working directory.
eval
@@ -191,9 +215,9 @@ sub view_button_clicked_cb($$);
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 move to the workspace's
- # root and then pre-load the browser with the relevant branch and revision.
+ # Open a Monotone database. First attempt to open the current Monotone
+ # workspace's database. If this doesn't work or the default database is to
+ # be used anyway then attempt to open that database instead.
eval
{
@@ -216,10 +240,48 @@ sub view_button_clicked_cb($$);
}
}
$mtn = Monotone::AutomateStdio->new();
- $mtn->get_option(\$branch, "branch");
- $mtn->get_base_revision_id(\$revision_id);
+ if ($user_preferences->{workspace}->{auto_select})
+ {
+ $mtn->get_option(\$branch, "branch");
+ $mtn->get_base_revision_id(\$revision_id);
+ }
};
+ if (! ($user_preferences->{workspace}->{takes_precedence}
+ && defined($mtn))
+ && $user_preferences->{default_mtn_db} ne "")
+ {
+ # Before opening the default database, make sure we are not in any
+ # workspace.
+
+ if (defined($mtn))
+ {
+ chdir("..");
+ $mtn = $branch = $revision_id = undef;
+ }
+
+ # Attempt to open the default database.
+
+ eval
+ {
+ $mtn = Monotone::AutomateStdio->
+ new($user_preferences->{default_mtn_db});
+ };
+ if ($@ ne "")
+ {
+ my $dialog = Gtk2::MessageDialog->new
+ (undef,
+ ["modal"],
+ "warning",
+ "close",
+ sprintf("Cannot open database `%s'.",
+ $user_preferences->{default_mtn_db}));
+ $dialog->run();
+ $dialog->destroy();
+ }
+
+ }
+
# Set up the error handlers for the Monotone library.
Monotone::AutomateStdio->register_error_handler("both",
@@ -230,7 +292,7 @@ sub view_button_clicked_cb($$);
# that control can be handed over to Gtk2 before updating the display.
$browser = get_browser_window($mtn);
- if (defined($mtn))
+ if (defined($mtn) && defined($branch))
{
Glib::Idle->add
(sub {
@@ -249,8 +311,8 @@ sub view_button_clicked_cb($$);
return FALSE;
},
$browser);
- $mtn = undef;
}
+ $mtn = undef;
# Hand control over to Gtk2.
@@ -345,8 +407,8 @@ sub about_activate_cb($$)
#
# Routine - new_toolbutton_clicked_cb
#
-# Description - Callback routine called when the user clicks on the
-# new toolbutton in a main browser window.
+# 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
@@ -374,8 +436,8 @@ sub new_toolbutton_clicked_cb($$)
#
# Routine - open_toolbutton_clicked_cb
#
-# Description - Callback routine called when the user clicks on the
-# open toolbutton in a main browser window.
+# 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
@@ -393,102 +455,22 @@ sub open_toolbutton_clicked_cb($$)
return if ($browser->{in_cb});
local $browser->{in_cb} = 1;
- my($chooser_dialog,
- $done);
+ my $mtn;
- $chooser_dialog = Gtk2::FileChooserDialog->new("Open Database",
- $browser->{window},
- "open",
- "gtk-cancel" => "cancel",
- "gtk-open" => "ok");
-
- do
+ if (open_database($browser->{window}, \$mtn, undef))
{
- 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;
- }
+ $browser->{mtn} = $mtn;
+ &{$browser->{update_handler}}($browser, DATABASE_CHANGED);
}
- 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.
+# 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
@@ -569,7 +551,12 @@ sub preferences_toolbutton_clicked_cb($$
return if ($browser->{in_cb});
local $browser->{in_cb} = 1;
- preferences($browser);
+ if (preferences($browser))
+ {
+ $user_preferences = load_preferences();
+ $mime_match_table =
+ build_mime_match_table($user_preferences->{mime_table});
+ }
}
#
@@ -1033,7 +1020,8 @@ sub view_button_clicked_cb($$)
$data,
$fh,
$file_name,
- $mime,
+ $helper,
+ $mime_obj,
$mime_type);
if (! defined($file_name =
@@ -1072,39 +1060,80 @@ sub view_button_clicked_cb($$)
$fh->close();
$fh = undef;
- # Load into the appropriate application for this type of file, defaulting
- # to Vi if necessary.
+ # Get the user preference settings for this type of file.
- if (! defined($mime_type =
- Gnome2::VFS->get_mime_type("file://" . $file_name)))
+ foreach my $entry (@$mime_match_table)
{
- my $dialog = Gtk2::MessageDialog->new
- ($browser->{window},
- ["modal"],
- "warning",
- "close",
- "Unknown file type, not viewing.");
- $dialog->run();
- $dialog->destroy();
- return;
+ if ($browser->{file_being_viewed}->{short_name} =~ m/$entry->{re}/)
+ {
+ $helper = $entry->{details}->{helper_application};
+ last;
+ }
}
- $app = $mime->get_default_application()
- if (defined($mime = Gnome2::VFS::Mime::Type->new($mime_type)));
- if (defined($app))
+
+ # If the user has specified a helper application then use that to view the
+ # file, otherwise use the default desktop settings.
+
+ if (defined($helper) && $helper ne "")
{
- $app->launch("file://" . $file_name);
+
+ # Use the specified helper application, replacing `{file}' with the
+ # real file name.
+
+ if ($helper =~ m/\{file\}/)
+ {
+ $helper =~ s/\{file\}/$file_name/g;
+ }
+ else
+ {
+ $helper .= " " . $file_name;
+ }
+
+ # Launch it.
+
+ system($helper . " &");
+
}
else
{
- my $dialog = Gtk2::MessageDialog->new
- ($browser->{window},
- ["modal"],
- "info",
- "close",
- sprintf("No application is associated with\n"
- . "Mime type `%s',\nusing Vi instead.",
- $mime_type));
- system("xterm -e vi " . $file_name . " &");
+
+ # Use the desktop to load the file.
+
+ # Use the appropriate application for this type of file, defaulting to
+ # Vi if necessary.
+
+ if (! defined($mime_type =
+ Gnome2::VFS->get_mime_type("file://" . $file_name)))
+ {
+ my $dialog = Gtk2::MessageDialog->new
+ ($browser->{window},
+ ["modal"],
+ "warning",
+ "close",
+ "Unknown file type, not viewing.");
+ $dialog->run();
+ $dialog->destroy();
+ return;
+ }
+ $app = $mime_obj->get_default_application()
+ if (defined($mime_obj = Gnome2::VFS::Mime::Type->new($mime_type)));
+ if (defined($app))
+ {
+ $app->launch("file://" . $file_name);
+ }
+ else
+ {
+ my $dialog = Gtk2::MessageDialog->new
+ ($browser->{window},
+ ["modal"],
+ "info",
+ "close",
+ sprintf("No application is associated with\n"
+ . "Mime type `%s',\nusing Vi instead.",
+ $mime_type));
+ system("xterm -e vi " . $file_name . " &");
+ }
+
}
}
@@ -1565,7 +1594,7 @@ sub get_browser_window(;$$$$$)
$browser->{revision_combo_details}->{preset} = 0;
$browser->{directory_combo_details}->{preset} = 0;
$browser->{file_being_viewed_preset_value} = "";
- &{$browser->{update_handler}}($browser, DATABASE_CHANGED);
+ &{$browser->{update_handler}}($browser, ALL_CHANGED);
}
else
@@ -1589,7 +1618,7 @@ sub get_browser_window(;$$$$$)
$browser->{revision_combo_details}->{preset} = 0;
$browser->{directory_combo_details}->{preset} = 0;
$browser->{file_being_viewed_preset_value} = "";
- &{$browser->{update_handler}}($browser, DATABASE_CHANGED);
+ &{$browser->{update_handler}}($browser, ALL_CHANGED);
$browser->{window}->show_all();
# Now update with the details of the specified database.
@@ -1664,7 +1693,7 @@ sub update_browser_state($$)
# The database has changed.
- if ($changed & BRANCH)
+ if ($changed == DATABASE_CHANGED)
{
my $db_name;
@@ -1786,42 +1815,11 @@ sub update_browser_state($$)
{
$browser->{appbar}->set_status("Fetching revision list");
gtk2_update();
-
- # Get either a list of tags or revision ids depending upon what the
- # user has chosen.
-
- if ($browser->{tagged_checkbutton}->get_active())
- {
- my(%dup_list,
- @list);
- $browser->{mtn}->
- tags(address@hidden, $browser->{branch_combo_details}->{value});
- $browser->{appbar}->set_progress_percentage(0.5);
- gtk2_update();
- foreach my $item (@list)
- {
- if (! exists($dup_list{$item->{tag}}))
- {
- push(@revision_list, $item->{tag});
- $dup_list{$item->{tag}} = 1;
- }
- }
- }
- else
- {
- $browser->{mtn}->
- select(address@hidden,
- "b:" . $browser->{branch_combo_details}->{value});
- $browser->{appbar}->set_progress_percentage(0.33);
- gtk2_update();
- $browser->{mtn}->toposort(address@hidden, @revision_list);
- $browser->{appbar}->set_progress_percentage(0.66);
- gtk2_update();
- splice(@revision_list, 0, scalar(@revision_list) - 100);
- @revision_list = reverse(@revision_list);
- }
- $browser->{appbar}->set_progress_percentage(1);
- gtk2_update();
+ get_branch_revisions($browser->{mtn},
+ $browser->{branch_combo_details}->{value},
+ $browser->{tagged_checkbutton}->get_active(),
+ $browser->{appbar},
+ address@hidden);
}
$browser->{revision_combo_details}->{list} = address@hidden;
@@ -1861,7 +1859,7 @@ sub update_browser_state($$)
if ($browser->{directory_combo_details}->{preset})
{
$browser->{directory_combo_details}->{complete} = 1;
- $browser->{revision_combo_details}->{preset} = 0;
+ $browser->{directory_combo_details}->{preset} = 0;
}
else
{
@@ -2114,8 +2112,7 @@ sub update_browser_state($$)
if (exists($browser->{file_being_viewed}->{manifest_entry}))
{
- my $manifest_entry;
- $manifest_entry =
+ my $manifest_entry =
$browser->{file_being_viewed}->{manifest_entry};
# Only do anything if the selected file has changed.
@@ -2124,170 +2121,37 @@ sub update_browser_state($$)
ne $manifest_entry->{file_id})
{
- my($contents,
- $lang,
- $mime_type,
- $scrolled_window);
+ my $textual_data;
- # Reset the file view buffer and the associated find text
- # window.
+ # Enable the file buttons, keeping the ones relating to text
+ # files disabled, and reset any associated find text window.
$browser->{file_button_vbox}->set_sensitive(TRUE);
foreach my $widget (@{$browser->{text_file_sensitive_group}})
{
$widget->set_sensitive(FALSE);
}
- $browser->{file_view_svbuffer}->
- place_cursor($browser->{file_view_svbuffer}->
- get_start_iter());
- $browser->{file_view_svbuffer}->set_text("");
- $browser->{file_view_svbuffer}->set("highlight", FALSE);
reset_find_text($browser->{file_view_sv});
disable_find_text($browser->{file_view_sv}, 1);
- # Get contents.
+ # Display the selected file's contents.
- $browser->{mtn}->get_file(\$contents,
- $manifest_entry->{file_id});
+ display_file($browser, \$textual_data);
- # Try and work out the mime type, first based on contents and
- # then based on the file name extension.
+ # If we have just displayed a text file then enable the file
+ # buttons applicable to text files and enable any associated
+ # find text window that may be displayed.
- if (! defined($mime_type =
- Gnome2::VFS->get_mime_type_for_data($contents))
- || $mime_type eq "text/plain")
+ if ($textual_data)
{
- my $name = $browser->{file_being_viewed}->{short_name};
- foreach my $item (@text_mime_types)
+ foreach my $widget
+ (@{$browser->{text_file_sensitive_group}})
{
- if ($name =~ m/$item->{pattern}/)
- {
- $mime_type = $item->{type};
- last;
- }
+ $widget->set_sensitive(TRUE);
}
+ disable_find_text($browser->{file_view_sv}, 0);
}
- # Override some mis-identified types.
-
- $mime_type = "image/svg+xml"
- if ($mime_type eq "text/xml"
- && $browser->{file_being_viewed}->{short_name}
- =~ m/.*\.svg$/o);
-
- # If it's image data then attempt to render it.
-
- if ($mime_type =~ m/^image\/.+$/o)
- {
-
- # Image data.
-
- eval
- {
- my $loader = Gtk2::Gdk::PixbufLoader->new();
- $loader->write($contents);
- $loader->close();
- $browser->{file_view_svbuffer}->insert_pixbuf
- ($browser->{file_view_svbuffer}->get_start_iter(),
- $loader->get_pixbuf());
- };
- $browser->{file_view_svbuffer}->
- set_text("<" . $mime_type . ">") if ($@ ne "");
-
- }
- else
- {
-
- # Non-image data.
-
- my $ok_to_render = 0;
-
- # Attempt to syntax highlight the file if it looks safe.
-
- if ($mime_type =~ m/^application\/.+$/o)
- {
- my $part;
- ($part) = ($mime_type =~ m/^application\/(.+)$/o);
- foreach my $item (@text_viewable_app_mime_types)
- {
- if ($part eq $item)
- {
- $ok_to_render = 1;
- last;
- }
- }
- }
-
- if ($mime_type =~ m/^text\/.+$/o || $ok_to_render)
- {
-
- # Contents is displayable text.
-
- my $iter;
-
- # Enable syntax highlighting if it is available for
- # this type of text file.
-
- if (defined($lang = $browser->{file_view_svlangmgr}->
- get_language_from_mime_type($mime_type)))
- {
- $browser->{file_view_svbuffer}->
- set("highlight", TRUE);
- $browser->{file_view_svbuffer}->
- set_language($lang);
- }
-
- # Load in the contents and then delete the trailing
- # newline.
-
- $browser->{file_view_svbuffer}->set_text($contents);
- $iter = $browser->{file_view_svbuffer}->get_end_iter();
- $browser->{file_view_svbuffer}->delete
- ($iter,
- $browser->{file_view_svbuffer}->get_end_iter())
- if ($iter->backward_char());
-
- # Enable the file buttons applicable to text files.
-
- foreach my $widget
- (@{$browser->{text_file_sensitive_group}})
- {
- $widget->set_sensitive(TRUE);
- }
-
- # Enable any associated find text window that may be
- # displayed.
-
- disable_find_text($browser->{file_view_sv}, 0);
-
- }
- else
- {
-
- # Display mime type for undisplayable file contents.
-
- $browser->{file_view_svbuffer}->
- set("highlight", FALSE);
- $browser->{file_view_svbuffer}->
- set_text("<" . $mime_type . ">");
-
- }
-
- }
-
- # Scroll back up to the top left.
-
- $browser->{file_view_svbuffer}->
- place_cursor($browser->{file_view_svbuffer}->
- get_start_iter());
- if ($browser->{file_view_scrolledwindow}->realized())
- {
- $browser->{file_view_scrolledwindow}->
- get_vadjustment()->set_value(0);
- $browser->{file_view_scrolledwindow}->
- get_hadjustment()->set_value(0);
- }
-
# Update the file details labels.
if (! exists($manifest_entry->{last_changed_revision}))
@@ -2353,6 +2217,178 @@ sub update_browser_state($$)
#
##############################################################################
#
+# Routine - display_file
+#
+# Description - Display the currenty selected file in the sourceview
+# textview.
+#
+# Data - $browser : The browser instance that is to display the
+# file.
+# $text_data : A reference to a variable that is to contain a
+# boolean indicator as to whether the displayed
+# file contains textual or binary data.
+#
+##############################################################################
+
+
+
+sub display_file($$)
+{
+
+ my($browser, $textual_data) = @_;
+
+ my($contents,
+ $iter,
+ $lang,
+ $mime_details,
+ $mime_type);
+
+ $$textual_data = 0;
+
+ # Reset the file view buffer.
+
+ $browser->{file_view_svbuffer}->
+ place_cursor($browser->{file_view_svbuffer}->get_start_iter());
+ $browser->{file_view_svbuffer}->set_text("");
+ $browser->{file_view_svbuffer}->set("highlight", FALSE);
+
+ # Get contents.
+
+ $browser->{mtn}->get_file(\$contents,
+ $browser->{file_being_viewed}->{manifest_entry}->
+ {file_id});
+
+ # Try and work out the MIME type through file name pattern matching.
+
+ foreach my $entry (@$mime_match_table)
+ {
+ if ($browser->{file_being_viewed}->{short_name} =~ m/$entry->{re}/)
+ {
+ $mime_type = $entry->{details}->{name};
+ $mime_details = $entry->{details};
+ last;
+ }
+ }
+
+ # If that didn't work then try determining the MIME type based upon the
+ # file's contents.
+
+ $mime_type = Gnome2::VFS->get_mime_type_for_data($contents)
+ if (! defined($mime_type));
+
+ # Only attempt to render the file's contents if requested to do so.
+
+ if (! defined($mime_type)
+ || (defined($mime_details) && ! $mime_details->{display_internally}))
+ {
+
+ # The user doesn't want to display this type of file.
+
+ $browser->{file_view_svbuffer}->
+ set_text("<"
+ . (defined($mime_type) ? $mime_type : "Unknown Contents")
+ . ">");
+
+ }
+ else
+ {
+
+ # The user wants to display this type of file.
+
+ # Image/non-image data?
+
+ if ($mime_type =~ m/^image\/.+$/o)
+ {
+
+ # Image data.
+
+ eval
+ {
+ my $loader = Gtk2::Gdk::PixbufLoader->new();
+ $loader->write($contents);
+ $loader->close();
+ $browser->{file_view_svbuffer}->insert_pixbuf
+ ($browser->{file_view_svbuffer}->get_start_iter(),
+ $loader->get_pixbuf());
+ };
+ $browser->{file_view_svbuffer}->set_text("<" . $mime_type . ">")
+ if ($@ ne "");
+
+ }
+ else
+ {
+
+ # Non-image data.
+
+ # Binary/text data?
+
+ if (data_is_binary(\$contents))
+ {
+
+ # Binary data.
+
+ # We have been asked to display this data. The only thing we
+ # can do is to hex dump it out.
+
+ $browser->{file_view_svbuffer}->
+ set_text("<" . $mime_type . "> Hex dump:\n");
+ $browser->{file_view_svbuffer}->
+ insert($browser->{file_view_svbuffer}->get_end_iter(),
+ ${hex_dump(\$contents)});
+
+ }
+ else
+ {
+
+ # Text data.
+
+ $$textual_data = 1;
+
+ # Enable syntax highlighting if the user wants it on and it is
+ # available for this type of file.
+
+ if ((! defined($mime_details)
+ || (defined($mime_details)
+ && $mime_details->{syntax_highlight}))
+ && defined($lang =
+ $browser->{file_view_svlangmgr}->
+ get_language_from_mime_type($mime_type)))
+ {
+ $browser->{file_view_svbuffer}->set("highlight", TRUE);
+ $browser->{file_view_svbuffer}->set_language($lang);
+ }
+
+ # Load in the contents.
+
+ $browser->{file_view_svbuffer}->set_text($contents);
+
+ }
+
+ # Delete the trailing newline.
+
+ $iter = $browser->{file_view_svbuffer}->get_end_iter();
+ $browser->{file_view_svbuffer}->delete
+ ($iter, $browser->{file_view_svbuffer}->get_end_iter())
+ if ($iter->backward_char());
+
+ }
+
+ }
+
+ # Scroll back up to the top left.
+
+ $browser->{file_view_svbuffer}->
+ place_cursor($browser->{file_view_svbuffer}->get_start_iter());
+ if ($browser->{file_view_scrolledwindow}->realized())
+ {
+ $browser->{file_view_scrolledwindow}->get_vadjustment()->set_value(0);
+ $browser->{file_view_scrolledwindow}->get_hadjustment()->set_value(0);
+ }
+
+}
+#
+##############################################################################
+#
# Routine - mtn_error_handler
#
# Description - This routine is called when ever there is a problem with
============================================================
--- mtn-browse.glade 7e503af1903439bbf47468d917f692db3bea8ec4
+++ mtn-browse.glade e108526a6ed91bc84238ac6586567a7c53b196ea
@@ -3971,7 +3971,7 @@ file version that is to be compared0
-
+
True
View the change log of the revision
that had the red highlighted text
@@ -3982,9 +3982,9 @@ that had the red highlighted text
-
+
True
- <span foreground="DarkRed">Revision Change Log</span>
+
False
True
GTK_JUSTIFY_LEFT
@@ -4000,7 +4000,7 @@ that had the red highlighted text
-
+
True
View the change log of the revision
that had the green highlighted text
@@ -4011,9 +4011,9 @@ that had the green highlighted text
-
+
True
- <span foreground="SpringGreen4">Revision Change Log</span>
+
False
True
GTK_JUSTIFY_LEFT
@@ -4767,7 +4767,8 @@ of tagged revisions in Combo lists
True
The maximum number of tags
-to be displayed (0 - unlimited)
+to be displayed (starting from
+the most recent, 0 = unlimited)
True
False
@@ -4801,7 +4802,8 @@ to be displayed (0 - unlimited)
True
The maximum number of ids
-to be displayed (0 - unlimited)
+to be displayed (starting from
+the most recent, 0 = unlimited)
True
False
@@ -6561,10 +6563,11 @@ 2) The optional token {file} is
with this file type is used
2) The optional token {file} is
-replaced with the file's full file
-name, if not present then the
-file name is just appended to
-the end of the command
+replaced with the file's full path
+name, if this token is not
+present then the file name is
+simply appended to the end of
+the command
True
False