%# BEGIN BPS TAGGED BLOCK {{{ %# %# COPYRIGHT: %# %# This software is Copyright (c) 1996-2010 Best Practical Solutions, LLC %# %# %# (Except where explicitly superseded by other copyright notices) %# %# %# LICENSE: %# %# This work is made available to you under the terms of Version 2 of %# the GNU General Public License. A copy of that license should have %# been provided with this software, but in any event can be snarfed %# from www.gnu.org. %# %# This work 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 program; if not, write to the Free Software %# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA %# 02110-1301 or visit their web page on the internet at %# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. %# %# %# CONTRIBUTION SUBMISSION POLICY: %# %# (The following paragraph is not intended to limit the rights granted %# to you to modify and distribute this software under the terms of %# the GNU General Public License and is only of importance to you if %# you choose to contribute your changes and enhancements to the %# community by submitting them to Best Practical Solutions, LLC.) %# %# By intentionally submitting any modifications, corrections or %# derivatives to this work, or any other work intended for use with %# Request Tracker, to Best Practical Solutions, LLC, you confirm that %# you are the copyright holder for those contributions and you grant %# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, %# royalty-free, perpetual, license to use, copy, create derivative %# works based on those contributions, and sublicense and distribute %# those contributions and any derivatives thereof. %# %# END BPS TAGGED BLOCK }}} <& /Admin/Elements/Header, Title => loc("Theme"), LinkRel => { stylesheet => '/NoAuth/css/farbtastic.css' } &> <& /Admin/Elements/SystemTabs, current_tab => 'Admin/Global/Theme.html', Title => loc("Theme") &> <& /Elements/ListActions, actions => \@results &>

Customize the RT theme

  1. <&|/l&>Select a color for the section:
    % if ($colors) {
    % for (@$colors) { % my $fg = $_->{l} >= $text_threshold ? 'black' : 'white'; % }
    % }

Custom CSS (Advanced)


<%INIT> my $text_threshold = 0.6; my @results; my $has_color_analyzer = eval { require Imager; require Convert::Color; 1 }; my $img; if (my $file_hash = _UploadedFile( 'logo-upload' )) { my ($id, $msg) = $RT::System->SetAttribute( Name => "UserLogo", Description => "User-provided logo", Content => { type => $file_hash->{ContentType}, data => $file_hash->{LargeContent} } ); $img = Imager->new; unless ( $img->read(data => $file_hash->{LargeContent}) ) { push @results, loc("Unable to read image: [_1]", $img->errstr); undef $img; } } elsif ($ARGS{'reset_logo'}) { $RT::System->DeleteAttribute('UserLogo'); } else { if (my $attr = $RT::System->FirstAttribute('UserLogo')) { my $content = $attr->Content; if (ref($content) eq 'HASH') { $img = Imager->new; unless ( $img->read(data => $content->{data}) ) { push @results, loc("Unable to read image: [_1]", $img->errstr); undef $img; } } else { $RT::System->DeleteAttribute('UserLogo'); } } } if ($user_css) { if ($ARGS{'reset_css'}) { $RT::System->DeleteAttribute('UserCSS'); undef $user_css; } else { my ($id, $msg) = $RT::System->SetAttribute( Name => "UserCSS", Description => "User-provided css", Content => $user_css ); } } if (!$user_css) { my $attr = $RT::System->FirstAttribute('UserCSS'); $user_css = $attr ? $attr->Content : '/* Page */ body {} input[type="reset"], input[type="submit"], input[class="button"] {} /* Page content */ div#body {} /* Page title */ div#header h1 {} /* Header */ div#quickbar {} /* Navigation */ div#nav {} /* Page menu */ div#page-navigation ul#page-menu {} '; } # XXX: move this to some other modules my $colors = $img && $has_color_analyzer? analyze_img($img) : undef; use List::MoreUtils qw(uniq); sub analyze_img { my $img = shift; my $color; for my $i (0..$img->getwidth-1) { for my $j (0..$img->getheight-1) { my @color = $img->getpixel(x=>$i, y=>$j)->rgba; pop @color; my $hsl = Convert::Color->new('rgb:'.join(',',map { $_ / 255 } @color))->convert_to('hsl'); my $c = join(',',@color); next if $hsl->lightness < 0.1; $color->{$c} ||= { h => $hsl->hue, s => $hsl->saturation, l => $hsl->lightness, cnt => 0, c => $c}; $color->{$c}->{cnt}++; } } for (values %$color) { $_->{rank} = $_->{s} * $_->{cnt}; } my @top5 = grep { defined and $_->{'l'} and $_->{'c'} } (sort { $b->{rank} <=> $a->{rank} } values %$color)[0..5]; if ((scalar uniq map {$_->{rank}} @top5) == 1) { warn "bad"; } return \@top5; } <%ARGS> $user_css => ''