#!/usr/bin/perl
# perlpanel-item-edit - a Gtk2-Perl .desktop file editor
# This file is part of PerlPanel.
# 
# PerlPanel 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 2 of the License, or
# (at your option) any later version.
# 
# PerlPanel 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 PerlPanel; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# Copyright: (C) 2003-2004 Gavin Brown <gavin.brown@uk.com>
#
# $Id: old-perlpanel-item-edit,v 1.17 2004/10/26 16:15:33 jodrell Exp $
use Gtk2;
use strict;

Gtk2->init;

my $desktop_namespace = 'Desktop Entry';

my $PREFIX = (-e '@PREFIX@' ? '@PREFIX@' : $ENV{PWD});

my $namespace = '';
my $data = {};

my $theme = Gtk2::IconTheme->get_default;

$theme->prepend_search_path(sprintf('%s/share/icons/hicolor/48x48/apps/', $PREFIX));

my $file = $ARGV[0] or print STDERR "Usage: perlpanel-item-edit [FILE]\n" and exit 1;

open(FILE, $file) or print STDERR "Error opening '$file': $!\n" and exit 1;

my $line_no = 0;

while (<FILE>) {
	$line_no++;
	chomp;
	s/\;.*$//g;
	s/^\s*//g;
	s/\s*$//g;
	next if (/^$/);
	if (/^\[(.+?)\]$/) {
		$namespace = $1;
	} elsif (/^(.+)=(.*)$/) {
		if ($namespace eq '') {
			print STDERR "Parse error on line $line_no of '$file'\n" and exit 1;
		} else {
			$data->{$namespace}{$1} = $2;
		}
	} else {
			print STDERR "Parse error on line $line_no of '$file'\n" and exit 1;
	}
}

close(FILE);

my $language = $ENV{LANG} || 'en_US';
$language =~ s/\..*$//g;

if ($data->{$desktop_namespace}{Name} eq '') {
	$data->{$desktop_namespace}{Name} = $data->{$desktop_namespace}{"Name[$language]"}
}

if ($data->{$desktop_namespace}{Comment} eq '') {
	$data->{$desktop_namespace}{Comment} = $data->{$desktop_namespace}{"Comment[$language]"}
}

my $pristine = {
	Encoding	=> $data->{$desktop_namespace}{Encoding},
	Type		=> $data->{$desktop_namespace}{Type},
	Name		=> $data->{$desktop_namespace}{Name},
	Comment		=> $data->{$desktop_namespace}{Comment},
	Icon		=> $data->{$desktop_namespace}{Icon},
	Exec		=> $data->{$desktop_namespace}{Exec},
	StartupNotify	=> $data->{$desktop_namespace}{StartupNotify}
};

my $icon = $theme->load_icon('perlpanel', 48, 'use-builtin');

my $window = Gtk2::Dialog->new;
$window->signal_connect('delete_event', \&save);
$window->set_position('center');
$window->set_title('Launcher Properties');
$window->set_border_width(8);
$window->set_icon($icon);
$window->vbox->set_spacing(8);

my $table = Gtk2::Table->new(3, 4, 0);
$table->set_col_spacings(8);
$table->set_row_spacings(8);

my $name_entry = Gtk2::Entry->new;
$name_entry->set_text($data->{$desktop_namespace}{Name});
$name_entry->signal_connect('activate', \&save);
my $name_label = Gtk2::Label->new('Name:');
$name_label->set_alignment(1, 0.5);

my $comment_entry = Gtk2::Entry->new;
$comment_entry->set_text($data->{$desktop_namespace}{Comment});
$comment_entry->signal_connect('activate', \&save);
my $comment_label = Gtk2::Label->new('Comment:');
$comment_label->set_alignment(1, 0.5);

my $exec_entry = Gtk2::Entry->new;
$exec_entry->set_text($data->{$desktop_namespace}{Exec});
$exec_entry->signal_connect('activate', \&save);
my $exec_label = Gtk2::Label->new('Program:');
$exec_label->set_alignment(1, 0.5);

my $exec_button_label = Gtk2::Label->new_with_mnemonic('_Browse...');
my $exec_button_image = Gtk2::Image->new_from_stock('gtk-open', 'button');
my $exec_button_box = Gtk2::HBox->new;
$exec_button_box->pack_start($exec_button_image, 0, 0, 0);
$exec_button_box->pack_start($exec_button_label, 1, 1, 0);
my $exec_button = Gtk2::Button->new;
$exec_button->add($exec_button_box);
$exec_button->signal_connect('clicked', \&choose_program);

my $icon_label = Gtk2::Label->new('Icon:');
$icon_label->set_alignment(1, 0);
my $icon_image;
my $pixmap_path = sprintf('%s/share/pixmaps/%s', $PREFIX, $data->{$desktop_namespace}{Icon});

if (-r $data->{$desktop_namespace}{Icon} && is_image($data->{$desktop_namespace}{Icon})) {
	$icon_image = Gtk2::Image->new_from_pixbuf(Gtk2::Gdk::Pixbuf->new_from_file_at_size($data->{$desktop_namespace}{Icon}, 48, 48));

} elsif (-r $pixmap_path && is_image($pixmap_path)) {
	$icon_image = Gtk2::Image->new_from_pixbuf(Gtk2::Gdk::Pixbuf->new_from_file_at_size($pixmap_path, 48, 48));

} else {
	$icon_image = Gtk2::Image->new_from_stock('gtk-missing-image', 'dialog');

}

my $icon_button = Gtk2::Button->new;
$icon_button->add($icon_image);
$icon_button->signal_connect('clicked', \&choose_icon);

my $icon_align = Gtk2::Alignment->new(0, 0, 0, 0);
$icon_align->add($icon_button);

my $notify = Gtk2::CheckButton->new('Launch Feedback');
$notify->set_active($data->{$desktop_namespace}{StartupNotify} eq 'true' ? 1 : undef);

$table->attach_defaults($name_label, 0, 1, 0, 1);
$table->attach_defaults($name_entry, 1, 3, 0, 1);

$table->attach_defaults($comment_label, 0, 1, 1, 2);
$table->attach_defaults($comment_entry, 1, 3, 1, 2);

$table->attach_defaults($exec_label, 0, 1, 2, 3);
$table->attach_defaults($exec_entry, 1, 2, 2, 3);
$table->attach_defaults($exec_button, 2, 3, 2, 3);

$table->attach_defaults($icon_label, 0, 1, 3, 4);
$table->attach_defaults($icon_align, 1, 2, 3, 4);

$table->attach_defaults($notify, 1, 3, 4, 5);

$window->vbox->pack_start($table, 1, 1, 0);

$window->add_button('gtk-ok', 0);

$window->signal_connect('response', sub { save() if $_[1] == 0 });

$window->show_all;

Gtk2->main;

sub choose_program {

	my $selector;
	if ('' ne (my $msg = Gtk2->check_version (2, 4, 0)) or $Gtk2::VERSION < 1.040) {
		$selector = Gtk2::FileSelection->new('Choose File');
	} else {
		$selector = Gtk2::FileChooserDialog->new(
			'Choose File',
			undef,
			'open',
			'gtk-cancel'	=> 'cancel',
			'gtk-ok' => 'ok'
		);
	}

	chomp(my $path = `which $data->{$desktop_namespace}{Exec}`);
	if (-e $path) {
		$selector->set_filename($path);
	} else {
		$selector->set_filename($data->{$desktop_namespace}{Exec});
	}

	$selector->signal_connect('response', sub {
		if ($_[1] eq 'ok') {
			$exec_entry->set_text($selector->get_filename);
		}
		$selector->destroy;
	});
	$selector->show_all;
	return 1;
}

sub choose_icon {
	my $selector = Gtk2::FileChooserDialog->new(
		'Choose File',
		undef,
		'open',
		'gtk-cancel'	=> 'cancel',
		'gtk-ok' 	=> 'ok'
	);

	$selector->set_preview_widget(Gtk2::Image->new);
	$selector->signal_connect('selection-changed', sub {
		my $file = $selector->get_filename;
		if (-f $file) {
			my $pbf = Gtk2::Gdk::Pixbuf->new_from_file_at_size($file, 48, 48);
			$selector->get_preview_widget->set_from_pixbuf($pbf) if (defined($pbf));
		}
	});

	my $pixmap_path = sprintf('%s/share/pixmaps/%s', $PREFIX, $data->{$desktop_namespace}{Icon});
	if (-e $pixmap_path) {
		$selector->set_filename($pixmap_path);
	} elsif (-e $data->{$desktop_namespace}{Icon}) {
		$selector->set_filename($data->{$desktop_namespace}{Icon});
	} else {
		$selector->set_current_folder('/usr/share/icons/hicolor/48x48/apps');
	}

	$selector->signal_connect('response', sub {
		if ($_[1] eq 'ok') {
			$data->{$desktop_namespace}{Icon} = $selector->get_filename;
			my $new_image = Gtk2::Image->new_from_file($data->{$desktop_namespace}{Icon});
			$new_image->show;
			$icon_button->remove($icon_button->child);
			$icon_button->add($new_image);
		}
		$selector->destroy;
	});
	$selector->show_all;
	return 1;
}

sub save {
	$data->{$desktop_namespace}{Name} = $name_entry->get_text;
	$data->{$desktop_namespace}{Comment} = $comment_entry->get_text;
	$data->{$desktop_namespace}{Exec} = $exec_entry->get_text;
	$data->{$desktop_namespace}{StartupNotify} = ($notify->get_active ? 'true' : 'false');

	$data->{$desktop_namespace}{Type} = 'Application';
	$data->{$desktop_namespace}{Encoding} = 'UTF-8';

	my $changed = 0;
	my $empty = 0;
	foreach my $name (keys %{$pristine}) {
		$changed++ if ($pristine->{$name} ne $data->{$desktop_namespace}{$name});
		$empty++ if ($data->{$desktop_namespace}{$name} eq '');
	}

	exit if ($changed < 1 || $empty == scalar(keys %{$pristine}));

	open(FILE, ">$file") or print STDERR "Error opening '$file': $!\n" and exit 1;
	foreach my $namespace (keys %{$data}) {
		print FILE "[$namespace]\n";
		foreach my $name (keys %{$data->{$namespace}}) {
			print FILE "$name=$data->{$namespace}{$name}\n";
		}
	}
	close(FILE);
	exit;
}

# we could do all kinds of clever stuff here, using gdk-pixbuf-query-loaders to get
# gdkpixbuf's supported file types, or using file -ib to get the file's mime type,
# but they're all suboptimal, so just regex the filename:
sub is_image {
	my $filename = shift;
	return ($filename =~ /\.(jpe?g|png|bmp|gif|tif)$/i);
	
}

exit;
