[gimp-perl] Add registry_viewer.



commit 7423d67d40f638dcf37ba5e46fb94383abe32d64
Author: Ed J <edj src gnome org>
Date:   Wed May 28 21:38:10 2014 +0100

    Add registry_viewer.

 MANIFEST                 |    1 +
 Makefile.PL              |    1 +
 examples/Makefile.PL     |    1 +
 examples/registry_viewer |  352 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 355 insertions(+), 0 deletions(-)
---
diff --git a/MANIFEST b/MANIFEST
index 9eb8aea..059eeb4 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -78,6 +78,7 @@ examples/randomart1
 examples/randomblends
 examples/README
 examples/redeye
+examples/registry_viewer
 examples/repdup
 examples/scratches
 examples/selective_sharpen
diff --git a/Makefile.PL b/Makefile.PL
index f3549ff..9cdeb3d 100644
--- a/Makefile.PL
+++ b/Makefile.PL
@@ -52,6 +52,7 @@ WriteMakefile(
     ExtUtils::PkgConfig        => 0,
     Gtk2::Ex::PodViewer        => 0,
     IO::Scalar         => 0,
+    Web::Scraper       => 0,
   },
   META_MERGE => {
     "meta-spec" => { version => 2 },
diff --git a/examples/Makefile.PL b/examples/Makefile.PL
index cfabd3e..29cef85 100644
--- a/examples/Makefile.PL
+++ b/examples/Makefile.PL
@@ -11,6 +11,7 @@ our %cfg;
 my @pins = qw(
   Perl-Server
   Perl-Console
+  registry_viewer
   dataurl
   example-fu
   exceptiontest
diff --git a/examples/registry_viewer b/examples/registry_viewer
new file mode 100755
index 0000000..7b126d3
--- /dev/null
+++ b/examples/registry_viewer
@@ -0,0 +1,352 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Gimp;
+use Gimp::Fu;
+
+sub process;
+sub scraper(&);
+
+sub filesize_str {
+  my $size = $_[0];
+  ($size > 1099511627776)
+   ? sprintf ( "%.2f TiB", $size/1099511627776 )
+   : ( $size > 1073741824 )
+   ? sprintf ( "%.2f GiB", $size/1073741824 )
+   : ( $size > 1048576 )
+   ? sprintf ( "%.2f MiB", $size/1048576 )
+   : ( $size > 1024 )
+   ? sprintf ( "%.2f KiB", $size/1024 )
+   : ("$size byte" . ( $size == 1 ? "" : "s" ))
+}
+
+sub scraper_init {
+  my $h = {
+    list => scraper {
+      process '#block-system-main div.node > h2', 'content[]' => scraper {
+        process '>a[href]', link => '@href', title => sub { $_->as_trimmed_text }
+      }
+    },
+
+    pager => scraper {
+      process '#block-system-main li.pager-next a[href]', link => '@href'
+    },
+
+    node => scraper {
+      process 'div.node-scriptfu', 'classes' => sub {
+        my $c = $_->attr('class');
+        $c ? +{ map { ($_=>1) } split ' ', $c } : ()
+      },
+         node => scraper {
+           process 'span.submitted', 'submit-date' => sub {
+             (my $x = ($_->content)[0][0]) =~ s/\s*\x{2014}\s*$//;
+             $x
+           };
+           process 'span.submitted > span.username', 'author' => 'TEXT';
+           process '.field-name-body .field-items > .field-item',
+           body => 'TEXT';
+           process '.field-name-upload span.file > a[href]',
+           'files[]' => scraper {
+             process 'a[href]', name => '@title', link => '@href',
+             desc => 'TEXT',
+             size => sub {
+               $_->attr('type')
+                && $_->attr('type') =~ /length=(\d+)/
+                && $1
+             };
+           };
+           process '.field-type-taxonomy-term-reference',
+           'taxonomy[]' => scraper {
+             process '.field-label', name => sub {
+               (my $x = lc ($_->as_text)) =~ s/\W+/-/g;
+               $x =~ s/-+$//;
+               $x
+             };
+             process '.field-item > a[href]', 'values[]' => 'TEXT';
+           }
+        }
+   },
+    pos => 0,
+  };
+  my $uri = URI->new( "http://registry.gimp.org/taxonomy/term/20"; );
+  if (my $r_stubs = $h->{list}->scrape($uri)) {
+    $h->{stubs} = $r_stubs->{content};
+    if (my $next = $h->{pager}->scrape($uri)) {
+      $h->{next_uri} = URI->new($next->{link});
+    }
+    return $h;
+  }
+}
+
+sub get_next_plugin {
+  my ($h) = @_;
+  return unless $h && $h->{list};
+  while (1) {
+    while (@{ $h->{stubs} }) {
+      $h->{pos}++;
+      my $stub = shift @{ $h->{stubs} };
+      if (my $r_node = $h->{node}->scrape ($stub->{link})) {
+        if ($r_node->{node}) {
+          $stub->{$_} = $r_node->{node}{$_} for keys %{ $r_node->{node} };
+          if ($stub->{taxonomy}) {
+            my $tx = {};
+            for my $t ( @{ $stub->{taxonomy} }) {
+              $tx->{$t->{name}} = +{ map { ($_=>1) } @{ $t->{values} }};
+            }
+            $stub->{taxonomy} = $tx;
+            @{ $stub->{files} }
+            = grep $_->{link} =~ /\.scm$/, @{ $stub->{files} };
+          }
+        }
+        return $stub;
+      }
+    }
+    my $count;
+    if ($h->{next_uri}) {
+      if (my $r_page = $h->{list}->scrape($h->{next_uri})) {
+        push @{ $h->{stubs} }, @{ $r_page->{content} };
+        $count = @{ $r_page->{content} };
+      }
+      if (my $next = $h->{pager}->scrape($h->{next_uri})) {
+        $h->{next_uri} = URI->new($next->{link});
+        next;
+      } else {
+        delete $h->{next_uri};
+      }
+    }
+    return if !$count && !$h->{next_uri};
+  }
+}
+
+sub filter_plugin {
+  ref ($_[0]) eq 'HASH'
+   and $_[0]{files}
+  and @{ $_[0]{files} }
+  and $_[0]{taxonomy}{'gimp-version'}
+  and ($_[0]{taxonomy}{'gimp-version'}{2.7}
+       || $_[0]{taxonomy}{'gimp-version'}{2.8})
+  and $_[0]
+}
+
+# RETURNS $file, $dir
+sub fetch_file {
+  my ($uri, $dir, $u2lf, $file) = @_;
+  return unless $uri = URI->new($uri);
+  # (warn "already fetched file: $file"),
+  return ($file, $dir)
+   if ($u2lf && ($file = $u2lf->{$uri}) && -r $file && -s $file);
+
+  $dir = undef if $dir && !-w $dir;
+  if ($dir ||= File::Temp->newdir()) {
+    # warn LWP::Simple::get($uri);
+    my $rc = LWP::Simple::getstore(
+      $uri->as_string, $file = "$dir/".($uri->path_segments)[-1]);
+    # (warn "fetched file: $file"),
+    return ($u2lf->{$uri} = $file, $dir)
+     if (LWP::Simple::is_success($rc) && -s $file);
+
+    warn "couldn't fetch '$uri' to '$file': $rc";
+  } else {
+    warn "couldn't make temp dir: $!";
+  }
+  ()
+}
+
+podregister {
+  require Gimp::Config;
+  require Gtk2::SimpleList;
+  require File::Temp;
+  require URI;
+  require LWP::Simple;
+  require IO::All; IO::All->import;
+  require Web::Scraper; Web::Scraper->import;
+
+  Gimp::gtk_init;
+  my $d = Gtk2::Dialog->new("Browse/Install Plugins", undef,
+                            [qw(modal destroy-with-parent)],
+                            'Done' => 'close');
+  $d->set_default_response('close');
+  my $ca = $d->get_content_area;
+
+  my $box1 = Gtk2::VBox->new (FALSE, 2);
+  my $box2 = Gtk2::VBox->new (FALSE, 2);
+  my $box3 = Gtk2::VBox->new (FALSE, 2);
+
+  my $tbl = Gtk2::Table->new(1,2);
+  my $s = Gtk2::ScrolledWindow->new(undef,undef);
+  $s->set_policy ('automatic', 'automatic');
+  $s->set_size_request (300, 500);
+
+  my $t = Gtk2::ScrolledWindow->new(undef,undef);
+  $t->set_policy ('automatic', 'automatic');
+  $t->set_size_request (300, 500);
+
+  my $tv = Gtk2::TextView->new;
+  $tv->set_editable(FALSE);
+  my $b = $tv->get_buffer;
+
+  $tbl->set_border_width(6);
+  $tbl->set_col_spacings(6);
+  my $list = Gtk2::SimpleList->new('Script' => 'text');
+  my $l2;
+  my $status = Gtk2::Label->new('');
+
+  my @nlist;
+
+  $list->signal_connect (
+    cursor_changed => sub {
+      my ($i) = $_[0]->get_selected_indices();
+      $tv->set_cursor_visible(FALSE);
+      $tv->set_wrap_mode('word');
+      $b->set_text($nlist[$i][0]);
+      my $rows = @{$nlist[$i][1]};
+
+      $l2->destroy() if $l2;
+      $l2 = Gtk2::Table->new($rows+1,3);
+      $l2->attach_defaults(Gtk2::Label->new('Files'), 0, 3, 0, 1);
+      $box2->pack_start($l2,FALSE,TRUE,0);
+      my $r = 1;
+
+      for my $f (@{$nlist[$i][1]}) {
+        $l2->attach_defaults(
+          Gtk2::Label->new(($f->{name} || $f->{desc} || $f->{link})
+          . " (".filesize_str($f->{size}).")"),
+          0, 1, $r, $r+1);
+
+        $l2->attach(
+          my $vbtn = Gtk2::Button->new("View"), 1, 2, $r, $r+1,
+          'shrink','fill', 2, 2);
+        $l2->attach(
+          my $ibtn = Gtk2::Button->new ("Install"), 2, 3, $r, $r+1,
+          'shrink','fill', 2, 2);
+        ++$r;
+
+        my ($dir, %url2localfiles);
+
+        $vbtn->signal_connect(
+          clicked => sub {
+            $status->set_text('fetching: '.$f->{link});
+            (my $file, $dir) = fetch_file($f->{link}, $dir,
+                                          \%url2localfiles);
+            return unless $file;
+            if (my $text = io($file)->all) {
+              $tv->set_cursor_visible(TRUE);
+              $tv->set_wrap_mode('none');
+              $b->set_text($text);
+            }
+            $status->set_text('');
+          });
+
+        $ibtn->signal_connect(
+          clicked => sub {
+            $status->set_text('fetching: '.$f->{link});
+            (my $file, $dir) = fetch_file($f->{link}, $dir,
+                                          \%url2localfiles);
+            return unless $file;
+              $status->set_text('installing: '.$f->{name}||$f->{desc});
+            die "couldn't $Gimp::Config{GIMPTOOL} --install-script $file: $!"
+             unless
+             system ($Gimp::Config{GIMPTOOL}, '--install-script', $file) == 0;
+            $status->set_text('installed, refreshing');
+            Gimp->script_fu_refresh();
+            $status->set_text("installed ". $f->{name}||$f->{desc});
+          });
+      }
+      $l2->show_all();
+      $box2->show();
+    });
+
+  $ca->add($box1);
+  $ca->add($box3);
+  $box1->pack_start($tbl,TRUE,TRUE,0);
+  $box1->pack_start($status,FALSE,FALSE,0);
+  $tbl->attach_defaults($s, 0, 1, 0, 1);
+  $tbl->attach_defaults($box2, 1, 2, 0, 1);
+  $box2->pack_start($t,TRUE,TRUE,0);
+  $s->add($list);
+  $t->add($tv);
+
+  $d->show_all();
+  $box2->hide();
+  $box3->hide();
+
+  die "Failed to load web scraper, sorry."
+   unless my $s_hash = scraper_init();
+
+  Glib::Idle->add(
+    sub {
+      $status->set_text('');
+      if (my $p_hash = get_next_plugin($s_hash)) {
+        $status->set_text(
+          "checking $p_hash->{title}" .
+          ($p_hash->{taxonomy} && $p_hash->{taxonomy}{'gimp-version'}
+           ? (" (Gimp " . join (
+                ',', sort keys %{$p_hash->{taxonomy}{'gimp-version'}})
+              . ")")
+           : ''));
+        # print "got: ", Dumper ($p_hash);
+        if (filter_plugin ($p_hash)) {
+          push @{ $list->{data} }, $p_hash->{title};
+          push @nlist, [$p_hash->{body}, $p_hash->{files}];
+        }
+        # print "USING\n" if filter_plugin ($p_hash);
+        @nlist > 39 ? $status->set_text('') && 0 : 1;
+      }
+    });
+
+  my $rsp = $d->run;
+  $d->destroy;
+
+  ()
+};
+exit main;
+# if (my $s = scraper_init) {
+#   my $i = 0;
+#   while (my $h = get_next_plugin($s)) {
+#     print $h->{title}, "\n";
+#   }
+# }
+
+__END__
+
+=head1 NAME
+
+registry_viewer - Browse the gimp plugin registry
+
+=head1 SYNOPSIS
+
+<Toolbox>/Filters/Languages/Browse Pl_ug-in Registry
+
+=head1 DESCRIPTION
+
+Browse scripts from http://registry.gimp.org.
+
+Currently only shows scriptfu scripts compatible with Gimp 2.8.
+
+Requires Web::Scraper.
+
+=head1 PARAMETERS
+
+=head1 AUTHOR
+
+Rain <rain AT terminaldefect DOT com>
+
+=head1 DATE
+
+2014-05-19
+
+=head1 LICENSE
+
+This program 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 3 of the License, or (at your option) any later
+version.
+
+This program 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, see <http://www.gnu.org/licenses/>.


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]