App-MaMGal

 view release on metacpan or  search on metacpan

MANIFEST  view on Meta::CPAN

t/010_unit_command_checker.t
t/010_unit_imageinfo.t
t/010_unit_imageinfo_exiftool.t
t/010_unit_system_exception.t
t/050_unit_entry.t
t/060_unit_nonpicture.t
t/065_unit_brokensymlink.t
t/070_unit_dir.t
t/080_unit_picture.t
t/100_unit_formatter.t
t/100_unit_localeenv.t
t/100_unit_maker.t
t/100_unit_mplayer_wrapper.t
t/300_integration_dir_with_many.t
t/300_integration_dir_with_one_file.t
t/300_integration_entry_factory.t
t/500_integration_formatter_one_film.t
t/500_integration_formatter_one_picture.t
t/500_integration_formatter_one_subdir.t
t/500_integration_formatter_slides_sequence.t
t/800_integration_maker_one_film.t

TODO  view on Meta::CPAN

--------------------

The following things would be useful, though not critical:

Check FSF address in GNU licenses.

Make the film miniatures stand out by having e.g. an overlay film icon.

Add options for forcing mamgal to refresh slides and/or miniatures despite them
being fresh. This will be useful when e.g. regenerating the gallery in a
different locale (or with some modified options, when they are implemented).
There could also be an option to just remove generated files, rather than
creating them.

There are some features in imageindex which would be nice to have, such as
graphic smileys, or greater ability to control the appearance of pages.

Ability to rapidly move from a directory to any of its parents by clicking on a
component of the path displayed at the top of the page.

Parallel processing - having all CPUs busy generating the gallery would be

lib/App/MaMGal.pm  view on Meta::CPAN

use App::MaMGal::ImageInfoFactory;
use App::MaMGal::LocaleEnv;
use App::MaMGal::Maker;
use App::MaMGal::MplayerWrapper;

sub init
{
	my $self = shift;

	my $logger = App::MaMGal::Logger->new(FileHandle->new_from_fd('STDERR', 'w'));
	my $locale_env;
	if (@_) {
		$locale_env = App::MaMGal::LocaleEnv->new($logger);
		$locale_env->set_locale($_[0]);
		textdomain('mamgal');
	} else {
		$locale_env = App::MaMGal::LocaleEnv->new($logger);
	}
	my $formatter = App::MaMGal::Formatter->new($locale_env);
	my $command_checker = App::MaMGal::CommandChecker->new;
	my $mplayer_wrapper = App::MaMGal::MplayerWrapper->new($command_checker);
	my $datetime_parser = Image::EXIF::DateTime::Parser->new;
	my $image_info_factory = App::MaMGal::ImageInfoFactory->new($datetime_parser, $logger);
	my $entry_factory = App::MaMGal::EntryFactory->new($formatter, $mplayer_wrapper, $image_info_factory, $logger);
	my $maker = App::MaMGal::Maker->new($entry_factory);

	$self->{maker} = $maker;
	$self->{logger} = $logger;

lib/App/MaMGal/Formatter.pm  view on Meta::CPAN

use base 'App::MaMGal::Base';
use Carp;
use Locale::gettext;
use URI::file;
use HTML::Entities qw(encode_entities_numeric);
use App::MaMGal::Logger;

sub init
{
	my $self = shift;
	my $le = shift or croak "Need a locale env arg";
	ref $le and $le->isa('App::MaMGal::LocaleEnv') or croak "Arg is not a App::MaMGal::LocaleEnv, but a [$le]";
	$self->set_locale_env($le);
}

sub set_locale_env
{
	my $self = shift;
	my $le = shift;
	$self->{locale_env} = $le;
}

sub HEADER
{
	my $self = shift;
	my $head = shift || '';
	sprintf("<html><head><meta http-equiv='Content-Type' content='text/html; charset=%s'>%s</head><body>", $self->{locale_env}->get_charset, $head);
}

sub MAYBE_LINK
{
	my $self = shift;
	my $link = shift;
	my $text = shift;
	if ($link) {
		$self->LINK($link.'.html', $text)
	} else {

lib/App/MaMGal/Formatter.pm  view on Meta::CPAN

{
	my $self  = shift;
	my $entry = shift;
	my $suppress_description = shift;
	my $path = $entry->page_path;
	my $thumbnail_path = $entry->thumbnail_path;
	my $ret = '';
	$ret .= '<td class="entry_cell">';
	my @timeret;
	foreach my $time ($entry->creation_time()) {
		push @timeret, sprintf('<span class="date">%s</span> <span class="time">%s</span>', $self->{locale_env}->format_date($time), $self->{locale_env}->format_time($time));
	}
	$ret .= '<br>'.join(' &mdash; ', @timeret).'<br>';
	$ret .= $self->LINK($path, $self->MAYBE_IMG($thumbnail_path));
	if ($entry->description and not $suppress_description) {
		$ret .= sprintf('<br><span class="desc">%s</span>', $entry->description);
	} else {
		$ret .= sprintf('<br><span class="filename">[%s]</span><br>', $self->LINK($path, $entry->name));
	}
	$ret .= '</td>';
	return $ret;

lib/App/MaMGal/Formatter.pm  view on Meta::CPAN

	$r .= "</p>\n";

	if ($pic->isa('App::MaMGal::Entry::Picture::Film')) {
		$r .= $self->MAYBE_EMBED('../'.$pic->name);
		$r .= '<br>';
		$r .= $self->LINK('../'.$pic->name, gettext('Download'));
	} else {
		$r .= $self->LINK('../'.$pic->name, $self->MAYBE_IMG('../'.$pic->medium_dir.'/'.$pic->name));
	}
	my $time = $pic->creation_time();
	$r .= sprintf('<br><span class="date">%s</span> <span class="time">%s</span><br>', $self->{locale_env}->format_date($time), $self->{locale_env}->format_time($time));
	$r .= $self->FOOTER;
	return $r;
}

sub stylesheet
{
	my $t = <<END;
table.index { width: 100% }
.entry_cell { text-align: center }
.slide_desc     { font-weight: bold }

lib/App/MaMGal/LocaleEnv.pm  view on Meta::CPAN

# mamgal - a program for creating static image galleries
# Copyright 2008 Marcin Owsiany <marcin@owsiany.pl>
# See the README file for license information
# A class encapsulating locale environment settings.
package App::MaMGal::LocaleEnv;
use strict;
use warnings;
use base 'App::MaMGal::Base';
use Carp;
use Locale::gettext;
use POSIX;

sub init
{

lib/App/MaMGal/LocaleEnv.pm  view on Meta::CPAN

		$self->{get_codeset} = sub { langinfo(CODESET()) };
	}
}

sub get_charset
{
	my $self = shift;
	&{$self->{get_codeset}}
}

sub set_locale
{
	my $self = shift;
	my $locale = shift;
	setlocale(LC_ALL, $locale);
}

sub format_time
{
	my $self = shift;
	my $time = shift or return '??:??:??';
	strftime('%X', localtime($time))
}

sub format_date

po/Makefile  view on Meta::CPAN

LINGUAS = pl
MOS     = pl.mo

.PHONY: all
all: $(MOS)

.PHONY: install
install: $(MOS)
	for locale in $(LINGUAS) ; do \
	 install -m 0644 -o root -g root $$locale.mo $(DEST)/usr/share/locale/$$locale/LC_MESSAGES/mamgal.mo ; \
	done

.PHONY: refresh-pot
refresh-pot:
	rm -f mamgal.pot.new mamgal.pot.old
	cd .. && (echo mamgal; grep 'pm$$' MANIFEST) | xgettext \
	  --add-comments=TRANSLATORS: \
	  --from-code=UTF-8 \
	  --msgid-bugs-address="Marcin Owsiany <marcin@owsiany.pl>" \
	  --package-name=mamgal --package-version=0.1 \
	  --copyright-holder="Marcin Owsiany <marcin@owsiany.pl>" \
	  -L Perl -d mamgal -o po/mamgal.pot.new -f -
	mv mamgal.pot mamgal.pot.old
	msgmerge mamgal.pot.old mamgal.pot.new > mamgal.pot

.PHONY: refresh-pos
refresh-pos:
	set -e ; \
	for locale in $(LINGUAS) ; do \
	 mv $$locale.po $$locale.po.old ; \
	 msgmerge $$locale.po.old mamgal.pot > $$locale.po ; \
	done

%.mo: %.po
	msgfmt -o $@ $<

t/100_unit_formatter.t  view on Meta::CPAN

use lib 'testlib';
use App::MaMGal::TestHelper;

prepare_test_data;

use_ok('App::MaMGal::Formatter');
my $f;
dies_ok(sub { App::MaMGal::Formatter->new },     "formatter cannot be created without parameters");
dies_ok(sub { App::MaMGal::Formatter->new(1) },  "formatter cannot be created with some junk parameter");

my $le = get_mock_localeenv;
$le->mock('get_charset', sub { 'UTF-8' });
$le->mock('format_time', sub { $_[1] == 1227684276 ? '12:00:00' : '13:13:13' });
$le->mock('format_date', sub { $_[1] == 1227684276 ? '18 gru 2004' : '2 kwi 2004' });

lives_ok(sub { $f = App::MaMGal::Formatter->new($le) }, "formatter can be created with locale env");
isa_ok($f, 'App::MaMGal::Formatter');
lives_ok(sub { $f->set_locale_env($le) },          "Formatter accepts a set_locale_env call");

my $mock_td = Test::MockObject->new
	->mock('name', sub { 'td' })
	->mock('is_root', sub { 1 });
my $d = Test::MockObject->new
	->mock('elements', sub { () })
	->mock('containers', sub { $mock_td })
	->mock('name', sub { 'empty' })
	->mock('is_root', sub { 0 });
dies_ok(sub { $f->format },                             "dies with no args");

t/100_unit_formatter.t  view on Meta::CPAN

$mp->set_isa('App::MaMGal::Picture::Static');
my $time = 1227684276;
$mp->mock('creation_time', sub { $time });
$mp->mock('page_path', sub { "pag'e_path" });
$mp->mock('thumbnail_path', sub { "tn'_pa?t#h" });
$mp->mock('description', sub { 'some description' });
$mp->mock('name', sub { 'foobar' });
my $cell;
lives_ok(sub { $cell = $f->entry_cell($mp) },		"formatter can format a cell");
ok($mp->called('creation_time'),			"formatter interrogated the entry for creation time");
ok($le->called('format_time'),				"formatter interrogated the locale env for time formatting");
ok($le->called('format_date'),				"formatter interrogated the locale env for date formatting");
tag_ok($cell, 'span', { 'class' => 'time', _content => '12:00:00' }, "generated cell contains creation time");
tag_ok($cell, 'span', { 'class' => 'date', _content => '18 gru 2004' }, "generated cell contains creation date");
tag_ok($cell, 'a', { href => "pag'e_path" }, "generated link is correctly encoded");
tag_ok($cell, 'img', { src => "tn'_pa%3Ft%23h" }, "generated img src is correctly encoded");

my $mp2 = Test::MockObject->new;
$mp2->set_isa('App::MaMGal::Picture::Static');
my ($time1, $time2) = (1080907993, 1227684276);
$mp2->mock('creation_time', sub { ($time1, $time2) });
$mp2->mock('page_path', sub { 'page_path ¿ó³w na staro¶æ wydziela wstrêtn± woñ' });
$mp2->mock('thumbnail_path', sub { 'tn_path ¿ó³w na staro¶æ wydziela wstrêtn± woñ' });
$mp2->mock('description', sub { 'some description ¿ó³w na staro¶æ wydziela wstrêtn± woñaae' });
$mp2->mock('name', sub { 'name ¿ó³w na staro¶æ wydziela wstrêtn± woñ' });
my $cell2;
lives_ok(sub { $cell2 = $f->entry_cell($mp2) },		"formatter can format a cell");
ok($mp2->called('creation_time'),			"formatter interrogated the entry for creation time");
ok($le->called('format_time'),				"formatter interrogated the locale env for time formatting");
ok($le->called('format_date'),				"formatter interrogated the locale env for date formatting");
tag_ok($cell2, 'span', { 'class' => 'time', _content => '12:00:00' }, "generated cell contains creation time");
tag_ok($cell2, 'span', { 'class' => 'date', _content => '18 gru 2004' }, "generated cell contains creation date");
tag_ok($cell2, 'span', { 'class' => 'time', _content => '13:13:13' }, "generated cell contains creation time");
tag_ok($cell2, 'span', { 'class' => 'date', _content => '2 kwi 2004' }, "generated cell contains creation date");
tag_ok($cell2, 'a', { href => 'page_path%20%BF%F3%B3w%20na%20staro%B6%E6%20wydziela%20wstr%EAtn%B1%20wo%F1' }, "generated link is correctly encoded");
tag_ok($cell2, 'img', { src => 'tn_path%20%BF%F3%B3w%20na%20staro%B6%E6%20wydziela%20wstr%EAtn%B1%20wo%F1' }, "generated image url is correctly encoded");
tag_ok($cell2, 'span', { class => 'desc', _content => qr'some description ¿ó³w na staro¶æ wydziela wstrêtn± woñaae' }, "generated description is not encoded");

t/100_unit_localeenv.t  view on Meta::CPAN

# test parameter checks
dies_ok(sub { App::MaMGal::LocaleEnv->new },               "Locale env dies on creation with no args");
dies_ok(sub { App::MaMGal::LocaleEnv->new(1) },            "Locale env dies on creation with junk arg");
my $le;
lives_ok(sub { $le = App::MaMGal::LocaleEnv->new(get_mock_logger) }, "new succeeds with logger");
my $ch;
lives_ok(sub { $ch = $le->get_charset },             "Locale env returns a charset");
ok($ch,                                              "The charset returned by get_charset is never empty");

# It is not possible to portably test whether changing, retrieving or setting
# anything other than C locale is possible, because the set of available
# locales is system-specific.
lives_ok(sub { $le->set_locale("C") },               "Locale env can set a posix locale");
lives_ok(sub { $ch = $le->get_charset },             "Locale env can retrieve the charset name afterwards");
# The following string should be returned whether nl_langinfo is available or not
is($ch, "ANSI_X3.4-1968",                            "Charset name retrieved by locale env is expected name for posix locale");

# Time formatting
my ($t, $d);
lives_ok(sub { $t = $le->format_time(1227723614) },  "Locale env can format time");
lives_ok(sub { $d = $le->format_date(1227723614) },  "Locale env can format date");
# cannot test exact date and time, as it will differ depending on the timezone
like($t, qr'\d{2}:\d{2}:14',                         "Time is correct");
like($d, qr'11/2[567]/08',                           "Date is correct");
is($le->format_time(), '??:??:??',                   "Locale env can format unknown time");
is($le->format_date(), '???',                        "Locale env can format unknown date");

t/500_integration_formatter_one_film.t  view on Meta::CPAN

use lib 'testlib';
use App::MaMGal::TestHelper;

prepare_test_data;

use App::MaMGal::Formatter;
use App::MaMGal::EntryFactory;
use App::MaMGal::LocaleEnv;
use App::MaMGal::ImageInfoFactory;
my $le = App::MaMGal::LocaleEnv->new(get_mock_logger);
$le->set_locale('C');
my $f = App::MaMGal::Formatter->new($le);

#
# a dir with a single film
#

my $time = 1228933448;
utime($time, $time, 'td/one_film/m.mov') == 1 or die "Failed to touch file";
my $dir = App::MaMGal::EntryFactory->new($f, get_mock_mplayer_wrapper, App::MaMGal::ImageInfoFactory->new(get_mock_datetime_parser, get_mock_logger), get_mock_logger)->create_entry_for('td/one_film');
# this is m.mov

t/500_integration_formatter_one_picture.t  view on Meta::CPAN

use App::MaMGal::TestHelper;
use Image::EXIF::DateTime::Parser;
use App::MaMGal::ImageInfoFactory;

prepare_test_data;

use App::MaMGal::Formatter;
use App::MaMGal::EntryFactory;
use App::MaMGal::LocaleEnv;
my $le = App::MaMGal::LocaleEnv->new(get_mock_logger);
$le->set_locale('C');
my $f = App::MaMGal::Formatter->new($le);
my $edtp = Image::EXIF::DateTime::Parser->new;
my $iif = App::MaMGal::ImageInfoFactory->new($edtp, get_mock_logger);
my $ef = App::MaMGal::EntryFactory->new($f, get_mock_mplayer_wrapper, $iif, get_mock_logger);

#
# a dir with a single pic _without_ description
#

my $time = 1228933448;

t/500_integration_formatter_one_subdir.t  view on Meta::CPAN

use Carp 'verbose';
use Test::More tests => 10;
use Test::HTML::Content;
use lib 'testlib';
use App::MaMGal::TestHelper;

prepare_test_data;

use App::MaMGal::LocaleEnv;
my $le = App::MaMGal::LocaleEnv->new(get_mock_logger);
$le->set_locale('C');
use App::MaMGal::Formatter;
my $f = App::MaMGal::Formatter->new($le);

use App::MaMGal::EntryFactory;
use App::MaMGal::ImageInfoFactory;
my $d = App::MaMGal::EntryFactory->new($f, get_mock_mplayer_wrapper, App::MaMGal::ImageInfoFactory->new(get_mock_datetime_parser, get_mock_logger), get_mock_logger)->create_entry_for('td/one_dir');
$d->set_root(1);
my $t = $f->format($d);
text_ok($t, 'one_dir',					"there is the directory name");
tag_count($t, "a", { href => 'subdir/index.html' }, 2,	"there are two links to the subdir");

t/500_integration_formatter_slides_sequence.t  view on Meta::CPAN

use App::MaMGal::TestHelper;
use Image::EXIF::DateTime::Parser;
use App::MaMGal::ImageInfoFactory;

prepare_test_data;

use App::MaMGal::Formatter;
use App::MaMGal::EntryFactory;
use App::MaMGal::LocaleEnv;
my $le = App::MaMGal::LocaleEnv->new(get_mock_logger);
$le->set_locale('C');
my $edtp = Image::EXIF::DateTime::Parser->new,
my $f = App::MaMGal::Formatter->new($le);
my $iif = App::MaMGal::ImageInfoFactory->new($edtp, get_mock_logger);
my $ef = App::MaMGal::EntryFactory->new($f, get_mock_mplayer_wrapper, $iif, get_mock_logger);
my $d = $ef->create_entry_for('td/more');

my @elems = $d->elements;
my $p = $elems[1];
my $t = $f->format_slide($p);
tag_ok($t, "img", {src => '../.mamgal-medium/b.png'}, "b.png: there is a medium pic on the page");

t/900_integration_maker_many_files.t  view on Meta::CPAN

use App::MaMGal::TestHelper;

prepare_test_data;

dir_only_contains_ok('td/more', [qw(a.png b.png x.png subdir subdir/p.png subdir/p2.png subdir/lost+found),
                                 qw(subdir/uninteresting subdir/uninteresting/bar.txt),
                                 qw(subdir/interesting subdir/interesting/b.png),
                                 'zzz another subdir', 'zzz another subdir/p.png'], "not much exists initially");

use_ok('App::MaMGal');
# Get locale from environment so that you can see some representatative output in your language
my $M = App::MaMGal->new('');
ok($M->{logger});
ok($M->make_roots('td/more'), "maker returns success on an dir with some files");
dir_only_contains_ok('td/more', [qw(.mamgal-root
					index.html .mamgal-index.png .mamgal-style.css
					.mamgal-medium .mamgal-thumbnails .mamgal-slides
					a.png b.png x.png
					.mamgal-medium/a.png .mamgal-medium/b.png .mamgal-medium/x.png
					.mamgal-thumbnails/a.png .mamgal-thumbnails/b.png .mamgal-thumbnails/x.png
					.mamgal-slides/a.png.html .mamgal-slides/b.png.html .mamgal-slides/x.png.html

t/README  view on Meta::CPAN

  all other tests. Also, integration tests which use less classes should be put
  before those which use more classes, if possible.

  Ordering is possible because the perl testing framework runs them in filename
  alphabetical order.

Notes
-----

Things to keep in mind when changing/adding tests:
 - they should succeed in any timezone and any locale: you can check that by
   running for example:

   LANG=C TZ=GMT make test
   LANG=pl_PL.UTF-8 TZ=America/Los_Angeles make test

   before that make sure your system supports the locale you are testing with (try "LANG=pl_PL.UTF-8 locale")

testlib/App/MaMGal/TestHelper.pm  view on Meta::CPAN

# mamgal - a program for creating static image galleries
# Copyright 2008-2011 Marcin Owsiany <marcin@owsiany.pl>
# See the README file for license information
package App::MaMGal::TestHelper;
use Test::MockObject;
use Test::More;
use base 'Exporter';
use Carp;
@EXPORT = qw(get_mock_entry get_mock_iif get_mock_datetime_parser get_mock_formatter get_mock_localeenv get_mock_cc prepare_test_data get_mock_mplayer_wrapper get_mock_logger logged_only_ok logged_exception_only_ok get_mock_exception get_mock_fh prin...

sub get_mock_entry
{
	my $class = (shift || 'App::MaMGal::Entry');
	my %args = @_;
	my $mock_entry = Test::MockObject->new
		->mock('set_root')
		->mock('make')
		->mock('add_tools')
		->mock('name', sub { $args{'name'} || 'filename.jpg' })

testlib/App/MaMGal/TestHelper.pm  view on Meta::CPAN

}

sub get_mock_formatter {
	my @methods = @_;
	my $mf = Test::MockObject->new();
	$mf->set_isa('App::MaMGal::Formatter');
	$mf->mock($_, sub { "whatever" }) for @methods;
	return $mf;
}

sub get_mock_localeenv {
	my $ml = Test::MockObject->new();
	$ml->set_isa('App::MaMGal::LocaleEnv');
	$ml->mock('get_charset', sub { "ISO-8859-123" });
	$ml->mock('set_locale');
	$ml->mock('format_time', sub { "12:12:12" });
	$ml->mock('format_date', sub { "18 dec 2004" });
	return $ml;
}

sub get_mock_mplayer_wrapper {
	my $mmw = Test::MockObject->new;
	$mmw->set_isa('App::MaMGal::MplayerWrapper');
	my $mock_image = Test::MockObject->new;
	$mock_image->set_isa('Image::Magick');



( run in 1.633 second using v1.01-cache-2.11-cpan-ceb78f64989 )