Index: app/helpers/issues_helper.rb
===================================================================
--- app/helpers/issues_helper.rb	(revision 19865)
+++ app/helpers/issues_helper.rb	(revision 19866)
@@ -43,7 +43,7 @@
     n = 0
     ordered_values.compact.each do |value|
       s << "</tr>\n<tr>\n" if n > 0 && (n % 2) == 0
-      s << "\t<th>#{ h(value.custom_field.name) }:</th><td>#{ simple_format_without_paragraph(h(show_value(value))) }</td>\n"
+      s << "\t<th>#{ h(value.custom_field.name) }:</th><td>#{ simple_format_without_paragraph(show_value(value)) }</td>\n"
       n += 1
     end
     s << "</tr>\n"
Index: app/helpers/queries_helper.rb
===================================================================
--- app/helpers/queries_helper.rb	(revision 19865)
+++ app/helpers/queries_helper.rb	(revision 19866)
@@ -28,40 +28,46 @@
   end
   
   def column_content(column, issue, query = nil)
-    value = column.value(issue)
-    
-    case value.class.name
-    when 'String'
-      if column.name == :subject
-        subject_in_tree( issue, issue.subject, query)
+    case column.class.name
+    when 'QueryColumn'
+      value = column.value(issue)
+      case value.class.name
+      when 'String'
+        if column.name == :subject
+          subject_in_tree( issue, issue.subject, query)
+        else
+          h(value)
+        end
+      when 'Time'
+        format_time(value)
+      when 'Date'
+        format_date(value)
+      when 'Fixnum', 'Float'
+        case column.name
+        when :done_ratio
+            progress_bar(value, :width => '80px')
+        when :estimated_hours
+            l_hours(value)
+        else
+          value.to_s
+        end
+      when 'User'
+        link_to_user value
+      when 'Project'
+        link_to(h(value), :controller => 'projects', :action => 'show', :id => value)
+      when 'Version'
+        link_to(h(value), :controller => 'versions', :action => 'show', :id => value)
+      when 'TrueClass'
+        l(:general_text_Yes)
+      when 'FalseClass'
+        l(:general_text_No)
       else
         h(value)
       end
-    when 'Time'
-      format_time(value)
-    when 'Date'
-      format_date(value)
-    when 'Fixnum', 'Float'
-      case column.name
-      when :done_ratio
-          progress_bar(value, :width => '80px')
-      when :estimated_hours
-          l_hours(value)
-      else
-        value.to_s
-      end
-    when 'User'
-      link_to_user value
-    when 'Project'
-      link_to(h(value), :controller => 'projects', :action => 'show', :id => value)
-    when 'Version'
-      link_to(h(value), :controller => 'versions', :action => 'show', :id => value)
-    when 'TrueClass'
-      l(:general_text_Yes)
-    when 'FalseClass'
-      l(:general_text_No)
-    else
-      h(value)
+
+    when 'QueryCustomFieldColumn'
+      cfv = issue.custom_field_values.detect {|v| v.custom_field_id == column.custom_field.id}
+      show_value(cfv)
     end
   end
 
Index: app/helpers/custom_fields_helper.rb
===================================================================
--- app/helpers/custom_fields_helper.rb	(revision 19865)
+++ app/helpers/custom_fields_helper.rb	(revision 19866)
@@ -89,9 +89,19 @@
 
   # Return a string used to display a custom value
   def show_value(custom_value)
-    return "" unless custom_value
-    format_value(custom_value.value, custom_value.custom_field.field_format)
+    return "" unless custom_value && !custom_value.value.empty?
+    if custom_value.custom_field.url.empty?
+      return h(format_value(custom_value.value, custom_value.custom_field.field_format))
+    else
+      return url_format(custom_value)
+    end
   end
+
+  # Return an escaped string used to display a custom value
+  def show_value_plain(custom_value)
+    return "" unless custom_value && !custom_value.value.empty?
+    return h(format_value(custom_value.value, custom_value.custom_field.field_format))
+  end
   
   # Return a string used to display a custom value
   def format_value(value, field_format)
@@ -106,6 +116,17 @@
     end
   end
 
+  # Return a clean URL for a given custom field value
+  def url_format(custom_value)
+    url = custom_value.custom_field.url
+    return if url.empty?
+    
+    formatted_value = format_value(custom_value.value, custom_value.custom_field.field_format)
+    while (url.sub!(/__VALUE__/, h(custom_value.value)))
+    end
+    return link_to formatted_value, url, :target=>'_blank'
+  end
+
   # Return an array of custom field formats which can be used in select_tag
   def custom_field_formats_for_select
     CustomField::FIELD_FORMATS.sort {|a,b| a[1][:order]<=>b[1][:order]}.collect { |k| [ l(k[1][:name]), k[0] ] }
Index: app/helpers/timelog_helper.rb
===================================================================
--- app/helpers/timelog_helper.rb	(revision 19865)
+++ app/helpers/timelog_helper.rb	(revision 19866)
@@ -115,7 +115,7 @@
                   entry.hours.to_s.gsub('.', decimal_separator),
                   entry.comments
                   ]
-        fields += custom_fields.collect {|f| show_value(entry.custom_value_for(f)) }
+        fields += custom_fields.collect {|f| show_value_plain(entry.custom_value_for(f)) }
                   
         csv << fields.collect {|c| begin; ic.iconv(c.to_s); rescue; c.to_s; end }
       end
Index: app/controllers/custom_fields_controller.rb
===================================================================
--- app/controllers/custom_fields_controller.rb	(revision 19865)
+++ app/controllers/custom_fields_controller.rb	(revision 19866)
@@ -33,7 +33,8 @@
     rescue
     end
     (redirect_to(:action => 'index'); return) unless @custom_field.is_a?(CustomField)
-    
+
+    @custom_field.url.strip!
     if request.post? and @custom_field.save
       flash[:notice] = l(:notice_successful_create)
       call_hook(:controller_custom_fields_new_after_save, :params => params, :custom_field => @custom_field)
Index: app/views/custom_fields/_form.rhtml
===================================================================
--- app/views/custom_fields/_form.rhtml	(revision 19865)
+++ app/views/custom_fields/_form.rhtml	(revision 19866)
@@ -8,6 +8,7 @@
   p_regexp = $("custom_field_regexp");
   p_values = $("custom_field_possible_values");
   p_searchable = $("custom_field_searchable");
+  p_url = $("custom_field_url");
   p_default = $("custom_field_default_value");
   
   p_default.setAttribute('type','text');
@@ -65,6 +66,8 @@
 																																			 :rows => 15 %>
 <br /><em><%= l(:text_custom_field_possible_values_info) %></em></p>
 <p><%= @custom_field.field_format == 'bool' ? f.check_box(:default_value) : f.text_field(:default_value) %></p>
+<p><%= f.text_field :url, :size => 60 %>
+<br /><%= l(:text_custom_field_url_info) %></p>
 <%= call_hook(:view_custom_fields_form_upper_box, :custom_field => @custom_field, :form => f) %>
 </div>
 
Index: app/views/users/show.rhtml
===================================================================
--- app/views/users/show.rhtml	(revision 19865)
+++ app/views/users/show.rhtml	(revision 19866)
@@ -12,7 +12,7 @@
 	<% end %>
 	<% for custom_value in @custom_values %>
 	<% if !custom_value.value.blank? %>
-    <li><%=h custom_value.custom_field.name%>: <%=h show_value(custom_value) %></li>
+    <li><%=h custom_value.custom_field.name%>: <%= show_value(custom_value) %></li>
 	<% end %>
 	<% end %>
     <li><%=l(:label_registered_on)%>: <%= format_date(@user.created_on) %></li>
Index: app/views/versions/_overview.rhtml
===================================================================
--- app/views/versions/_overview.rhtml	(revision 19865)
+++ app/views/versions/_overview.rhtml	(revision 19866)
@@ -8,7 +8,7 @@
 <ul>
 	<% version.custom_values.each do |custom_value| %>
 		<% if !custom_value.value.blank? %>
-		   <li><%=h custom_value.custom_field.name %>: <%=h show_value(custom_value) %></li>
+		   <li><%=h custom_value.custom_field.name %>: <%= show_value(custom_value) %></li>
 		<% end %>
 	<% end %>
 </ul>
Index: app/views/mailer/_issue_text_plain.rhtml
===================================================================
--- app/views/mailer/_issue_text_plain.rhtml	(revision 19865)
+++ app/views/mailer/_issue_text_plain.rhtml	(revision 19866)
@@ -7,7 +7,7 @@
 <%=l(:field_assigned_to)%>: <%= issue.assigned_to %>
 <%=l(:field_category)%>: <%= issue.category %>
 <%=l(:field_fixed_version)%>: <%= issue.fixed_version %>
-<% issue.custom_values.each do |c| %><%= c.custom_field.name %>: <%= show_value(c) %>
+<% issue.custom_values.each do |c| %><%= c.custom_field.name %>: <%= show_value_plain(c) %>
 <% end %>
 
 <%= issue.description %>
Index: app/views/projects/show.rhtml
===================================================================
--- app/views/projects/show.rhtml	(revision 19865)
+++ app/views/projects/show.rhtml	(revision 19866)
@@ -16,7 +16,7 @@
   <% end %>
 	<% @project.custom_values.each do |custom_value| %>
 	<% if !custom_value.value.blank? %>
-	   <li><%= custom_value.custom_field.name%>: <%=h show_value(custom_value) %></li>
+	   <li><%= custom_value.custom_field.name%>: <%= show_value(custom_value) %></li>
 	<% end %>
 	<% end %>
 	</ul>	
Index: db/migrate/20100309115805_add_custom_fields_url.rb
===================================================================
--- db/migrate/20100309115805_add_custom_fields_url.rb	(revision 0)
+++ db/migrate/20100309115805_add_custom_fields_url.rb	(revision 19866)
@@ -0,0 +1,9 @@
+class AddCustomFieldsUrl < ActiveRecord::Migration
+  def self.up
+    add_column :custom_fields, :url, :string, :limit=>255, :default=>"", :null=>false
+  end
+
+  def self.down
+    remove_column :custom_fields, :url
+  end
+end
\ No newline at end of file
Index: config/locales/en.yml
===================================================================
--- config/locales/en.yml	(revision 19865)
+++ config/locales/en.yml	(revision 19866)
@@ -866,6 +866,7 @@
   text_repository_usernames_mapping: "Select or update the Redmine user mapped to each username found in the repository log.\nUsers with the same Redmine and repository username or email are automatically mapped."
   text_diff_truncated: '... This diff was truncated because it exceeds the maximum size that can be displayed.'
   text_custom_field_possible_values_info: 'One line for each value'
+  text_custom_field_url_info: '(__VALUE__ is a placeholder for each of the field values, eg. http://www.google.com/search?q=__VALUE__)'
   text_wiki_page_destroy_question: "This page has {{descendants}} child page(s) and descendant(s). What do you want to do?"
   text_wiki_page_nullify_children: "Keep child pages as root pages"
   text_wiki_page_destroy_children: "Delete child pages and all their descendants"
Index: config/locales/sk.yml
===================================================================
--- config/locales/sk.yml	(revision 19865)
+++ config/locales/sk.yml	(revision 19866)
@@ -789,6 +789,7 @@
   label_display: Zobrazenie
   button_create_and_continue: Vytvoriť a pokračovať
   text_custom_field_possible_values_info: 'Jeden riadok pre každú hodnotu'
+  text_custom_field_url_info: '(__VALUE__ sa nahradí hodnotou poľa, príklad: http://www.google.com/search?q=__VALUE__)'
   setting_repository_log_display_limit: Maximálne množstvo revizií zobrazené v logu
   setting_file_max_size_displayed: Maximálna veľkosť textových súborov zobrazených priamo na stránke
   field_watcher: Pozorovateľ
