#!/usr/bin/perl -w #------------------------------------------------------------------------------ =head1 NAME oometadoc - Document properties management interface =head1 SYNOPSIS oometadoc =head1 DESCRIPTION Simple graphical user interface allowing the user to get and set the metadata of the OpenOffice.org documents (SXW, SXI, SXC, ...) in a given directory. The list of the OpenOffice.org files is shown in the main window. Each time the user selects a file (by double-clic or OK button), another window appears, with some property fields: title, author, subject, description, keywords. The flat text content is shown in a read-only field. The user can update any property, or insert/delete any keyword. A double-click on a word in the text content field appends the word to the keword list. 'OK' saves the changes in the file. =head1 LIMITS This script is provided as a demo and test tool, with a very basic user interface. There is no directory selection dialog box. Some file names with blank spaces and/or non-ASCII characters are not properly processed. =head1 REQUIREMENTS Requires Tk and some Tk extensions (TK::Dialog, Tk::LabFrame, Tk::LabEntry) =cut #------------------------------------------------------------------------------ use Tk; use Tk::Dialog; use OpenOffice::OODoc; #------------------------------------------------------------------------------ our $sv_chemin = $ARGV[0] || $ENV{'HOME'} || '.'; our $chemin = $sv_chemin; our $D = undef; our $f = undef; our $F = undef; our $boite_liste = undef; our @liste = (); our $couleur_saisie = 'ivory'; our $couleur_lecture = 'LightSkyBlue'; our %delimiteurs = ( 'text:p' => { begin => undef, end => "\n" }, 'text:h' => { begin => '[Titre] ', end => "\n" }, 'text:list-item' => { begin => "\t* " }, %OpenOffice::OODoc::Text::DEFAULT_DELIMITERS ); #------------------------------------------------------------------------------ sub place_fenetre { my $fenetre = shift; my $x = int(($fenetre->screenwidth - $fenetre->reqwidth) / 2); my $y = int(($fenetre->screenheight - $fenetre->reqheight) / 2); $fenetre->geometry("+$x+$y"); $fenetre->resizable(0, 0); } #------------------------------------------------------------------------------ sub accesMeta { require Tk::LabFrame; require Tk::LabEntry; my $fichier = shift; my $oo_archive = ooFile($fichier); return undef unless $oo_archive; my $doc = ooMeta (archive => $oo_archive); return undef unless $doc; my $txt = ooText (archive => $oo_archive, delimiters => { %delimiteurs }); my ($titre, $auteur, $sujet, $description, @clefs, $mot); $f->idletasks; $D = $f->Toplevel ( -title => $fichier, ); $D->withdraw; my $fr2 = $D->Frame -> pack(-side => 'bottom', -expand => 1, -fill => 'x'); my $fr1 = $D->Frame ->pack(-side => 'left', -anchor => 'n'); my $fr3 = $D->LabFrame ( -label => 'Keywords', -labelside => 'acrosstop' ) ->pack(-side => 'right', -expand => 1, -fill => 'y'); $fr1->LabEntry ( -label => 'Title', -textvariable => \$titre, -width => 40, -bg => $couleur_saisie ) -> pack(-side => 'top', -fill => 'x'); $fr1->LabEntry ( -label => 'Author', -textvariable => \$auteur, -width => 40, -bg => $couleur_saisie ) -> pack(-side => 'top', -fill => 'x'); $fr1->LabEntry ( -label => 'Subject', -textvariable => \$sujet, -width => 40, -bg => $couleur_saisie ) -> pack(-side => 'top', -fill => 'x'); my $fr4 = $fr1->LabFrame ( -label => 'Description', ) -> pack(-side => 'top', -fill => 'x'); $description = $fr4->Scrolled ( 'Text', -scrollbars => 'ose', -height => 3, -width => 80, -bg => $couleur_saisie, -exportselection => 'yes' ) -> pack(-side => 'top', -fill => 'both'); my $fr5 = $fr1->LabFrame ( -label => 'Content', ) -> pack(-side => 'top', -fill => 'x'); my $texte = $fr5->Scrolled ( 'Text', -scrollbars => 'ose', -height => 20, -width => 90, -bg => $couleur_lecture, -exportselection => 'yes' ) -> pack(-side => 'top', -fill => 'both'); my $l = $fr3->Scrolled ( 'Listbox', -scrollbars => 'ose', -height => 20, -bg => $couleur_saisie, -exportselection => 'yes' ) -> pack(-side => 'top', -expand => 1, -fill => 'x'); $texte->bind ( '' => sub { push @clefs, $texte->get ('insert wordstart', 'insert wordend'); $l->see('end'); } ); my $nm = $fr3->Entry ( -textvariable => \$mot, -width => 18, -bg => $couleur_saisie ) -> pack(-side => 'bottom', -fill => 'x'); $nm->bind ( '' => sub { if ($mot) { push @clefs, $mot; $l->see('end'); $mot = ""; } } ); $l->bind ( '<1>' => sub { $l->focus; }); $l->bind ( '' => sub { my $s = $l->curselection; $l->selectionClear($s) if defined $s; } ); $l->bind ( '' => sub { my $s = $l->curselection; $l->delete($s) if defined $s; } ); $fr2->Button ( -text => 'OK', -command => sub { $doc->title($titre); $doc->creator($auteur); $doc->subject($sujet); $doc->description ( $description->get('1.0', 'end') ); $doc->removeKeywords; $doc->keywords(@clefs); $doc->save; $doc->dispose; $txt->dispose; $D->destroy; } ) -> pack(-side => 'left', -expand => 1, -fill => 'x'); $fr2->Button ( -text => 'Cancel', -command => sub { $doc->dispose; $txt->dispose; $D->destroy; } ) -> pack(-side => 'left', -expand => 1, -fill => 'x'); $D->bind('' => sub { $D->destroy }); $D->bind('' => sub { $f->deiconify; }); $D->update; place_fenetre($D); $f->withdraw; $D->deiconify; tie @clefs, "Tk::Listbox", $l; @clefs = $doc->keywords; shift @clefs unless $clefs[0]; $titre = $doc->title; $auteur = $doc->creator; $sujet = $doc->subject; $description->delete('1.0', 'end'); $description->insert('end', $doc->description); if ($txt) { $texte->insert('end', "Loading the text..."); $D->idletasks; $texte->delete('1.0', 'end'); foreach my $contenu ($txt->selectTextContent) { $texte->insert('end', ($contenu . "\n")); } } else { $texte->insert('end', "**** CONTENT NOT AVAILABLE ****"); } $texte->configure(-state => 'disabled'); $D->grab; } #------------------------------------------------------------------------------ sub listeFichiers { $chemin = $sv_chemin unless $chemin; my $r = chdir $chemin; unless ($r) { warn "$chemin is not available ; back to $sv_chemin\n"; $chemin = $sv_chemin; chdir $chemin or warn "$chemin is not available\n"; } return <*.sx?>; } #------------------------------------------------------------------------------ $f = MainWindow->new ( title => 'Documents', ); $r1 = $f->Frame->pack(-side => 'bottom', -fill => 'x'); my $dir = $f->Entry(-width => 32, -textvariable => \$chemin) ->pack(-side => 'bottom', -expand => 'yes'); $dir->bind('', sub { @liste = listeFichiers; }); $boite_liste = $f->Scrolled ( 'Listbox', -scrollbars => 'oe', -width => 32, -height => 16, -bg => $couleur_saisie ) ->pack(-side => 'top', -expand => 'yes'); my $OK = $r1->Button ( -text => 'OK', ) ->pack(-side => 'left', -expand => 1, -fill => 'x'); $OK->configure ( -command => sub { my $f = $liste[$boite_liste->curselection]; $OK->configure ( -text => 'Loading...' ); accesMeta($f) if ($f); $OK->configure ( -text => 'OK' ); } ); $boite_liste->bind ( '' => sub { my $f = $liste[($boite_liste->curselection)[0]]; $OK->configure ( -text => 'Loading...' ); accesMeta($f) if ($f); $OK->configure ( -text => 'OK' ); } ); my $Annuler = $r1->Button ( -text => 'Cancel', -command => [ $f => 'destroy' ] ) ->pack(-side => 'left', -fill => 'x'); $f->bind('' => sub { $f->destroy }); tie @liste, "Tk::Listbox", $boite_liste; @liste = listeFichiers; $boite_liste->selectionSet(0); place_fenetre($f); $OK->focus; #------------------------------------------------------------------------------ MainLoop; exit; #------------------------------------------------------------------------------