📄 viewtopic.pm
字号:
################################################################################ Codestriker: Copyright (c) 2001, 2002 David Sitsky. All rights reserved.# sits@users.sourceforge.net## This program is free software; you can redistribute it and modify it under# the terms of the GPL.# Action object for handling the viewing of a topic.package Codestriker::Action::ViewTopic;use strict;use HTML::Entities ();use Codestriker::Model::Topic;use Codestriker::Model::Comment;use Codestriker::Http::UrlBuilder;use Codestriker::Http::DeltaRenderer;use Codestriker::Repository::RepositoryFactory;use Codestriker::TopicListeners::Manager;# If the input is valid, display the topic.sub process($$$) { my ($type, $http_input, $http_response) = @_; my $query = $http_response->get_query(); my $topicid = $http_input->get('topic'); my $mode = $http_input->get('mode'); my $fview = $http_input->get('fview'); my $tabwidth = $http_input->get('tabwidth'); my $email = $http_input->get('email'); my $feedback = $http_input->get('feedback'); if (Codestriker::Model::Topic::exists($topicid) == 0) { # Topic no longer exists, most likely its been deleted. $http_response->error("Topic no longer exists."); } # Retrieve the appropriate topic details. my $topic = Codestriker::Model::Topic->new($topicid); my $projectid = $topic->{project_id}; # Retrieve the comment details for this topic, firstly determine how # many distinct comment lines are there. my @comments = $topic->read_comments(); my %comment_map = (); foreach my $comment (@comments) { my $key = $comment->{filenumber} . "|" . $comment->{fileline} . "|" . $comment->{filenew}; if (! exists $comment_map{$key}) { $comment_map{$key} = 1; } } # Retrieve the changed files which are a part of this review. my (@filenames, @revisions, @offsets, @binary, @numchanges); $topic->get_filestable( \@filenames, \@revisions, \@offsets, \@binary, \@numchanges); # Retrieve line-by-line versions of the data and description. my @document_description = split /\n/, $topic->{description}; $http_response->generate_header(topic=>$topic, comments=>\@comments, topic_title=>"Topic Text: $topic->{title}", mode=>$mode, tabwidth=>$tabwidth, fview=>$fview, reload=>0, cache=>1); # Retrieve the repository object, if repository functionality is enabled. my $repository; if (scalar(@Codestriker::valid_repositories)) { $repository = Codestriker::Repository::RepositoryFactory->get($topic->{repository}); } else { # Indicate not to activate any repository-related links. $topic->{repository} = ""; } # Create the hash for the template variables. my $vars = {}; $vars->{'feedback'} = $feedback; # Create the necessary template variables for generating the heading part # of the view topic display. # Obtain a new URL builder object. my $url_builder = Codestriker::Http::UrlBuilder->new($query); ProcessTopicHeader($vars, $topic, $url_builder); # Display the "update" message if the topic state has been changed. $vars->{'updated'} = $http_input->get('updated'); $vars->{'rc_ok'} = $Codestriker::OK; $vars->{'rc_stale_version'} = $Codestriker::STALE_VERSION; $vars->{'rc_invalid_topic'} = $Codestriker::INVALID_TOPIC; if ($topic->{bug_ids} ne "") { my @bugs = split ', ', $topic->{bug_ids}; my $bug_string = ""; for (my $i = 0; $i <= $#bugs; $i++) { $bug_string .= $query->a({href=>"$Codestriker::bugtracker$bugs[$i]"}, $bugs[$i]); $bug_string .= ', ' unless ($i == $#bugs); } $vars->{'bug_string'} = $bug_string; } else { $vars->{'bug_string'} = ""; } $vars->{'document_reviewers'} = Codestriker->filter_email($topic->{reviewers}); $vars->{'project_name'} = $topic->{project_name}; $vars->{'number_of_lines'} = $topic->get_topic_size_in_lines(); $vars->{'suggested_topic_size_lines'} = $Codestriker::suggested_topic_size_lines eq "" ? 0 : $Codestriker::suggested_topic_size_lines; # Prepare the data for displaying the state update option. # Make sure the old mode setting is no longer used. if ((! defined $mode) || $mode == $Codestriker::NORMAL_MODE) { $mode = $Codestriker::COLOURED_MODE; } if (! defined $fview) { $fview = $Codestriker::default_file_to_view; if (! defined $fview) { $fview = -1; } } $vars->{'states'} = \@Codestriker::topic_states; $vars->{'default_state'} = $topic->{state}; # Set the description of the topic. my $data = ""; for (my $i = 0; $i <= $#document_description; $i++) { $data .= $document_description[$i] . "\n"; } $vars->{'description'} = $data; # Obtain the link to download the actual document text. $vars->{'download_url'} = $url_builder->download_url(topicid => $topicid, projectid => $projectid); # Obtain the links for the different viewing modes. $vars->{'coloured_mode_url'} = $url_builder->view_url(topicid => $topicid, projectid => $projectid, mode => $Codestriker::COLOURED_MODE, fview => $fview); $vars->{'coloured_mono_mode_url'} = $url_builder->view_url(topicid => $topicid, projectid => $projectid, mode => $Codestriker::COLOURED_MONO_MODE, fview => $fview); # Set template variables relating to coloured mode. if ($mode == $Codestriker::COLOURED_MODE) { $vars->{'mode'} = 'coloured'; } elsif ($mode == $Codestriker::COLOURED_MONO_MODE) { $vars->{'mode'} = 'coloured_mono'; } else { $vars->{'mode'} = 'unknown'; } # Set varibles relating to tab-width setting. my $newtabwidth = ($tabwidth == 4) ? 8 : 4; $vars->{'tabwidth'} = $tabwidth; $vars->{'newtabwidth'} = $newtabwidth; $vars->{'change_tabwidth_url'} = $url_builder->view_url(topicid => $topicid, projectid => $projectid, mode => $mode, tabwidth => $newtabwidth, fview => $fview); # Set the display all, display single URLs. $vars->{'display_all_files_url'} = $url_builder->view_url(topicid => $topicid, projectid => $projectid, mode => $mode, fview => -1); $vars->{'display_single_file_url'} = $url_builder->view_url(topicid => $topicid, projectid => $projectid, mode => $mode); $vars->{'fview'} = $fview; # Setup the filetable template variable for displaying the table of # contents. my @filetable = (); my $total_old_changes = 0; my $total_new_changes = 0; for (my $i = 0; $i <= $#filenames; $i++) { my $filerow = {}; my $filename = $filenames[$i]; $filerow->{filename} = $filename; $filerow->{numchanges} = $numchanges[$i]; if (defined $numchanges[$i] && $numchanges[$i] =~ /^\+(\d+),\-(\d+)$/o) { $total_old_changes += $2; $total_new_changes += $1; } $filerow->{href_filename_url} = $url_builder->view_url(topicid => $topicid, projectid => $projectid, mode => $mode, fview => $i) . "#" . $filename; $filerow->{binary} = $binary[$i]; my $revision = $revisions[$i]; if ($revision eq $Codestriker::ADDED_REVISION) { $filerow->{revision} = 'added'; } elsif ($revision eq $Codestriker::REMOVED_REVISION) { $filerow->{revision} = 'removed'; } elsif ($revision eq $Codestriker::PATCH_REVISION) { $filerow->{revision} = 'patch'; } else { $filerow->{revision} = $revision; } push @filetable, $filerow; } $vars->{'filetable'} = \@filetable; $vars->{'total_old_changes'} = $total_old_changes; $vars->{'total_new_changes'} = $total_new_changes; # Determine which deltas are to be retrieved. my @deltas = (); if ($fview != -1) { # Get only the deltas for the selected file. @deltas = Codestriker::Model::Delta->get_delta_set($topicid, $fview); } else { # Get the whole delta data. @deltas = Codestriker::Model::Delta->get_delta_set($topicid, -1); } my $delta_renderer = Codestriker::Http::DeltaRenderer->new($topic, \@comments, \@deltas, $query, $mode, $tabwidth, $repository); # Set the add general comment URL. $vars->{'add_general_comment_element'} = $delta_renderer->comment_link(-1, -1, 1, "Add General Comment"); # Set the per-delta URL links, such as adding a file-level comment, # and links to the previous/next file. my $current_filename = ""; foreach my $delta (@deltas) { my $filenumber = $delta->{filenumber}; $delta->{add_file_comment_element} = $delta_renderer->comment_link($filenumber, -1, 1, "[Add File Comment]"); # Determine if the file has a link to a repository system, # and if so, create the appropriate links. if ($delta->{repmatch} && $delta->{revision} ne $Codestriker::ADDED_REVISION && $delta->{revision} ne $Codestriker::PATCH_REVISION && defined $repository) { $delta->{repository_file_view_url} = $repository->getViewUrl($delta->{filename}); $delta->{view_old_full_url} = $url_builder->view_file_url(topicid => $topicid, projectid => $projectid, filenumber => $filenumber, new => 0, line => $delta->{old_linenumber}, mode => $mode); $delta->{view_old_full_both_url} = $delta->{view_old_full_url}; $delta->{view_new_full_url} = $url_builder->view_file_url(topicid => $topicid, projectid => $projectid, filenumber => $filenumber, new => 1, line => $delta->{new_linenumber}, mode => $mode); $delta->{view_new_full_both_url} = $delta->{view_new_full_url}; } # Create the next/previous file URL links. if ($filenumber > 0) { $delta->{previous_file_url} = $url_builder->view_url(topicid => $topicid, projectid => $projectid, mode => $mode, fview => $filenumber-1) . "#" . $filenames[$filenumber-1]; } if ($filenumber < $#filenames) { $delta->{next_file_url} = $url_builder->view_url(topicid => $topicid, projectid => $projectid, mode => $mode, fview => $filenumber+1) . "#" . $filenames[$filenumber+1]; } $current_filename = $delta->{filename}; } # Annotate the deltas appropriately so that they can be easily rendered. $delta_renderer->annotate_deltas(); $vars->{'deltas'} = \@deltas; # Fire the template for generating the view topic screen. my $template = Codestriker::Http::Template->new("viewtopic"); $template->process($vars); $http_response->generate_footer(); # Fire the topic listener to indicate that the user has viewed the topic. Codestriker::TopicListeners::Manager::topic_viewed($email, $topic);}# This function is used by all of the view topic tabs to fill out the# common template items that are required by all, in addition to the view# topic file action.sub ProcessTopicHeader { my ($vars, $topic, $url_builder) = @_; # Handle the links in the three topic tabs. $vars->{'view_topicinfo_url'} = $url_builder->view_topicinfo_url(topicid => $topic->{topicid}, projectid => $topic->{project_id}); $vars->{'view_topic_url'} = $url_builder->view_url(topicid => $topic->{topicid}, projectid => $topic->{project_id}); $vars->{'view_comments_url'} = $url_builder->view_comments_url(topicid => $topic->{topicid}, projectid => $topic->{project_id}); $vars->{'view_topic_properties_url'} = $url_builder->view_topic_properties_url(topicid => $topic->{topicid}, projectid => $topic->{project_id}); my @project_ids = ($topic->{project_id}); $vars->{'list_open_topics_in_project_url'} = $url_builder->list_topics_url("", "", "", "", "", "", "", "", "", "", [ 0 ], \@project_ids); # Retrieve the comment details for this topic. my @comments = $topic->read_comments(); # Obtains how many comments there are, and the internal link to them. $vars->{'number_comments'} = $#comments + 1; # Obtain the view topic summary information, the title, bugs it relates # to, and who the participants are. $vars->{'title'} = $topic->{title}; $vars->{'author'} = Codestriker->filter_email($topic->{author}); $vars->{'document_creation_time'} = Codestriker->format_timestamp($topic->{creation_ts}); $vars->{'topic'} = $topic->{topicid}; $vars->{'reviewers'} = Codestriker->filter_email($topic->{reviewers}); $vars->{'cc'} = Codestriker->filter_email($topic->{cc}); # Get the list of obsoleted topics. my @obsoleted_topics = (); foreach my $id (@{ $topic->{obsoleted_topics} }) { my $obsoleted_topic = Codestriker::Model::Topic->new($id); my $entry = {}; $entry->{title} = $obsoleted_topic->{title}; $entry->{view_url} = $url_builder->view_url(topicid => $id, projectid => $obsoleted_topic->{project_id}); push @obsoleted_topics, $entry; } $vars->{'obsoleted_topics'} = \@obsoleted_topics; # Get the list of topics this has been obsoleted by. my @obsoleted_by = (); foreach my $id (@{ $topic->{obsoleted_by} }) { my $superseeded_topic = Codestriker::Model::Topic->new($id); my $entry = {}; $entry->{title} = $superseeded_topic->{title}; $entry->{view_url} = $url_builder->view_url(topicid => $id, projectid => $superseeded_topic->{project_id}); push @obsoleted_by, $entry; } $vars->{'obsoleted_by'} = \@obsoleted_by; }1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -