# # # add_file "FindFiles.pm" # content [fb80c399c9551ba7d3da269d466ede47e7d4e027] # # patch "AdvancedFind.pm" # from [9e7ed7872bbe9dd29d712fb54727bae6af7be4c2] # to [d62fc3a65a6f7c361800185d8907280fefe0dd75] # # patch "Annotate.pm" # from [edc84764f8d6d85efdb259014f3a2660425fa679] # to [96f269e7203303f964dfb0fd024a3f6b55104591] # # patch "ChangeLog.pm" # from [f9ba345d6a2d3a9fd104b35ce36ef9df8b04d8a2] # to [1bc50a48e82d47e18f69a426dcf068ecfa9cbb78] # # patch "ComboAutoCompletion.pm" # from [6b3d8c390427cc6638b69aafcc01c1433ec543d7] # to [e64c089c106406ce01bd742aa45cf28a164aebea] # # patch "Completion.pm" # from [71827654ac9917a8031920fc50bb877f660714d6] # to [d416a066aa7f7ea3c953f07d97b6e5d7a1f3cc05] # # patch "FindText.pm" # from [7eb1fe25f19787ddc1795556f571de6bb0d53b64] # to [6b84fd52375956b82047faa0b453a36646b8f75b] # # patch "Globals.pm" # from [210c3971b3ca55744f8e3ae4c40f42395e326d77] # to [671f3b14c85fa6f451133c775f43160a950fc834] # # patch "History.pm" # from [06156650d4157a98ad7b2d627b2f9da2d58c83ac] # to [591b6d22fc8b0f99ea5127f90a2087171f576cb6] # # patch "Preferences.pm" # from [777f8bf59768c400f654b5f4565a7d48dc46791d] # to [15134271c380429b82b4ec8cbb44eea27d9795f2] # # patch "Utilities.pm" # from [6271d135e4afb4b089282c157b70dfe11fff7a9d] # to [ac91364337013be65703eebc6dd492b2841d6a11] # # patch "WindowManager.pm" # from [72764d5731e5cf3bf95be105da2fca5b15089fb2] # to [2f164203f11d37ea14d264041fd83c7d9e44aa6a] # # patch "mtn-browse" # from [186fceb438602cbd85c940611e2083ffbd795358] # to [c4da8275bcc59dac9bd253aae27e1a380be8aa4a] # # patch "mtn-browse.glade" # from [ee150cf030015b3f40d78a83daa28bad07269dd1] # to [91f78642431d06166c66500947afe38933877de6] # ============================================================ --- FindFiles.pm fb80c399c9551ba7d3da269d466ede47e7d4e027 +++ FindFiles.pm fb80c399c9551ba7d3da269d466ede47e7d4e027 @@ -0,0 +1,1268 @@ +############################################################################## +# +# File Name - FindFiles.pm +# +# Description - The find files module for the mtn-browse application. This +# module contains all the routines for implementing the find +# files window. +# +# Author - A.E.Cooper. +# +# Legal Stuff - Copyright (c) 2007 Anthony Edward Cooper +# . +# +# This program is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public +# License as published by the Free Software Foundation; +# either version 3 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +# PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public +# License along with this software; if not, write to the Free +# Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307 USA. +# +############################################################################## +# +############################################################################## +# +# Global Data For This Module +# +############################################################################## + + + +# ***** DIRECTIVES ***** + +require 5.008; + +use strict; +use warnings; + +# ***** GLOBAL DATA DECLARATIONS ***** + +# Constants for the columns within the results listsore widget. + +use constant RLS_NAME_COLUMN => 0; +use constant RLS_MANIFEST_ENTRY_COLUMN => 1; + +# Constants for representing combobox values. + +use constant DURATION_MINUTES => 0; +use constant DURATION_HOURS => 1; +use constant DURATION_DAYS => 2; +use constant DURATION_MONTHS => 3; +use constant DURATION_YEARS => 4; + +use constant CMP_ANY_SIZE => 0; +use constant CMP_AT_LEAST => 1; +use constant CMP_AT_MOST => 2; +use constant CMP_EQUAL_TO => 3; + +use constant SIZE_B => 0; +use constant SIZE_KB => 1; +use constant SIZE_MB => 2; + +# ***** FUNCTIONAL PROTOTYPES ***** + +# Public routines. + +sub display_find_files($$$$); + +# Private routines. + +sub between_range_radiobutton_toggled_cb($$); +sub date_range_checkbutton_toggled_cb($$); +sub get_find_files_window(); +sub results_treeview_cursor_changed_cb($$); +sub results_treeview_row_activated_cb($$$$); +sub save_query_from_gui($); +sub search_files_button_clicked_cb($$); +sub size_comparitor_combobox_changed_cb($$); +sub update_comboxentries_history($$); +sub validate_query($$); +# +############################################################################## +# +# Routine - display_find_files +# +# Description - Display the find files window. +# +# Data - $mtn : The Monotone instance handle that is to +# be used to search for files. +# $revision_id : The id of the revision that is to be +# searched. +# $manifest : A reference to the corresponding revision +# manifest. +# $starting_point : The directory from which the search is to +# be started. +# +############################################################################## + + + +sub display_find_files($$$$) +{ + + my($mtn, $revision_id, $manifest, $starting_point) = @_; + + my $instance; + + $instance = get_find_files_window(); + local $instance->{in_cb} = 1; + + $instance->{mtn} = $mtn; + $instance->{revision_id} = $revision_id; + $instance->{manifest} = $manifest; + $instance->{starting_point} = $starting_point; + + $instance->{window}->set_title(__x("Find Files With Revision {rev}", + rev => $revision_id)); + set_label_value($instance->{searching_from_value_label}, + $instance->{starting_point}); + + $instance->{window}->show_all(); + +} +# +############################################################################## +# +# Routine - date_range_checkbutton_toggled_cb +# +# Description - Callback routine called when the user changes the value of +# the date range check button in the find files window. +# +# Data - $widget : The widget object that received the signal. +# $instance : The window instance that is associated with +# this widget. +# +############################################################################## + + + +sub date_range_checkbutton_toggled_cb($$) +{ + + my($widget, $instance) = @_; + + return if ($instance->{in_cb}); + local $instance->{in_cb} = 1; + + # Simply enable and disable the appropriate widgets. + + if ($instance->{date_range_checkbutton}->get_active()) + { + for my $widget (@{$instance->{date_sensitive_group}}) + { + $widget->set_sensitive(TRUE); + } + if ($instance->{between_range_radiobutton}->get_active()) + { + for my $widget (@{$instance->{during_dates_sensitive_group}}) + { + $widget->set_sensitive(FALSE); + } + } + else + { + for my $widget (@{$instance->{between_dates_sensitive_group}}) + { + $widget->set_sensitive(FALSE); + } + } + } + else + { + for my $widget (@{$instance->{date_sensitive_group}}) + { + $widget->set_sensitive(FALSE); + } + } + +} +# +############################################################################## +# +# Routine - between_range_radiobutton_toggled_cb +# +# Description - Callback routine called when the user changes the value of +# the between radio button in the find files window. +# +# Data - $widget : The widget object that received the signal. +# $instance : The window instance that is associated with +# this widget. +# +############################################################################## + + + +sub between_range_radiobutton_toggled_cb($$) +{ + + my($widget, $instance) = @_; + + return if ($instance->{in_cb}); + local $instance->{in_cb} = 1; + + # Simply enable and disable the appropriate widgets. + + if ($instance->{between_range_radiobutton}->get_active()) + { + for my $widget (@{$instance->{between_dates_sensitive_group}}) + { + $widget->set_sensitive(TRUE); + } + for my $widget (@{$instance->{during_dates_sensitive_group}}) + { + $widget->set_sensitive(FALSE); + } + } + else + { + for my $widget (@{$instance->{during_dates_sensitive_group}}) + { + $widget->set_sensitive(TRUE); + } + for my $widget (@{$instance->{between_dates_sensitive_group}}) + { + $widget->set_sensitive(FALSE); + } + } + +} +# +############################################################################## +# +# Routine - size_comparitor_combobox_changed_cb +# +# Description - Callback routine called when the user changes the value of +# the file size combobox by selecting an entry from its +# pulldown list in the find files window. +# +# Data - $widget : The widget object that received the signal. +# $instance : The window instance that is associated with +# this widget. +# +############################################################################## + + + +sub size_comparitor_combobox_changed_cb($$) +{ + + my($widget, $instance) = @_; + + return if ($instance->{in_cb}); + local $instance->{in_cb} = 1; + + # Simply enable and disable the appropriate widgets. + + if ($widget->get_active() == CMP_ANY_SIZE) + { + for my $widget (@{$instance->{size_sensitive_group}}) + { + $widget->set_sensitive(FALSE); + } + } + else + { + for my $widget (@{$instance->{size_sensitive_group}}) + { + $widget->set_sensitive(TRUE); + } + } + +} +# +############################################################################## +# +# Routine - search_files_button_clicked_cb +# +# Description - Callback routine called when the user clicks on the find +# button in a find files window. +# +# Data - $widget : The widget object that received the signal. +# $instance : The window instance that is associated with +# this widget. +# +############################################################################## + + + +sub search_files_button_clicked_cb($$) +{ + + my($widget, $instance) = @_; + + return if ($instance->{in_cb}); + local $instance->{in_cb} = 1; + + my($contents_re, + $counter, + $file_glob_re, + $manifest, + $matches, + $period, + $query, + $size); + my $wm = WindowManager->instance(); + + # Get the query from the GUI and validate it. + + $query = save_query_from_gui($instance); + return if (! validate_query($instance, $query)); + + # Update the comboxentries histories. + + update_comboxentries_history($instance, $query); + + # Build up a sub-manifest representing the items that we are going to + # search. + + if ($query->{file_glob_search_subdirectories} + && $instance->{starting_point} eq "") + { + $manifest = $instance->{manifest}; + } + else + { + my @manifest; + if ($query->{file_glob_search_subdirectories}) + { + my $match_re = qr/^$instance->{starting_point}\/.+$/; + @manifest = + grep($_->{name} =~ m/$match_re/, @{$instance->{manifest}}); + } + else + { + my @result; + get_dir_contents($instance->{starting_point}, + $instance->{manifest}, + address@hidden); + @manifest = map($_->{manifest_entry}, @result); + } + $manifest = address@hidden; + } + + # Precompile the regexps and more complex comparison values. + + if ($query->{file_glob} ne "") + { + my $re_text = file_glob_to_regexp($query->{file_glob}); + if ($query->{file_glob_case_sensitive}) + { + $file_glob_re = qr/$re_text/; + } + else + { + $file_glob_re = qr/$re_text/i; + } + } + else + { + $file_glob_re = qr/^.*$/; + } + if ($query->{contents_pattern} ne "") + { + + # Need the following pragma as $contents_re could potentially be used + # against binary data. + + use bytes; + + if ($query->{contents_pattern_is_regexp}) + { + if ($query->{contents_case_sensitive}) + { + $contents_re = qr/$query->{contents_pattern}/; + } + else + { + $contents_re = qr/$query->{contents_pattern}/i; + } + } + else + { + if ($query->{contents_case_sensitive}) + { + $contents_re = qr/\Q$query->{contents_pattern}\E/; + } + else + { + $contents_re = qr/\Q$query->{contents_pattern}\E/i; + } + } + + } + if (exists($query->{period})) + { + + my($time, + @time_val); + + # Please note: + # 1) Values from localtime etc start from 0. + # 2) You may think that gmtime() should be used instead of + # localtime(), but what happens when the user jumps back in time + # by 5 months and goes from say GMT to BST? Would they expect + # the hours to be adjusted? Probably not. + + @time_val = localtime(); + $time = timelocal(@time_val[0 .. 5]); + if ($query->{period_units} == DURATION_MINUTES) + { + $time -= ($query->{period} * 60); + } + elsif ($query->{period_units} == DURATION_HOURS) + { + $time -= ($query->{period} * 60 * 60); + } + elsif ($query->{period_units} == DURATION_DAYS) + { + $time -= ($query->{period} * 60 * 60 * 24); + } + elsif ($query->{period_units} == DURATION_MONTHS) + { + my($month, + $query_months, + $year); + $query_months = $query->{period}; + ($month, $year) = (@time_val)[4, 5]; + if ($query_months > 12) + { + $year -= int($query_months / 12); + $query_months %= 12; + } + if ($query_months > $month) + { + -- $year; + $month = 12 - ($query_months - $month); + } + else + { + $month -= $query_months; + } + @time_val[4, 5] = ($month, $year); + $time = timegm(@time_val[0 .. 5]); + } + else + { + $time_val[5] -= $query->{period}; + $time = timegm(@time_val[0 .. 5]); + } + $period = strftime("%Y-%m-%dT%H:%M:%S", gmtime($time)); + } + if (exists($query->{file_size})) + { + if ($query->{file_size_units} == SIZE_B) + { + $size = $query->{file_size}; + } + elsif ($query->{file_size_units} == SIZE_KB) + { + $size = $query->{file_size} * 1024; + } + else + { + $size = $query->{file_size} * 1024 * 1024; + } + } + + $wm->make_busy($instance, 1); + $instance->{appbar}->push(""); + $wm->update_gui(); + + $instance->{appbar}->set_status(__("Finding matching files")); + $instance->{results_liststore}->clear(); + set_label_value($instance->{author_value_label}, ""); + set_label_value($instance->{file_id_value_label}, ""); + set_label_value($instance->{last_update_value_label}, ""); + set_label_value($instance->{file_revision_id_value_label}, ""); + $wm->update_gui(); + + $instance->{stop_button}->set_sensitive(TRUE); + + # Now do the search. + + $counter = 1; + $matches = 0; + foreach my $entry (@$manifest) + { + + # Check for aborts. + + last if ($instance->{stop}); + + # Exclude entries using the cheapest critera first. + + # Name. + + next if ($entry->{name} !~ m/$file_glob_re/ + || ($query->{file_glob} eq "" && $entry->{type} ne "file")); + + # The remaining tests only make sense for files. + + if ($entry->{type} eq "file") + { + + # Date and/or modifier. + + if (exists($query->{older_date}) || exists($query->{period}) + || $query->{modified_by} ne "") + { + my($author, + $last_update); + if (! exists($entry->{author})) + { + get_file_details($instance->{mtn}, + $instance->{revision_id}, + $entry->{name}, + \$author, + \$last_update, + \$entry->{last_changed_revision}); + $entry->{author} = $author; + $entry->{last_update} = $last_update; + } + else + { + $author = $entry->{author}; + $last_update = $entry->{last_update}; + } + if (exists($query->{older_date})) + { + next if ($last_update lt $query->{older_date} + || $last_update gt $query->{younger_date}); + } + elsif (exists($query->{period})) + { + next if ($last_update lt $period); + } + next if ($query->{modified_by} ne "" + && $query->{modified_by} ne $author); + } + + # Contents and/or size. + + if (defined($contents_re) || exists($query->{file_size})) + { + my $data; + if (exists($query->{file_size})) + { + if (! exists($entry->{size})) + { + $instance->{mtn}->get_file(\$data, $entry->{file_id}); + $entry->{size} = length($data); + } + if ($query->{file_size_operator} == CMP_AT_LEAST) + { + next if ($entry->{size} < $size); + } + elsif ($query->{file_size_operator} == CMP_AT_MOST) + { + next if ($entry->{size} > $size); + } + else + { + next if ($entry->{size} != $size); + } + } + if (defined($contents_re)) + { + if (! exists($entry->{is_binary})) + { + $instance->{mtn}->get_file(\$data, $entry->{file_id}) + if (! defined($data)); + $entry->{is_binary} = data_is_binary(\$data); + } + + # Ignore binary files if requested. + + next if ($entry->{is_binary} + && ! $query->{contents_search_binary_files}); + + $instance->{mtn}->get_file(\$data, $entry->{file_id}) + if (! defined($data)); + next if ($data !~ m/$contents_re/); + } + } + + } + + # If we have got this far then it is a match. + + ++ $matches; + $instance->{results_liststore}-> + set($instance->{results_liststore}->append(), + RLS_NAME_COLUMN, $entry->{name}, + RLS_MANIFEST_ENTRY_COLUMN, $entry); + + } + continue + { + if (($counter % 10) == 0) + { + $instance->{appbar}->set_progress_percentage + ($counter / scalar(@$manifest)); + $wm->update_gui(); + } + ++ $counter; + } + + $instance->{stop_button}->set_sensitive(FALSE); + $instance->{stop} = 0; + + $instance->{results_treeview}->scroll_to_point(0, 0); + $instance->{appbar}->set_progress_percentage(0); + $instance->{appbar}->set_status(""); + $wm->update_gui(); + + $instance->{appbar}->pop(); + if ($matches > 0) + { + $instance->{appbar}->set_status(__x("Found {files_found} files", + files_found => $matches)); + } + else + { + $instance->{appbar}->set_status(__("Nothing found")); + } + $wm->make_busy($instance, 0); + +} +# +############################################################################## +# +# Routine - results_treeview_cursor_changed_cb +# +# Description - Callback routine called when the user selects an entry in +# the results treeview in a find files window. +# +# Data - $widget : The widget object that received the signal. +# $instance : The window instance that is associated with +# this widget. +# +############################################################################## + + + +sub results_treeview_cursor_changed_cb($$) +{ + + my($widget, $instance) = @_; + + return if ($instance->{in_cb}); + local $instance->{in_cb} = 1; + + my $manifest_entry; + + # Get the manifest entry details for the item that was selected. + + $widget->get_selection()->selected_foreach + (sub { + my($model, $path, $iter) = @_; + $manifest_entry = $model->get($iter, RLS_MANIFEST_ENTRY_COLUMN); + }); + + if (defined($manifest_entry)) + { + my($author, + $file_id, + $last_changed_revision, + $last_update); + if ($manifest_entry->{type} eq "file") + { + if (! exists($manifest_entry->{author})) + { + get_file_details($instance->{mtn}, + $instance->{revision_id}, + $manifest_entry->{name}, + \$author, + \$last_update, + \$last_changed_revision); + $manifest_entry->{author} = $author; + $manifest_entry->{last_changed_revision} = + $last_changed_revision; + $manifest_entry->{last_update} = $last_update; + } + else + { + $author = $manifest_entry->{author}; + $last_changed_revision = + $manifest_entry->{last_changed_revision}; + $last_update = $manifest_entry->{last_update}; + } + $file_id = $manifest_entry->{file_id}; + $last_update =~ s/T/ /o; + } + else + { + $author = $file_id = $last_changed_revision = $last_update = ""; + } + set_label_value($instance->{author_value_label}, $author); + set_label_value($instance->{file_id_value_label}, $file_id); + set_label_value($instance->{last_update_value_label}, $last_update); + set_label_value($instance->{file_revision_id_value_label}, + $last_changed_revision); + } + +} +# +############################################################################## +# +# Routine - results_treeview_row_activated_cb +# +# Description - Callback routine called when the user double clicks on an +# entry in the results treeview in a find files window. +# +# Data - $widget : The widget object that received the +# signal. +# $tree_path : A Gtk2::TreePath object for the +# selected item. +# $tree_view_column : A Gtk2::TreeViewColumn object for the +# selected item. +# $instance : The window instance that is associated +# with this widget. +# +############################################################################## + + + +sub results_treeview_row_activated_cb($$$$) +{ + + my($widget, $tree_path, $tree_view_column, $instance) = @_; + + return if ($instance->{in_cb}); + local $instance->{in_cb} = 1; + + my $manifest_entry; + + # Get the manifest entry details for the item that was double-clicked. + + $widget->get_selection()->selected_foreach + (sub { + my($model, $path, $iter) = @_; + $manifest_entry = $model->get($iter, RLS_MANIFEST_ENTRY_COLUMN); + }); + + if (defined($manifest_entry)) + { + + my($branch, + @certs_list); + + # First find out what branch the revision is on (take the first one). + + $instance->{mtn}->certs(address@hidden, $instance->{revision_id}); + $branch = ""; + foreach my $cert (@certs_list) + { + if ($cert->{name} eq "branch") + { + $branch = $cert->{value}; + last; + } + } + + # Either display the file or the directory depending upon the entry's + # type. + + if ($manifest_entry->{type} eq "file") + { + my($dir, + $file); + $dir = dirname($manifest_entry->{name}); + $dir = "" if ($dir eq "."); + $file = basename($manifest_entry->{name}); + get_browser_window($instance->{mtn}, + $branch, + $instance->{revision_id}, + $dir, + $file); + } + else + { + get_browser_window($instance->{mtn}, + $branch, + $instance->{revision_id}, + $manifest_entry->{name}); + } + + } + +} +# +############################################################################## +# +# Routine - get_find_files_window +# +# Description - Creates or prepares an existing find files window for use. +# +# Data - Return Value : A reference to the newly created or unused +# find files instance record. +# +############################################################################## + + + +sub get_find_files_window() +{ + + my $instance; + my $window_type = "find_files_window"; + my $wm = WindowManager->instance(); + + # Create a new find files window if an unused one wasn't found, otherwise + # reuse an existing unused one. + + if (! defined($instance = $wm->find_unused($window_type))) + { + + my($renderer, + $tv_column); + + $instance = {}; + $instance->{glade} = Gtk2::GladeXML->new($glade_file, $window_type); + + # Flag to stop recursive calling of callbacks. + + $instance->{in_cb} = 0; + + # Connect Glade registered signal handlers. + + glade_signal_autoconnect($instance->{glade}, $instance); + + # Get the widgets that we are interested in. + + $instance->{window} = $instance->{glade}->get_widget($window_type); + foreach my $widget ("appbar", + "execute_button", + "stop_button", + + "searching_from_value_label", + "files_named_comboboxentry", + "name_case_sensitive_checkbutton", + "search_subdirectories_checkbutton", + + "files_containing_comboboxentry", + "contents_case_sensitive_checkbutton", + "regular_expression_checkbutton", + "search_binary_files_checkbutton", + + "date_range_checkbutton", + "between_range_radiobutton", + "older_date_dateedit", + "and_label", + "younger_date_dateedit", + "during_range_radiobutton", + "time_spinbutton", + "time_units_combobox", + "size_comparitor_combobox", + "size_spinbutton", + "size_units_combobox", + "modified_by_comboboxentry", + + "results_scrolledwindow", + "results_treeview", + "author_value_label", + "file_id_value_label", + "last_update_value_label", + "file_revision_id_value_label") + { + $instance->{$widget} = $instance->{glade}->get_widget($widget); + } + + # Setup widget sensitivity groups. + + $instance->{date_sensitive_group} = []; + foreach my $widget ("between_range_radiobutton", + "older_date_dateedit", + "and_label", + "younger_date_dateedit", + "during_range_radiobutton", + "time_spinbutton", + "time_units_combobox") + { + push(@{$instance->{date_sensitive_group}}, $instance->{$widget}); + } + $instance->{between_dates_sensitive_group} = []; + foreach my $widget ("older_date_dateedit", + "and_label", + "younger_date_dateedit") + { + push(@{$instance->{between_dates_sensitive_group}}, + $instance->{$widget}); + } + $instance->{during_dates_sensitive_group} = []; + foreach my $widget ("time_spinbutton", "time_units_combobox") + { + push(@{$instance->{during_dates_sensitive_group}}, + $instance->{$widget}); + } + $instance->{size_sensitive_group} = []; + foreach my $widget ("size_spinbutton", "size_units_combobox") + { + push(@{$instance->{size_sensitive_group}}, $instance->{$widget}); + } + + # Setup the find files callbacks. + + $instance->{window}->signal_connect + ("delete_event", + sub { + my($widget, $event, $instance) = @_; + return TRUE if ($instance->{in_cb}); + local $instance->{in_cb} = 1; + $widget->hide(); + $instance->{manifest} = undef; + $instance->{mtn} = undef; + $instance->{results_liststore}->clear(); + return TRUE; + }, + $instance); + $instance->{stop_button}->signal_connect + ("clicked", sub { $_[1]->{stop} = 1; }, $instance); + + # Setup the comboboxes. + + $instance->{files_named_comboboxentry}-> + set_model(Gtk2::ListStore->new("Glib::String")); + $instance->{files_named_comboboxentry}->set_text_column(0); + $instance->{files_named_history} = []; + $instance->{files_containing_comboboxentry}-> + set_model(Gtk2::ListStore->new("Glib::String")); + $instance->{files_containing_comboboxentry}->set_text_column(0); + $instance->{files_containing_history} = []; + $instance->{modified_by_comboboxentry}-> + set_model(Gtk2::ListStore->new("Glib::String")); + $instance->{modified_by_comboboxentry}->set_text_column(0); + $instance->{modified_by_history} = []; + $instance->{size_comparitor_combobox}->set_active(CMP_ANY_SIZE); + $instance->{size_units_combobox}->set_active(SIZE_KB); + $instance->{time_units_combobox}->set_active(DURATION_DAYS); + + # Setup the results list browser. + + $instance->{results_liststore} = Gtk2::ListStore->new("Glib::String", + "Glib::Scalar"); + $instance->{results_treeview}-> + set_model($instance->{results_liststore}); + $tv_column = Gtk2::TreeViewColumn->new(); + $tv_column->set_sort_column_id(0); + $renderer = Gtk2::CellRendererText->new(); + $tv_column->pack_start($renderer, FALSE); + $tv_column->set_attributes($renderer, "text" => 0); + $instance->{results_treeview}->append_column($tv_column); + $instance->{results_treeview}->set_search_column(0); + + # Disable the approprate widgets by default. + + for my $widget (@{$instance->{date_sensitive_group}}, + @{$instance->{size_sensitive_group}}) + { + $widget->set_sensitive(FALSE); + } + + # Register the window for management. + + $wm->manage($instance, + $window_type, + $instance->{window}, + $instance->{stop_button}); + + } + else + { + + my($height, + $width); + + $instance->{in_cb} = 0; + local $instance->{in_cb} = 1; + ($width, $height) = $instance->{window}->get_default_size(); + $instance->{window}->resize($width, $height); + $instance->{stop_button}->set_sensitive(FALSE); + $instance->{appbar}->set_progress_percentage(0); + $instance->{appbar}->clear_stack(); + + } + + $instance->{stop} = 0; + $instance->{results_liststore}->clear(); + set_label_value($instance->{author_value_label}, ""); + set_label_value($instance->{file_id_value_label}, ""); + set_label_value($instance->{last_update_value_label}, ""); + set_label_value($instance->{file_revision_id_value_label}, ""); + + return $instance; + +} +# +############################################################################## +# +# Routine - validate_query +# +# Description - Check the specified query record, making sure it is valid. +# +# Data - $instance : The associated window instance. +# $query : The query record that is to be validated. +# Return Value : True on success, otherwise false on failure. +# +############################################################################## + + + +sub validate_query($$) +{ + + my($instance, $query) = @_; + + my($re_text); + + # Check that the file name glob is valid. + + $re_text = file_glob_to_regexp($query->{file_glob}); + eval + { + qr/$re_text/; + }; + if ($@ ne "") + { + my $dialog = Gtk2::MessageDialog->new + ($instance->{window}, + ["modal"], + "warning", + "close", + __x("`{pattern}' is an invalid\nfile name pattern.", + pattern => $query->{file_glob})); + $dialog->run(); + $dialog->destroy(); + return; + } + + # Check that the search pattern is valid. + + if ($query->{contents_pattern_is_regexp}) + { + $re_text = file_glob_to_regexp($query->{contents_pattern}); + eval + { + qr/$re_text/; + }; + if ($@ ne "") + { + my $dialog = Gtk2::MessageDialog->new + ($instance->{window}, + ["modal"], + "warning", + "close", + __x("`{pattern}' is an invalid\ncontent search pattern.", + pattern => $query->{contents_pattern})); + $dialog->run(); + $dialog->destroy(); + return; + } + } + + # Check that any date range is the right way around. + + if (exists($query->{older_date}) + && $query->{older_date} ge $query->{younger_date}) + { + my $dialog = Gtk2::MessageDialog->new + ($instance->{window}, + ["modal"], + "warning", + "close", + __("The `between' dates are either\n") + . __("the same or the wrong way round.")); + $dialog->run(); + $dialog->destroy(); + return; + } + + # Check that the duration period is not too large. + + if (exists($query->{period})) + { + my($month, $year) = (localtime())[4, 5]; + if ($query->{period_units} == DURATION_MONTHS + && $query->{period} > ((($year - 70) * 12) + $month)) + { + my $dialog = Gtk2::MessageDialog->new + ($instance->{window}, + ["modal"], + "warning", + "close", + __x("A duration of {months} months is too long.", + months => $query->{period})); + $dialog->run(); + $dialog->destroy(); + return; + } + elsif ($query->{period_units} == DURATION_YEARS + && $query->{period} > ($year - 70)) + { + my $dialog = Gtk2::MessageDialog->new + ($instance->{window}, + ["modal"], + "warning", + "close", + __x("A duration of {years} years is too long.", + years => $query->{period})); + $dialog->run(); + $dialog->destroy(); + return; + } + } + + return 1; + +} +# +############################################################################## +# +# Routine - update_comboxentries_history +# +# Description - Update all the histories for every comboboxentry widget in +# a in a find files window. +# +# Data - $instance : The associated window instance. +# $query : The query record containing what was saved from +# the GUI. +# +############################################################################## + + + +sub update_comboxentries_history($$) +{ + + my($instance, $query) = @_; + + my $found; + + # Update the comboxentries histories. + + for my $record ({widget => $instance->{files_named_comboboxentry}, + history => $instance->{files_named_history}, + value => $query->{file_glob}}, + {widget => $instance->{files_containing_comboboxentry}, + history => $instance->{files_containing_history}, + value => $query->{contents_pattern}}, + {widget => $instance->{modified_by_comboboxentry}, + history => $instance->{modified_by_history}, + value => $query->{modified_by}}) + { + $found = 0; + foreach my $entry (@{$record->{history}}) + { + if ($entry eq $record->{value}) + { + $found = 1; + last; + } + } + if (! $found) + { + if (unshift(@{$record->{history}}, $record->{value}) > 20) + { + pop(@{$record->{history}}); + } + $record->{widget}->get_model()->clear(); + foreach my $entry (@{$record->{history}}) + { + $record->{widget}->append_text($entry); + } + } + } + +} +# +############################################################################## +# +# Routine - save_query_from_gui +# +# Description - Saves the query information from the find files window into +# a record. +# +# Data - $instance : The associated window instance. +# Return Value : A reference to the newly created query +# record. +# +############################################################################## + + + +sub save_query_from_gui($) +{ + + my $instance = $_[0]; + + my %query; + + # Do the name page. + + $query{file_glob} = + $instance->{files_named_comboboxentry}->child()->get_text(); + $query{file_glob_case_sensitive} = + $instance->{name_case_sensitive_checkbutton}->get_active() ? 1 : 0; + $query{file_glob_search_subdirectories} = + $instance->{search_subdirectories_checkbutton}->get_active() ? 1 : 0; + + # Do the contents page. + + $query{contents_pattern} = + $instance->{files_containing_comboboxentry}->child()->get_text(); + $query{contents_case_sensitive} = + $instance->{contents_case_sensitive_checkbutton}->get_active() ? 1 : 0; + $query{contents_pattern_is_regexp} = + $instance->{regular_expression_checkbutton}->get_active() ? 1 : 0; + $query{contents_search_binary_files} = + $instance->{search_binary_files_checkbutton}->get_active() ? 1 : 0; + + # Do the properties page. + + if ($instance->{date_range_checkbutton}->get_active()) + { + if ($instance->{between_range_radiobutton}->get_active()) + { + $query{older_date} = + strftime("%Y-%m-%dT%H:%M:%S", + localtime($instance->{older_date_dateedit}-> + get_time())); + $query{younger_date} = + strftime("%Y-%m-%dT%H:%M:%S", + localtime($instance->{younger_date_dateedit}-> + get_time())); + } + else + { + $query{period} = + $instance->{time_spinbutton}->get_value_as_int(); + $query{period_units} = + $instance->{time_units_combobox}->get_active(); + } + } + if ($instance->{size_comparitor_combobox}->get_active() != CMP_ANY_SIZE) + { + $query{file_size} = $instance->{size_spinbutton}->get_value_as_int(); + $query{file_size_operator} = + $instance->{size_comparitor_combobox}->get_active(); + $query{file_size_units} = + $instance->{size_units_combobox}->get_active(); + } + $query{modified_by} = + $instance->{modified_by_comboboxentry}->child()->get_text(); + + return \%query; + +} + +1; ============================================================ --- AdvancedFind.pm 9e7ed7872bbe9dd29d712fb54727bae6af7be4c2 +++ AdvancedFind.pm d62fc3a65a6f7c361800185d8907280fefe0dd75 @@ -43,6 +43,7 @@ use strict; require 5.008; use strict; +use warnings; # ***** FUNCTIONAL PROTOTYPES ***** @@ -764,9 +765,13 @@ sub update_advanced_find_state($$) foreach my $branch (@branch_list) { $advanced_find->{branch_comboboxentry}->append_text($branch); - $advanced_find->{appbar}->set_progress_percentage - ($counter ++ / scalar(@branch_list)); - $wm->update_gui(); + if (($counter % 10) == 0) + { + $advanced_find->{appbar}->set_progress_percentage + ($counter / scalar(@branch_list)); + $wm->update_gui(); + } + ++ $counter; } $advanced_find->{branch_comboboxentry}->child()-> set_text($advanced_find->{branch_combo_details}->{value}); @@ -822,9 +827,13 @@ sub update_advanced_find_state($$) foreach my $revision (@revision_list) { $advanced_find->{revision_comboboxentry}->append_text($revision); - $advanced_find->{appbar}->set_progress_percentage - ($counter ++ / scalar(@revision_list)); - $wm->update_gui(); + if (($counter % 10) == 0) + { + $advanced_find->{appbar}->set_progress_percentage + ($counter / scalar(@revision_list)); + $wm->update_gui(); + } + ++ $counter; } $advanced_find->{revision_comboboxentry}->child()-> set_text($advanced_find->{revision_combo_details}->{value}); @@ -951,9 +960,13 @@ sub update_advanced_find_state($$) $advanced_find->{revisions_liststore}-> set($advanced_find->{revisions_liststore}->append(), 0, $item); - $advanced_find->{appbar}->set_progress_percentage - ($counter ++ / scalar(@revision_ids)); - $wm->update_gui(); + if (($counter % 10) == 0) + { + $advanced_find->{appbar}->set_progress_percentage + ($counter / scalar(@revision_ids)); + $wm->update_gui(); + } + ++ $counter; last if ($advanced_find->{stop}); } $advanced_find->{stop_button}->set_sensitive(FALSE); ============================================================ --- Annotate.pm edc84764f8d6d85efdb259014f3a2660425fa679 +++ Annotate.pm 96f269e7203303f964dfb0fd024a3f6b55104591 @@ -43,6 +43,7 @@ use strict; require 5.008; use strict; +use warnings; # ***** FUNCTIONAL PROTOTYPES ***** ============================================================ --- ChangeLog.pm f9ba345d6a2d3a9fd104b35ce36ef9df8b04d8a2 +++ ChangeLog.pm 1bc50a48e82d47e18f69a426dcf068ecfa9cbb78 @@ -43,6 +43,7 @@ use strict; require 5.008; use strict; +use warnings; # ***** FUNCTIONAL PROTOTYPES ***** ============================================================ --- ComboAutoCompletion.pm 6b3d8c390427cc6638b69aafcc01c1433ec543d7 +++ ComboAutoCompletion.pm e64c089c106406ce01bd742aa45cf28a164aebea @@ -44,6 +44,7 @@ use strict; require 5.008; use strict; +use warnings; # ***** FUNCTIONAL PROTOTYPES ***** ============================================================ --- Completion.pm 71827654ac9917a8031920fc50bb877f660714d6 +++ Completion.pm d416a066aa7f7ea3c953f07d97b6e5d7a1f3cc05 @@ -47,8 +47,9 @@ require 5.008; require 5.008; +use integer; use strict; -use integer; +use warnings; # ***** PACKAGE INFORMATION ***** ============================================================ --- FindText.pm 7eb1fe25f19787ddc1795556f571de6bb0d53b64 +++ FindText.pm 6b84fd52375956b82047faa0b453a36646b8f75b @@ -43,6 +43,7 @@ use strict; require 5.008; use strict; +use warnings; # ***** GLOBAL DATA DECLARATIONS ***** ============================================================ --- Globals.pm 210c3971b3ca55744f8e3ae4c40f42395e326d77 +++ Globals.pm 671f3b14c85fa6f451133c775f43160a950fc834 @@ -49,6 +49,7 @@ use strict; require 5.008; use strict; +use warnings; # ***** GLOBAL DATA DECLARATIONS ***** ============================================================ --- History.pm 06156650d4157a98ad7b2d627b2f9da2d58c83ac +++ History.pm 591b6d22fc8b0f99ea5127f90a2087171f576cb6 @@ -43,6 +43,8 @@ use strict; require 5.008; use strict; +use warnings; +no warnings qw(recursion); # ***** GLOBAL DATA DECLARATIONS ***** @@ -314,7 +316,7 @@ sub display_file_change_history($$$) $instance->{first_revision_id} = ""; $instance->{second_revision_id} = ""; $instance->{window}->set_title(__x("File History For {file}", - file=> $instance->{file_name})); + file => $instance->{file_name})); $instance->{history_label}->set_markup(__("File History")); $instance->{window}->show_all(); @@ -350,13 +352,11 @@ sub display_file_change_history($$$) $instance->{appbar}->set_progress_percentage(0); $instance->{appbar}->set_status(__("Displaying file history")); $wm->update_gui(); - $counter = 0; + $counter = 1; $instance->{history_buffer}->set_text(""); for my $revision_id (@{$instance->{history}}) { - ++ $counter; - # Print out the revision summary. $instance->{mtn}->certs(address@hidden, $revision_id); @@ -449,9 +449,13 @@ sub display_file_change_history($$$) insert($instance->{history_buffer}->get_end_iter(), "\n"); } - $instance->{appbar}->set_progress_percentage - ($counter / scalar(@{$instance->{history}})); - $wm->update_gui(); + if (($counter % 10) == 0) + { + $instance->{appbar}->set_progress_percentage + ($counter / scalar(@{$instance->{history}})); + $wm->update_gui(); + } + ++ $counter; } ============================================================ --- Preferences.pm 777f8bf59768c400f654b5f4565a7d48dc46791d +++ Preferences.pm 15134271c380429b82b4ec8cbb44eea27d9795f2 @@ -43,6 +43,7 @@ use strict; require 5.008; use strict; +use warnings; # ***** GLOBAL DATA DECLARATIONS ***** @@ -129,7 +130,6 @@ sub defaults_button_clicked_cb($$); sub add_mime_type_button_clicked_cb($$); sub database_browse_button_clicked_cb($$); sub defaults_button_clicked_cb($$); -sub file_glob_to_regexp($); sub file_name_pattern_entry_changed_cb($$); sub file_name_patterns_treeview_cursor_changed_cb($$); sub get_preferences_window($$); @@ -838,7 +838,7 @@ sub add_file_name_pattern_button_clicked "warning", "close", __x("`{pattern}' is an invalid\nfile name pattern.", - pattern=> $pattern)); + pattern => $pattern)); $dialog->run(); $dialog->destroy(); return; @@ -884,7 +884,7 @@ sub add_file_name_pattern_button_clicked # # Routine - remove_file_name_pattern_button_clicked_cb # -# Description - Callback routine called when the user clicks on the add +# Description - Callback routine called when the user clicks on the remove # file name pattern button in the preferences window. # # Data - $widget : The widget object that received the signal. @@ -1662,77 +1662,6 @@ sub initialise_mime_info_table() # ############################################################################## # -# Routine - file_glob_to_regexp -# -# Description - Converts the specified string containing a file name style -# glob into a regular expression. -# -# Data - $file_glob : The file name wildcard that is to be -# converted. -# Return Value : The resultant regular expression string. -# -############################################################################## - - - -sub file_glob_to_regexp($) -{ - - my $file_glob = $_[0]; - - my($escaping, - $first, - $re_text); - - $escaping = 0; - $first = 1; - foreach my $char (split(//, $file_glob)) - { - if ($first) - { - $re_text .= "(?=[^\\.])" unless $char eq "."; - $first = 0; - } - if ("address@hidden()|" =~ m/\Q$char\E/) - { - $re_text .= "\\" . $char; - } - elsif ($char eq "*") - { - $re_text .= $escaping ? "\\*" : ".*"; - } - elsif ($char eq "?") - { - $re_text .= $escaping ? "\\?" : "."; - } - elsif ($char eq "\\") - { - if ($escaping) - { - $re_text .= "\\\\"; - $escaping = 0; - } - else - { - $escaping = 1; - } - } - else - { - $re_text .= "\\" if ($escaping && $char eq "["); - $re_text .= $char; - $escaping = 0; - } - } - - $re_text .= "\$"; - - return $re_text; - -} -# -############################################################################## -# # Routine - home_dir # # Description - Returns the user's home directory. ============================================================ --- Utilities.pm 6271d135e4afb4b089282c157b70dfe11fff7a9d +++ Utilities.pm ac91364337013be65703eebc6dd492b2841d6a11 @@ -43,6 +43,7 @@ use strict; require 5.008; use strict; +use warnings; # ***** FUNCTIONAL PROTOTYPES ***** @@ -51,9 +52,11 @@ sub data_is_binary($); sub colour_to_string($); sub create_format_tags($); sub data_is_binary($); +sub file_glob_to_regexp($); sub generate_tmp_path($); sub get_branch_revisions($$$$$); sub get_dir_contents($$$); +sub get_file_details($$$$$$); sub get_revision_ids($$); sub glade_signal_autoconnect($$); sub hex_dump($); @@ -285,11 +288,9 @@ sub get_dir_contents($$$) my($entry, $extract_re, - $i, $match_re, $name); - $i = 0; if ($path eq "") { $match_re = qr/^[^\/]+$/; @@ -306,8 +307,7 @@ sub get_dir_contents($$$) if ($entry->{name} =~ m/$match_re/) { ($name) = ($entry->{name} =~ m/$extract_re/); - $$result[$i ++] = {manifest_entry => $entry, - name => $name}; + push(@$result, {manifest_entry => $entry, name => $name}); } } @@ -713,6 +713,64 @@ sub get_branch_revisions($$$$$) # ############################################################################## # +# Routine - get_file_details +# +# Description - Get the details of the specified file. +# +# Data - $mtn : The Monotone database handle that +# is to be used. +# $revision_id : The revision id from where the +# search for the latest file update +# is to start, working backwards. +# $file_name : The full path name of the file. +# $author : A reference to the variable that +# is to contain the author's +# identity. +# $last_update : A reference to the variable that +# is to contain the last updated +# date for the file. +# $last_changed_revision : A reference to the variable that +# is to contain the revision id on +# which the file was last updated. +# +############################################################################## + + + +sub get_file_details($$$$$$) +{ + + my($mtn, + $revision_id, + $file_name, + $author, + $last_update, + $last_changed_revision) = @_; + + my(@certs_list, + @revision_list); + + $mtn->get_content_changed(address@hidden, $revision_id, $file_name); + $$last_changed_revision = $revision_list[0]; + $mtn->certs(address@hidden, $revision_list[0]); + $$author = $$last_update = ""; + foreach my $cert (@certs_list) + { + if ($cert->{name} eq "author") + { + $$author = $cert->{value}; + } + if ($cert->{name} eq "date") + { + $$last_update = $cert->{value}; + } + last if ($$author ne "" && $$last_update ne ""); + } + +} +# +############################################################################## +# # Routine - get_revision_ids # # Description - Return the currently selected revision id, whether this is @@ -750,6 +808,77 @@ sub get_revision_ids($$) # ############################################################################## # +# Routine - file_glob_to_regexp +# +# Description - Converts the specified string containing a file name style +# glob into a regular expression. +# +# Data - $file_glob : The file name wildcard that is to be +# converted. +# Return Value : The resultant regular expression string. +# +############################################################################## + + + +sub file_glob_to_regexp($) +{ + + my $file_glob = $_[0]; + + my($escaping, + $first, + $re_text); + + $escaping = 0; + $first = 1; + foreach my $char (split(//, $file_glob)) + { + if ($first) + { + $re_text .= "(?=[^\\.])" unless $char eq "."; + $first = 0; + } + if ("address@hidden()|" =~ m/\Q$char\E/) + { + $re_text .= "\\" . $char; + } + elsif ($char eq "*") + { + $re_text .= $escaping ? "\\*" : ".*"; + } + elsif ($char eq "?") + { + $re_text .= $escaping ? "\\?" : "."; + } + elsif ($char eq "\\") + { + if ($escaping) + { + $re_text .= "\\\\"; + $escaping = 0; + } + else + { + $escaping = 1; + } + } + else + { + $re_text .= "\\" if ($escaping && $char eq "["); + $re_text .= $char; + $escaping = 0; + } + } + + $re_text .= "\$"; + + return $re_text; + +} +# +############################################################################## +# # Routine - create_format_tags # # Description - Creates the Gtk2::TextBuffer tags that are used to pretty @@ -903,12 +1032,13 @@ sub data_is_binary($) my $data = $_[0]; - my $non_printable; + my($length, + $non_printable); + $length = length($$data); $non_printable = grep(/[^[:print:][:space:]]/, split(//, $$data)); - return 1 if (((100 * $non_printable) / length($$data)) > 20); - + return 1 if ($length > 0 && ((100 * $non_printable) / $length) > 20); return; } ============================================================ --- WindowManager.pm 72764d5731e5cf3bf95be105da2fca5b15089fb2 +++ WindowManager.pm 2f164203f11d37ea14d264041fd83c7d9e44aa6a @@ -47,8 +47,9 @@ require 5.008; require 5.008; +use integer; use strict; -use integer; +use warnings; # ***** REQUIRED PACKAGES ***** ============================================================ --- mtn-browse 186fceb438602cbd85c940611e2083ffbd795358 +++ mtn-browse c4da8275bcc59dac9bd253aae27e1a380be8aa4a @@ -1,5 +1,4 @@ -#!/usr/bin/perl -W -##!/usr/bin/perl -w +#!/usr/bin/perl ############################################################################## # # File Name - mtn-browse @@ -50,6 +49,7 @@ use strict; } use lib LIB_PATH; use strict; +use warnings; # ***** REQUIRED PACKAGES ***** @@ -73,6 +73,7 @@ use Text::Tabs; use POSIX qw(:errno_h :locale_h :sys_wait_h strftime); use Symbol qw(gensym); use Text::Tabs; +use Time::Local; # Monotone AutomateStdio module. @@ -86,6 +87,7 @@ use Completion; use ChangeLog; use ComboAutoCompletion; use Completion; +use FindFiles; use FindText; use History; use Preferences; @@ -122,6 +124,7 @@ sub file_change_history_button_clicked_c sub directory_up_button_clicked_cb($$); sub display_file($$); sub file_change_history_button_clicked_cb($$); +sub find_files_button_clicked_cb($$); sub get_browser_window(;$$$$$); sub help_toolbutton_clicked_cb($$); sub main_window_delete_event_cb($$$); @@ -917,6 +920,36 @@ sub directory_up_button_clicked_cb($$) # ############################################################################## # +# Routine - find_files_button_clicked_cb +# +# Description - Callback routine called when the user clicks on the find +# files 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 find_files_button_clicked_cb($$) +{ + + my($widget, $browser) = @_; + + return if ($browser->{in_cb}); + local $browser->{in_cb} = 1; + + display_find_files($browser->{mtn}, + $browser->{revision_combo_details}->{value}, + $browser->{manifest}, + $browser->{directory_combo_details}->{value}); + +} +# +############################################################################## +# # Routine - search_text_button_clicked_cb # # Description - Callback routine called when the user clicks on the search @@ -1427,6 +1460,7 @@ sub get_browser_window(;$$$$$) "tagged_checkbutton", "directory_comboboxentry", "directory_up_button", + "find_files_button", "manifest_browser_treeview", "file_view_scrolledwindow", "file_name_value_label", @@ -1444,13 +1478,13 @@ sub get_browser_window(;$$$$$) # Setup button sensitivity groups. - $browser->{text_file_sensitive_group} = (); + $browser->{text_file_sensitive_group} = []; foreach my $item ("search_text", "annotate") { push(@{$browser->{text_file_sensitive_group}}, $browser->{glade}->get_widget($item . "_button")); } - $browser->{revision_sensitive_group} = (); + $browser->{revision_sensitive_group} = []; foreach my $item ("revision_change_history", "revision_change_log") { push(@{$browser->{revision_sensitive_group}}, @@ -1761,9 +1795,13 @@ sub update_browser_state($$) foreach my $branch (@branch_list) { $browser->{branch_comboboxentry}->append_text($branch); - $browser->{appbar}->set_progress_percentage - ($counter ++ / scalar(@branch_list)); - $wm->update_gui(); + if (($counter % 10) == 0) + { + $browser->{appbar}->set_progress_percentage + ($counter / scalar(@branch_list)); + $wm->update_gui(); + } + ++ $counter; } $browser->{branch_comboboxentry}->child()-> set_text($browser->{branch_combo_details}->{value}); @@ -1818,9 +1856,13 @@ sub update_browser_state($$) foreach my $revision (@revision_list) { $browser->{revision_comboboxentry}->append_text($revision); - $browser->{appbar}->set_progress_percentage - ($counter ++ / scalar(@revision_list)); - $wm->update_gui(); + if (($counter % 10) == 0) + { + $browser->{appbar}->set_progress_percentage + ($counter / scalar(@revision_list)); + $wm->update_gui(); + } + ++ $counter; } $browser->{revision_comboboxentry}->child()-> set_text($browser->{revision_combo_details}->{value}); @@ -1940,9 +1982,13 @@ sub update_browser_state($$) foreach my $item (@directory_list) { $browser->{directory_comboboxentry}->append_text($item); - $browser->{appbar}->set_progress_percentage - ($counter ++ / scalar(@directory_list)); - $wm->update_gui(); + if (($counter % 10) == 0) + { + $browser->{appbar}->set_progress_percentage + ($counter / scalar(@directory_list)); + $wm->update_gui(); + } + ++ $counter; } $browser->{directory_comboboxentry}->child()-> set_text($browser->{directory_combo_details}->{value}); @@ -1951,7 +1997,8 @@ sub update_browser_state($$) foreach my $widget (@{$browser->{revision_sensitive_group}}) { $widget-> - set_sensitive($browser->{revision_combo_details}->{complete}); + set_sensitive($browser->{revision_combo_details}->{complete} + ? TRUE : FALSE); } $wm->update_gui(); @@ -1963,27 +2010,32 @@ sub update_browser_state($$) { my($author, - @certs_list, $counter, @directory_entry_list, $last_update, @revision_ids, - @revision_list, $taking_our_time); # Reset the manifest tree view. $browser->{manifest_liststore}->clear(); - # Get the contents of the new directory. + # If we are currently at a valid directory then get its contents and + # enable the find files button. - if ($browser->{directory_combo_details}->{complete} - || $browser->{directory_combo_details}->{value} eq "") + if ($browser->{revision_combo_details}->{complete} + && ($browser->{directory_combo_details}->{complete} + || $browser->{directory_combo_details}->{value} eq "")) { get_dir_contents($browser->{directory_combo_details}->{value}, $browser->{manifest}, address@hidden); + $browser->{find_files_button}->set_sensitive(TRUE); } + else + { + $browser->{find_files_button}->set_sensitive(FALSE); + } # Disable the directory up button if we are already at the top level, # otherwise make sure it is enabled. @@ -2010,36 +2062,22 @@ sub update_browser_state($$) if (! exists($item->{manifest_entry}->{author})) { $taking_our_time = 1; - $browser->{mtn}->get_content_changed - (address@hidden, - $revision_ids[0], - $item->{manifest_entry}->{name}); - $item->{manifest_entry}->{last_changed_revision} = - $revision_list[0]; - $browser->{mtn}->certs(address@hidden, $revision_list[0]); - $author = $last_update = ""; - foreach my $cert (@certs_list) - { - if ($cert->{name} eq "author") - { - $author = $cert->{value}; - $item->{manifest_entry}->{author} = $author; - } - if ($cert->{name} eq "date") - { - $last_update = $cert->{value}; - $last_update =~ s/T/ /o; - $item->{manifest_entry}->{last_update} = - $last_update; - } - last if ($author ne "" && $last_update ne ""); - } + get_file_details($browser->{mtn}, + $revision_ids[0], + $item->{manifest_entry}->{name}, + \$author, + \$last_update, + \$item->{manifest_entry}-> + {last_changed_revision}); + $item->{manifest_entry}->{author} = $author; + $item->{manifest_entry}->{last_update} = $last_update; } else { $author = $item->{manifest_entry}->{author}; $last_update = $item->{manifest_entry}->{last_update}; } + $last_update =~ s/T/ /o; } else { @@ -2068,7 +2106,7 @@ sub update_browser_state($$) $browser->{file_being_viewed_preset_value} = ""; } - if ($taking_our_time) + if ($taking_our_time && ($counter % 10) == 0) { $browser->{appbar}->set_progress_percentage ($counter / scalar(@directory_entry_list)); @@ -2106,7 +2144,8 @@ sub update_browser_state($$) ne $manifest_entry->{file_id}) { - my $textual_data; + my($last_update, + $textual_data); # Enable the file buttons, keeping the ones relating to text # files disabled, and reset any associated find text window. @@ -2141,35 +2180,25 @@ sub update_browser_state($$) if (! exists($manifest_entry->{last_changed_revision})) { - my(@certs_list, - @revision_ids, - @revision_list); + my($dummy, + @revision_ids); get_revision_ids($browser, address@hidden); - $browser->{mtn}-> - get_content_changed(address@hidden, - $revision_ids[0], - $manifest_entry->{name}); - $manifest_entry->{last_changed_revision} = - $revision_list[0]; - $browser->{mtn}->certs(address@hidden, $revision_list[0]); - foreach my $cert (@certs_list) - { - if ($cert->{name} eq "date") - { - my $last_update; - $last_update = $cert->{value}; - $last_update =~ s/T/ /o; - $manifest_entry->{last_update} = $last_update; - last; - } - } + get_file_details($browser->{mtn}, + $revision_ids[0], + $manifest_entry->{name}, + \$dummy, + \$manifest_entry->{last_update}, + \$manifest_entry-> + {last_changed_revision}); } + $last_update = $manifest_entry->{last_update}; + $last_update =~ s/T/ /o; set_label_value($browser->{file_name_value_label}, $manifest_entry->{name}); set_label_value($browser->{file_id_value_label}, $manifest_entry->{file_id}); set_label_value($browser->{last_update_value_label}, - $manifest_entry->{last_update}); + $last_update); set_label_value($browser->{file_revision_id_value_label}, $manifest_entry->{last_changed_revision}); } ============================================================ --- mtn-browse.glade ee150cf030015b3f40d78a83daa28bad07269dd1 +++ mtn-browse.glade 91f78642431d06166c66500947afe38933877de6 @@ -64,7 +64,7 @@ - + True gtk-new 1 @@ -102,8 +102,21 @@ True - GNOMEUIINFO_MENU_EXIT_ITEM - + _Quit + True + + + + + True + gtk-quit + 1 + 0.5 + 0.5 + 0 + 0 + + @@ -753,25 +766,67 @@ in Monotone-Viz - + True - Go up one directory level - True - GTK_RELIEF_NONE - True - + False + 0 - + True - gtk-go-up - 4 - 0.5 - 0.5 - 0 - 0 + Go up one directory level + True + GTK_RELIEF_NONE + True + + + + + True + gtk-go-up + 4 + 0.5 + 0.5 + 0 + 0 + + + + 0 + False + False + + + + + True + Find files based on one +or more search criteria + True + GTK_RELIEF_NONE + True + + + + + True + gtk-find + 4 + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + 0 @@ -901,7 +956,7 @@ in Monotone-Viz Name of the file being displayed 1 1 - 0 0 130 10 117 130 + 0 0 118 10 106.2 118 0 0 17 10 15.3 17 @@ -963,7 +1018,7 @@ in Monotone-Viz Date of when file was last changed 1 1 - 0 0 130 10 117 130 + 0 0 118 10 106.2 118 0 0 17 10 15.3 17 @@ -1108,7 +1163,7 @@ updated with respect to this revision

File's unique id in database 1 1 - 0 0 134 10 120.6 134 + 0 0 122 10 109.8 122 0 0 17 10 15.3 17 @@ -1171,7 +1226,7 @@ file was last changed file was last changed 1 1 - 0 0 134 10 120.6 134 + 0 0 122 10 109.8 122 0 0 17 10 15.3 17 @@ -2467,7 +2522,7 @@ entry field if you cannot remember the s True False - Stop displaying the query results + Stop the query True GTK_RELIEF_NONE True @@ -7207,4 +7262,1542 @@ of the command
+ + True + + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + 560 + 500 + True + False + mtn-browse.png + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + + + + True + False + 0 + + + + 5 + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + 5 + True + False + 5 + + + + True + True + True + True + GTK_POS_TOP + False + False + + + + 5 + True + False + 5 + + + + True + 2 + 2 + False + 5 + 5 + + + + True + + + 1 + 2 + 1 + 2 + fill + + + + + + True + Enter the file name pattern +that is to be searched for + True + False + + + + True + Files named: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + + + 0 + 1 + 1 + 2 + fill + fill + + + + + + True + The place in the directory hierarchy +where the search will start from + True + False + + + + True + Searching from: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + + + 0 + 1 + 0 + 1 + fill + fill + + + + + + True + True + GTK_POLICY_NEVER + GTK_POLICY_NEVER + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + 1 + 1 + 0 0 392 10 352.8 392 + 0 0 17 10 15.3 17 + + + + 0 + 0 + True + True + False + + + + 0 + 0 + True + True + + False + False + GTK_JUSTIFY_LEFT + False + True + 0 + 0.5 + 0 + 0 + + + + + 0 + 0 + + + + + + + 1 + 2 + 0 + 1 + fill + + + + + 0 + False + True + + + + + + True + False + 5 + + + + True + Choose whether searches are +to be case sensitive or not + True + Case sensitive + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + + True + Choose whether to search +subdirectories or not + True + Search subdirectories + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + 0 + False + True + + + + + False + True + + + + + + True + <b>Name</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + tab + + + + + + 5 + True + False + 5 + + + + True + False + 5 + + + + True + Enter the text that is to be +searched for inside files + True + False + + + + True + Files containing: + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + True + + + + + + True + + + 0 + True + True + + + + + 0 + False + True + + + + + + True + False + 5 + + + + True + Choose whether searches are +to be case sensitive or not + True + Case sensitive + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + + True + Use regular expression +search patterns + True + Regular expression + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + + True + Search binary files +as well as text files + True + Search binary files + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + 0 + False + False + + + + + False + True + + + + + + True + <b>Contents</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + tab + + + + + + 5 + True + 6 + 5 + False + 5 + 5 + + + + True + Select this mode if you want +to search for files that were +last modified between the +two specified dates + True + between + True + GTK_RELIEF_NORMAL + True + True + False + True + + + + 1 + 2 + 1 + 2 + fill + + + + + + + True + Select files based upon their +last modification date and time + True + Find all files created or modified: + True + GTK_RELIEF_NORMAL + True + False + False + True + + + + 0 + 3 + 0 + 1 + fill + + + + + + + True + Select this mode if you want to +select files last modified within +the last n hours/days/months... + True + during the previous + True + GTK_RELIEF_NORMAL + True + False + False + True + between_range_radiobutton + + + 1 + 2 + 3 + 4 + fill + + + + + + + True + and + False + False + GTK_JUSTIFY_LEFT + False + False + 1 + 0.5 + 0 + 0 + + + 1 + 2 + 2 + 3 + fill + + + + + + + True + Select files based upon their size + True + False + + + + True + File size is: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + + + 0 + 2 + 4 + 5 + fill + fill + + + + + + True + Select files last modified +by the specified user + True + False + + + + True + Files last modified by: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + + + 0 + 2 + 5 + 6 + fill + fill + + + + + + True + + + 2 + 5 + 5 + 6 + fill + + + + + + True + Enter the duration here + True + 1 + 0 + True + GTK_UPDATE_ALWAYS + False + False + 1 1 1000 1 10 10 + + + 2 + 3 + 3 + 4 + + + + + + + True + Enter the file size here + True + 1 + 0 + True + GTK_UPDATE_ALWAYS + False + False + 1 1 10000 1 10 10 + + + 3 + 4 + 4 + 5 + + + + + + + True + Use this to specify the oldest +modification date for your search + True + False + + + + True + GNOME_DATE_EDIT_SHOW_TIME|GNOME_DATE_EDIT_24_HR + 7 + 19 + + + + + 2 + 5 + 1 + 2 + + + + + + + True + Use this to specify the youngest +modification date for your search + True + False + + + + True + GNOME_DATE_EDIT_SHOW_TIME|GNOME_DATE_EDIT_24_HR + 7 + 19 + + + + + 2 + 5 + 2 + 3 + + + + + + + True + The unit of time to be used + True + False + + + + True + Minute(s) +Hour(s) +Day(s) +Month(s) +Year(s) + + + + + 3 + 4 + 3 + 4 + fill + fill + + + + + + True + The type of comparison +to be performed + True + False + + + + True + Any Size +At Least +At Most +Equal To + + + + + + 2 + 3 + 4 + 5 + fill + fill + + + + + + True + The unit of file size to be used + True + False + + + + True + Bytes +KB +MB + + + + + 4 + 5 + 4 + 5 + fill + fill + + + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + 0 + 1 + 1 + 2 + fill + + + + + + False + True + + + + + + True + <b>Properties</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + tab + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + False + Stop finding files + True + GTK_RELIEF_NONE + True + + + + True + gtk-stop + 4 + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + GTK_PACK_END + + + + + + True + Find the files + True + GTK_RELIEF_NONE + True + + + + + True + gtk-execute + 4 + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + GTK_PACK_END + + + + + 0 + False + True + + + + + + + + + + True + <b>Query</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + label_item + + + + + 0 + False + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + 5 + True + False + 5 + + + + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_IN + GTK_CORNER_TOP_LEFT + + + + True + True + False + False + False + True + + + + + + + 0 + True + True + + + + + + True + True + 5 + + + + True + 2 + 2 + False + 0 + 5 + + + + True + True + GTK_POLICY_NEVER + GTK_POLICY_NEVER + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + Name of the file being displayed + 1 + 1 + 0 0 188 10 169.199996948 188 + 0 0 17 10 15.3000001907 17 + + + + 0 + 0 + True + True + False + + + + 0 + 0 + True + True + + False + False + GTK_JUSTIFY_LEFT + False + True + 0 + 0.5 + 0 + 0 + + + + + 0 + 0 + + + + + + + 1 + 2 + 0 + 1 + fill + + + + + + True + True + GTK_POLICY_NEVER + GTK_POLICY_NEVER + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + Date of when file was last changed + 1 + 1 + 0 0 188 10 169.199996948 188 + 0 0 17 10 15.3000001907 17 + + + + 0 + 0 + True + True + False + + + + 0 + 0 + True + True + + False + False + GTK_JUSTIFY_LEFT + False + True + 0 + 0.5 + 0 + 0 + + + + + 0 + 0 + + + + + + + 1 + 2 + 1 + 2 + fill + + + + + + True + Author of the selected file + True + False + + + + True + Author: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + + + 0 + 1 + 0 + 1 + fill + fill + + + + + + True + Time when the selected file was last +updated with respect to this revision + True + False + + + + True + Last update: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + + + 0 + 1 + 1 + 2 + fill + fill + + + + + 0 + True + True + + + + + + True + 2 + 2 + False + 0 + 5 + + + + True + True + GTK_POLICY_NEVER + GTK_POLICY_NEVER + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + File's unique id in database + 1 + 1 + 0 0 192 10 172.800003052 192 + 0 0 17 10 15.3000001907 17 + + + + 0 + 0 + True + True + False + + + + 0 + 0 + True + True + + False + False + GTK_JUSTIFY_LEFT + False + True + 0 + 0.5 + 0 + 0 + + + + + 0 + 0 + + + + + + + 1 + 2 + 0 + 1 + fill + + + + + + True + True + GTK_POLICY_NEVER + GTK_POLICY_NEVER + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + Id of revision when +file was last changed + 1 + 1 + 0 0 192 10 172.800003052 192 + 0 0 17 10 15.3000001907 17 + + + + 0 + 0 + True + True + False + + + + 0 + 0 + True + True + + False + False + GTK_JUSTIFY_LEFT + False + True + 0 + 0.5 + 0 + 0 + + + + + 0 + 0 + + + + + + + 1 + 2 + 1 + 2 + fill + + + + + + True + Id of the selected file + True + False + + + + True + File id: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + + + 0 + 1 + 0 + 1 + fill + fill + + + + + + True + Revision id in which the selected file was +last updated with respect to this revision + True + False + + + + True + Revision id: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + + + 0 + 1 + 1 + 2 + fill + fill + + + + + 0 + True + True + + + + + 0 + False + True + + + + + + + + + + True + <b>Results</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + label_item + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + True + True + True + + + 0 + False + True + + + + + +