2003-09-06 12:55:42 -07:00
#!/usr/bin/perl
1999-09-30 14:50:59 -07:00
##############################################################################
2003-09-06 12:55:42 -07:00
# generates a file.menu format for Enlightenment out of menu hierarchies
#
2019-03-30 00:46:24 -07:00
# Copyright (C) 2003-2019 Kim Woelders
1999-10-04 13:52:25 -07:00
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
2003-09-06 12:55:42 -07:00
#
1999-10-04 13:52:25 -07:00
# The above copyright notice and this permission notice shall be included in
# all copies of the Software, its documentation and marketing & publicity
# materials, and acknowledgment shall be given in the documentation, materials
# and software packages that this Software was used.
2003-09-06 12:55:42 -07:00
#
1999-10-04 13:52:25 -07:00
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1999-09-30 14:50:59 -07:00
##############################################################################
2013-06-01 00:01:03 -07:00
#use strict;
#use warnings;
2003-09-06 12:55:42 -07:00
# Likely prefixes
2005-01-17 09:10:06 -08:00
$Prefixes = "/usr/local:/usr:/opt:/opt/kde:$ENV{'KDEDIR'}";
2006-03-29 12:18:00 -08:00
$Prefixes = "$Prefixes:/opt/kde3:/opt/gnome"; # SUSE
2009-11-21 03:13:16 -08:00
$Prefixes = "$Prefixes:$ENV{'HOME'}/.local";
2004-09-30 12:26:23 -07:00
$Prefixes = RemoveDuplcates($Prefixes);
2003-09-06 12:55:42 -07:00
2008-03-11 15:06:41 -07:00
# Where to look for GNOME/KDE stuff
$AppDirs = MkDirList($Prefixes, "/share/applications:/share/applications/kde:/share/applications/kde4");
2004-09-01 11:12:26 -07:00
2006-01-08 05:21:31 -08:00
$IconDirs = MkDirList($Prefixes, "/share/pixmaps:/share/icons");
$IconDirs2 = MkDirList($Prefixes, "/share/icons");
2019-03-30 00:46:24 -07:00
$Themes = "default.kde:gnome:hicolor:Adwaita";
2019-03-30 00:05:06 -07:00
$IconCats = "apps:filesystems:actions:devices:categories:places:mimetypes";
2003-09-06 12:55:42 -07:00
# Where to look for GNOME1 apps
$OldGnomeDirs = MkDirList($Prefixes, "/share/gnome/apps");
# Where to look for KDE1/2 apps
$OldKdeDirs = MkDirList($Prefixes, "/share/applnk");
# Pick up env vars
$EdirUser = "$ENV{'ECONFDIR'}";
$EdirRoot = "$ENV{'EROOT'}";
$EdirBin = "$ENV{'EBIN'}";
2004-06-13 13:47:39 -07:00
# Localization bits. There may be better ways to do this.
$Lang = "$ENV{'LANG'}";
$loc1 = $loc2 = $loc3 = $Lang;
$loc2 =~ s/[\.\@].*//;
$loc3 =~ s/_.*//;
$loc1 = "" if ($loc1 eq $loc2);
2004-12-28 15:46:49 -08:00
$EdirUser = "$ENV{'HOME'}/.e16" unless $EdirUser;
2019-03-30 00:05:06 -07:00
$EdirRoot = "/usr/share/e16" unless $EdirRoot;
2003-09-06 12:55:42 -07:00
$EdirBin = "/usr/bin" unless $EdirBin;
2004-12-28 15:46:49 -08:00
$EdirMenus = "$EdirUser/menus";
2003-09-06 12:55:42 -07:00
$dbg = "$ENV{'E_MENUGEN_DBG'}";
2013-06-01 00:01:03 -07:00
$dbg = 0 unless $dbg;
2003-09-06 12:55:42 -07:00
2003-10-25 06:11:46 -07:00
# Put EBIN first in path
$ENV{'PATH'} = "$EdirBin:$ENV{'PATH'}";
2003-09-06 12:55:42 -07:00
# Programs
2005-01-02 08:04:24 -08:00
$DoIconv = `which iconv`;
2003-09-06 12:55:42 -07:00
@CatsRemove = (
2019-12-09 08:46:10 -08:00
"ConsoleOnly",
2003-09-06 12:55:42 -07:00
"Qt",
2004-09-01 11:12:26 -07:00
"QT",
2006-01-08 05:21:31 -08:00
"GTK",
2003-09-06 12:55:42 -07:00
"GNOME",
"KDE",
"UtilityApplication",
"Applications",
"Application",
2006-01-08 05:21:31 -08:00
"X-.*",
2003-09-06 12:55:42 -07:00
);
@MainMenu = (
"t:User Menus",
2007-05-28 10:20:43 -07:00
"m:User Application List:user_apps.menu",
2011-07-17 11:43:19 -07:00
"m:Applications:menus_apps/index.menu",
2007-11-15 12:03:56 -08:00
"m:Epplets:epplets.menu",
"c:Restart:exit restart",
2005-01-17 09:10:06 -08:00
"c:Log Out:exit logout"
2003-09-06 12:55:42 -07:00
);
@UserAppsMenu = (
"t:User Application List",
"x:Eterm:Eterm",
2008-08-31 21:56:31 -07:00
"x:Terminal:Terminal",
2003-09-06 12:55:42 -07:00
"x:XTerm:xterm",
2006-10-05 12:07:59 -07:00
"x:rxvt:rxvt",
"x:urxvt:urxvt",
2004-06-06 13:05:09 -07:00
"x:Firefox:firefox",
2019-03-30 00:46:24 -07:00
"x:Thunderbird:thunderbird",
"x:Seamonkey:seamonkey",
"x:Shotwell:shotwell",
"x:Pidgin:pidgin",
2004-06-06 13:05:09 -07:00
"x:Gmplayer:gmplayer",
"x:Xine:xine",
2003-09-06 12:55:42 -07:00
"x:The GIMP:gimp",
2019-03-30 00:46:24 -07:00
"x:Geeqie:geeqie",
2006-10-05 12:07:59 -07:00
"x:XV:xv",
2003-09-06 12:55:42 -07:00
"x:XMag:xmag",
2006-10-05 12:07:59 -07:00
"x:Grip:grip",
2010-04-16 04:07:54 -07:00
"x:Audacious:audacious",
2003-09-06 12:55:42 -07:00
"x:XMMS:xmms"
);
2004-09-30 12:26:23 -07:00
# Remove duplicates and nulls in ':' separated dir list
sub RemoveDuplcates {
local $dl = shift;
local @r;
local %h;
foreach $p (split(':', $dl)) {
next unless $p;
next if $h{$p};
$h{$p} = $p;
push @r, $p;
}
return join(':', @r);
}
2003-09-06 12:55:42 -07:00
# Make : separated directory list, check that they exist
sub MkDirList {
2004-09-30 12:26:23 -07:00
local $dl = shift;
2003-09-06 12:55:42 -07:00
local $sf = shift;
local $d;
local @r;
2004-09-30 12:26:23 -07:00
foreach $p (split(':', $dl)) {
2004-09-01 11:12:26 -07:00
foreach $q (split(':', $sf)) {
$d = "$p$q";
push(@r, "$d") if -d "$d";
}
2003-09-06 12:55:42 -07:00
}
return join(':', @r);
}
# Make dir if non-existing
sub MkDir {
local $d = shift;
mkdir("$d") unless (-d "$d");
}
# Make simple menus
sub MakeMenu {
local $f = shift;
local $m = shift;
2004-12-28 15:46:49 -08:00
$f = "$EdirMenus/$f";
2003-10-25 06:11:46 -07:00
return if (-f "$f");
2003-09-06 12:55:42 -07:00
open(FD, ">$f");
foreach $e (@$m) {
($t, $n, $p) = split(':', $e);
if ($t eq "t") {
print FD "\"$n\"\n";
} elsif ($t eq "m") {
print FD "\"$n\" NULL menu \"$p\"\n";
} elsif ($t eq "x") {
print FD "\"$n\" NULL exec \"$p\"\n";
2005-01-17 09:10:06 -08:00
} elsif ($t eq "c") {
print FD "\"$n\" NULL \"$p\"\n";
2003-09-06 12:55:42 -07:00
}
}
close(FD);
}
# Process a .desktop file
sub ProcessFile {
local $f = shift;
2013-06-01 00:01:03 -07:00
local ($Name, $Exec, $Icon, $Cats, $Type, $Ndis, $File);
2003-09-06 12:55:42 -07:00
2003-12-11 10:02:02 -08:00
if (! -f "$f") {
print "Not found: $f\n" if $dbg ge 1;
return;
}
2003-09-06 12:55:42 -07:00
# Global ref no
$N++;
2011-07-17 11:43:14 -07:00
$Name = $Exec = $Icon = $Ndis = "";
2004-06-13 13:47:39 -07:00
$Nam1 = $Nam2 = $Nam3 = "";
2003-09-06 12:55:42 -07:00
$Cats = shift;
$Type = shift;
2003-12-11 10:02:02 -08:00
open(FI,$f) or return;
2003-09-06 12:55:42 -07:00
while (<FI>) {
2009-08-04 09:11:30 -07:00
s/\s+$//;
2013-10-05 02:16:27 -07:00
if (/^\[(\w+)\s+(\w+)/) {
# Note: This breaks if [Desktop Entry] is not the first
last if (($1 ne "Desktop") or ($2 ne "Entry"));
2019-10-03 08:50:51 -07:00
}
# skip early for the unneeded ones (important optimization):
next if (/^(#|Comment|GenericName|Keywords|TryExec|Icon\[|StartupNotify|MimeType|NotShowIn|DBusActivatable|X-|Version|TargetEnvironment|MultipleArgs|Encoding|Actions)/);
if (/^Name/) {
if (/^Name=(.*)$/) {
$Name = $1;
} elsif ($loc1 && /^Name\[$loc1\]=(.*)$/) {
$Nam1 = $1;
} elsif ($loc2 && /^Name\[$loc2\]=(.*)$/) {
$Nam2 = $1;
} elsif ($loc3 && /^Name\[$loc3\]=(.*)$/) {
$Nam3 = $1;
}
if ($Nam1 || $Nam2 || $Nam3) {
if ($Nam1) { $Name = $Nam1; }
elsif ($Nam2) { $Name = $Nam2; }
else { $Name = $Nam3; }
$Name = `echo "$Name" | iconv -f UTF-8` if $DoIconv;
chomp($Name);
}
2003-09-06 12:55:42 -07:00
} elsif (/^Exec=(.*)$/) {
$Exec = $1;
} elsif (/^Icon=(.*)$/) {
$Icon = $1;
} elsif (/^OnlyShowIn=(.*);$/) {
$Type = $1;
} elsif (/^Categories=(.*)$/) {
next if "$Cats"; # Given
2006-01-08 05:21:31 -08:00
CF: foreach $cf (split(';', $1)) {
if ($cf eq "KDE") {
$Type = "KDE";
next;
}
foreach $cr (@CatsRemove) {
next CF if ($cf =~ /^$cr$/);
}
$Cats = "$Cats$cf;";
}
2003-09-06 12:55:42 -07:00
} elsif (/^Type=(.*)$/) {
if ($1 ne "Application") {
$Name = "";
last;
}
2011-07-17 11:43:14 -07:00
} elsif (/^NoDisplay=(.*)$/) {
$Ndis = $1;
2003-09-06 12:55:42 -07:00
}
}
close FI;
$Cats =~ s/ +$//;
2011-07-17 11:43:14 -07:00
if ($Ndis eq "true" || !$Name || !$Exec || !$Cats) {
printf("Skipped: %-24s %-4s %-24s %-20s %-20s %s\n",
$f, $Name, $Ndis, $Exec, $Icon, $Cats) if $dbg ge 1;
2003-09-06 12:55:42 -07:00
return;
}
# Basename
$File = $f; $File =~ s/^.*\///;
printf("%-24s: %-24s %-20s %-20s %s\n",
$File, $Name, $Exec, $Icon, $Cats) if $dbg ge 3;
if (!$Type) {
if ($File =~ /^gnome/) {
$Type = "GNOME";
} elsif ($File =~ /^kde/) {
$Type = "KDE";
} else {
$Type = "Other";
}
}
$Namx = "$Name-$N"; # Make key unique
$Namx =~ tr/A-Z/a-z/; # To lower case (for sorting)
2006-01-03 09:28:04 -08:00
$Exec =~ s/\s*%(f|F|i|k|m|n|N|u|U|v)//g; # Strip unwanted args
$Exec =~ s/\s*-\w+\s*"%c"//g; # Strip option with caption
# $Exec =~ s/"%c"/'$Name'/g; # Alternatively - Substitute caption
2003-09-06 12:55:42 -07:00
$File{$Namx} = $File;
$Name{$Namx} = $Name;
$Exec{$Namx} = $Exec;
$Icon{$Namx} = $Icon;
$Cats{$Namx} = $Cats;
$Type{$Namx} = $Type;
}
2019-03-30 00:05:06 -07:00
my %seen;
2003-09-06 12:55:42 -07:00
# Process all .desktop files in a directory
sub ProcessDir {
local $d = shift;
local $dx = shift;
local $t = shift;
local @l;
local $f;
@l = grep /\.desktop$/, ReadDir($d);
2004-06-13 13:47:39 -07:00
foreach $f (@l) {
2019-03-30 00:05:06 -07:00
next if ($seen{$f});
$seen{$f} = 1;
2003-09-06 12:55:42 -07:00
$f = "$d/$f";
print "- File $f\n" if $dbg ge 2;
ProcessFile("$f", "$dx", "$t");
}
}
# Process old style GNOME/KDE directories
sub ProcessOldStyle {
local $t = shift;
local $dl = shift;
2013-06-01 00:01:03 -07:00
local ($d, $d2);
2003-09-06 12:55:42 -07:00
local @d2l;
foreach $d (split(':', $dl)) {
print "Processing directory: $d\n" if $dbg ge 1;
if (! -d "$d") {
print "- Not found\n" if $dbg ge 1;
next;
}
@d2l = grep !/^\./, ReadDir($d);
2004-06-13 13:47:39 -07:00
foreach $d2 (@d2l) {
2003-09-06 12:55:42 -07:00
print " Subdir: $d/$d2\n" if $dbg ge 1;
next unless -d "$d/$d2";
ProcessDir("$d/$d2", "$d2", "$t");
}
}
}
# Find that $#@! thing
sub FindIcon {
local $f = shift;
2006-01-16 04:45:56 -08:00
local $x = "x";
2003-09-06 12:55:42 -07:00
return $f if (! $f);
2006-01-16 04:45:56 -08:00
return $f if (-f $f);
2003-09-06 12:55:42 -07:00
2004-06-13 13:47:39 -07:00
foreach $d (split(':', $IconDirs)) {
2003-09-06 12:55:42 -07:00
$i = "$d/$f";
2006-01-08 05:21:31 -08:00
unless (-f $i) {
next if ($f =~ /\.png$/);
$i = "$i.png";
next unless -f $i;
}
2003-09-06 12:55:42 -07:00
return $i;
}
2006-01-08 05:21:31 -08:00
foreach $d (split(':', $IconDirs2)) {
2006-01-16 04:45:56 -08:00
next unless (-d "$d");
2004-06-13 13:47:39 -07:00
foreach $t (split(':', $Themes)) {
2006-01-16 04:45:56 -08:00
next unless (-d "$d/$t");
2009-04-28 12:35:20 -07:00
foreach $s (split(':', "48:32:24:16")) {
2007-11-03 03:31:31 -07:00
$S = "$d/$t/$s$x$s";
next unless (-d "$S");
if ($f =~ /^stock/) {
$i = "$S/stock/*/$f.png";
$ii = glob("$i");
2006-01-16 04:45:56 -08:00
print "Testing $i\n" if $dbg >= 2;
2007-11-03 03:31:31 -07:00
return $ii if (-f $ii);
} else {
foreach $u (split(':', $IconCats)) {
next unless (-d "$S/$u");
$i = "$S/$u/$f";
if ($f =~ /\.png|\.xpm$/) {
print "Testing $i\n" if $dbg >= 2;
return $i if (-f $i);
} else {
$ii = "$i.png";
print "Testing $ii\n" if $dbg >= 2;
return $ii if (-f $ii);
$ii = "$i.xpm";
print "Testing $ii\n" if $dbg >= 2;
return $ii if (-f $ii);
}
}
2006-01-16 04:45:56 -08:00
}
2003-09-06 12:55:42 -07:00
}
}
}
return $f;
}
# Make the Epplets menu
sub MakeEppsMenu {
local $f = shift;
2005-06-05 15:03:58 -07:00
local $d;
local %done;
2004-12-28 15:46:49 -08:00
open(FD, ">$EdirMenus/$f");
2003-09-28 12:23:42 -07:00
print FD "\"Enlightenment Epplets\"\n";
2005-06-05 15:03:58 -07:00
foreach $d (split(':', $ENV{'PATH'})) {
2005-06-10 14:55:22 -07:00
next unless -d $d;
2005-06-05 15:03:58 -07:00
next if ($done{$d});
$done{$d} = 1;
print "Looking for epplets in $d\n" if $dbg ge 1;
@el = grep /\.epplet$/, ReadDir($d);
foreach $e (@el) {
$e =~ s/\.epplet$//;
$i = "$EdirRoot/epplet_icons/$e.icon";
print FD "\"$e\" \"$i\" exec \"$d/$e.epplet\"\n";
}
2003-09-06 12:55:42 -07:00
}
close(FD);
}
# Make the menu for a given app type
sub MakeAppsMenu {
local $type = shift;
local %menus;
2013-06-01 00:01:03 -07:00
local ($c, $k, $dir);
2003-09-06 12:55:42 -07:00
2004-12-28 15:46:49 -08:00
$dir = "$EdirMenus/menus_$type";
2007-05-28 10:20:43 -07:00
$mdir = "menus_$type";
2003-09-06 12:55:42 -07:00
print "Generating Menu: $type in $dir\n" if $dbg ge 1;
MkDir($dir);
# Sort the apps into categories
foreach $k (sort(keys(%Name))) {
2011-07-17 11:43:19 -07:00
# next if ($Type{$k} ne $type);
2003-09-06 12:55:42 -07:00
$c = $Cats{$k};
$c =~ s/;.*$//;
# $menus{$c} = $k;
push(@{$menus{$c}}, $k);
}
# Make top- and sub-menus
2003-12-11 10:02:02 -08:00
open(FTopM, ">$dir/index.menu") or die "*** Couldn't create $dir/index.menu\n";
2003-09-06 12:55:42 -07:00
print FTopM "\"$type Menu\"\n";
foreach $m (sort(keys(%menus))) {
2003-12-11 10:02:02 -08:00
open(FSubM, ">$dir/$m.menu") or die "*** Couldn't create $dir/$m.menu\n";
2003-09-06 12:55:42 -07:00
print "- Submenu: $m\n" if $dbg ge 2;
2007-05-28 10:20:43 -07:00
print FTopM "\"$m\" \"\" menu \"$mdir/$m.menu\"\n";
2003-09-06 12:55:42 -07:00
print FSubM "\"$m\"\n";
foreach $k (sort(@{$menus{$m}})) {
print " - Item: $k\n" if $dbg ge 2;
$icon = FindIcon($Icon{$k});
printf FSubM "\"%s\" \"%s\" exec \"%s\"\n",
2006-01-03 09:28:04 -08:00
$Name{$k}, $icon, $Exec{$k};
2003-09-06 12:55:42 -07:00
}
close(FSubM);
}
close(FTopM);
}
# Return list of files in dir
sub ReadDir {
local $dir = shift;
local @dirs;
2008-11-03 09:28:52 -08:00
if (!opendir DH, $dir) { print "*** Could not open: $dir\n"; return 0; }
2003-09-06 12:55:42 -07:00
@dirs = readdir DH;
closedir DH;
return @dirs;
}
# Close all windows named "Message" (we assume they are E dialogs)
sub CloseMessageWindows {
2007-11-15 11:54:32 -08:00
system("eesh -e 'wop Message* close' >/dev/null");
2003-09-06 12:55:42 -07:00
}
##############################################################################
# Here we go
##############################################################################
$N = 0;
CloseMessageWindows();
system("eesh -e \"dialog_ok Menus are being generated... Please Wait.\"");
# Process old style GNOME directories
ProcessOldStyle("GNOME", "$OldGnomeDirs");
# Process old style KDE directories
ProcessOldStyle("KDE", "$OldKdeDirs");
# Process new style (GNOME2, KDE2/3) directories
foreach $d (split(':', $AppDirs)) {
print "Processing directory: $d\n" if $dbg ge 1;
if (! -d $d) {
print "- Not found\n" if $dbg ge 1;
next;
}
2013-06-01 00:01:03 -07:00
ProcessDir($d, "", "");
2003-09-06 12:55:42 -07:00
}
2004-12-28 15:46:49 -08:00
# Make menu dir and scaled icon dir
MkDir("$EdirMenus");
2003-09-06 12:55:42 -07:00
# Make the menus
2011-08-24 13:45:08 -07:00
# If file.menu exists replace old GNOME/KDE/Other menus with combined one
$f = "$EdirMenus/file.menu";
if (-f $f) {
$cmd = 'print unless (/menus_(GNOME|KDE|Other)/); print "\"Applications\" NULL menu \"menus_apps/index.menu\"\n" if (/menus_Other/);';
system("perl -ni -e '$cmd' $f");
} else {
MakeMenu("file.menu", \@MainMenu);
}
2003-09-06 12:55:42 -07:00
MakeMenu("user_apps.menu", \@UserAppsMenu);
MakeEppsMenu("epplets.menu");
2011-07-17 11:43:19 -07:00
MakeAppsMenu("apps");
2003-09-06 12:55:42 -07:00
CloseMessageWindows();
2004-12-28 15:46:49 -08:00
system("eesh -e 'menus reload'");
2003-09-06 12:55:42 -07:00
system("eesh -e 'dialog_ok Menu generation complete.'");