aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Auth.pm50
-rw-r--r--Category.pm132
-rw-r--r--ConfigReader.pm111
-rw-r--r--MainDisplay.pm330
-rw-r--r--Module.pm57
-rw-r--r--SettingsReader.pm44
-rwxr-xr-xapanel.pl76
-rw-r--r--categories.conf36
-rw-r--r--extras/README10
-rw-r--r--extras/org.freedesktop.policykit.pkexec.policy22
-rw-r--r--images/logo_mageia.pngbin0 -> 2425 bytes
-rw-r--r--images/mageia.pngbin0 -> 1788 bytes
-rw-r--r--images/quit.pngbin0 -> 2880 bytes
-rw-r--r--modules/test.cpp137
-rw-r--r--settings.conf9
15 files changed, 1014 insertions, 0 deletions
diff --git a/Auth.pm b/Auth.pm
new file mode 100644
index 00000000..c55e0678
--- /dev/null
+++ b/Auth.pm
@@ -0,0 +1,50 @@
+# Copyright 2012 Matteo Pasotti
+#
+# This file is part of mcc2
+#
+# mcc2 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.
+#
+# mcc2 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 mcc2. If not, see <http://www.gnu.org/licenses/>.
+
+package Auth;
+
+require Exporter;
+@ISA = qw(Exporter);
+@EXPORT = qw(require_root_capability
+ ask_for_authentication);
+
+use strict;
+use warnings;
+use diagnostics;
+use Data::Dumper;
+
+
+sub require_root_capability {
+ return 0 if(!$>);
+ return 1;
+}
+
+sub ask_for_authentication {
+ my @args = @ARGV;
+ my $command = wrap_command($0);
+ unshift(@args, $command->[2]);
+ exec { $command->[0] } $command->[1], @args or die ("command %s missing", $command->[0]);
+ die "You must be root to run this program" if $>;
+}
+
+sub wrap_command {
+ my $currenv = "env";
+ my $wrapper = "pkexec";
+ my $app = $0;
+ my $command = [$wrapper, $currenv, $app];
+ ($command);
+}
diff --git a/Category.pm b/Category.pm
new file mode 100644
index 00000000..6e4a58d4
--- /dev/null
+++ b/Category.pm
@@ -0,0 +1,132 @@
+# Copyright 2012 Steven Tucker
+#
+# This file is part of AdminPanel
+#
+# AdminPanel 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.
+#
+# AdminPanel 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 AdminPanel. If not, see <http://www.gnu.org/licenses/>.
+
+
+#Class Category
+package Category;
+
+use strict;
+use warnings;
+use diagnostics;
+use yui;
+
+## Can only add the config file data at constructor
+## The Gui elements are added in setupGui inside MainDisplay
+sub new {
+ my ($class, $newName, $newIcon) = @_;
+ my $self = {
+ my $name = 0,
+ my $button = 0,
+ my $icon = 0,
+ my $modules = 0
+ };
+ bless $self, 'Category';
+
+ $self->{name} = $newName;
+ $self->{icon} = $newIcon;
+
+ return $self;
+}
+
+## Add a new module to the list
+sub loadModule {
+ my ($self, $module) = @_;
+
+ push ( @{$self->{modules}}, $module );
+
+}
+
+## Create and add buttons for each module
+sub addButtons {
+ my($self, $pane, $factory) = @_;
+ my $count = 0;
+ my $tmpButton;
+ my $currLayout = 0;
+ $factory->createVSpacing($pane, 2);
+ foreach my $mod (@{$self->{modules}}) {
+ if(($count % 2) != 1)
+ {
+ $currLayout = $factory->createHBox($pane);
+ $factory->createHStretch($currLayout);
+ }
+ $count++;
+ $tmpButton = $factory->createPushButton($currLayout,
+ $mod->{name}
+ );
+ $mod->setButton($tmpButton);
+ $tmpButton->setLabel($mod->{name});
+ $tmpButton->setIcon($mod->{icon});
+ $factory->createHStretch($currLayout);
+ if(($count % 2) != 1)
+ {
+ $factory->createVSpacing($pane, 2);
+ }
+ }
+ $factory->createVStretch($pane);
+}
+
+## Delete the module buttons
+sub removeButtons {
+ my($self) = @_;
+
+ for(@{$self->{modules}}) {
+ $_->removeButton();
+ }
+}
+
+sub setIcon {
+ my($self) = @_;
+
+ $self->{button}->setIcon($self->{icon});
+}
+
+1;
+__END__
+
+=pod
+
+=head1 NAME
+
+ Category - add new category to window
+
+=head1 SYNOPSIS
+
+ $category = new Category('Category Name');
+
+
+=head1 USAGE
+
+ my $display = new MainDisplay();
+
+ my $category = new Category('Network');
+ $display->loadCategory($category);
+
+ $display->start();
+
+=head1 FUNCTIONS
+
+=head2 new (name)
+
+ Constructor: creates a new category named Name
+
+ $category = new Category('Name');
+
+=head3 name (String)
+
+ The name of the category
+
+=cut
diff --git a/ConfigReader.pm b/ConfigReader.pm
new file mode 100644
index 00000000..22d3b495
--- /dev/null
+++ b/ConfigReader.pm
@@ -0,0 +1,111 @@
+# Copyright 2012 Steven Tucker
+#
+# This file is part of AdminPanel
+#
+# AdminPanel 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.
+#
+# AdminPanel 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 AdminPanel. If not, see <http://www.gnu.org/licenses/>.
+
+
+#Class ConfigReader
+package ConfigReader;
+
+use strict;
+use warnings;
+use diagnostics;
+use XML::Simple;
+use Data::Dumper;
+
+sub new {
+ my ($class, $fileName) = @_;
+
+ my $self = {
+ my $data = 0,
+ my $catLen = 0,
+ my $currCat = 0,
+ my $modLen = 0,
+ my $currMod = 0,
+ my $placeHolder = 0
+ };
+ bless $self, 'ConfigReader';
+
+ my $xml = new XML::Simple (KeyAttr=>[]);
+ $self->{data} = $xml->XMLin($fileName);
+ $self->{catLen} = scalar(@{$self->{data}->{category}});
+ $self->{currCat} = -1;
+
+ if(ref(@{$self->{data}->{category}}[0]->{module}) eq "ARRAY") {
+ $self->{modLen} = scalar(@{@{$self->{data}->{category}}[0]->{module}});
+ } else {
+ $self->{modLen} = 1;
+ }
+ $self->{currMod} = -1;
+
+ return $self;
+}
+
+sub hasNextCat {
+ my ($self) = @_;
+
+ if($self->{currCat} + 1 >= $self->{catLen}) {
+ return 0;
+ }
+ return 1;
+}
+
+sub getNextCat {
+ my ($self) = @_;
+
+ $self->{currCat}++;
+ if($self->{currCat} >= $self->{catLen}) {
+ return 0;
+ }
+
+ # Reset the Module Count and Mod length for new Category
+ $self->{currMod} = -1;
+ if(ref(@{$self->{data}->{category}}[$self->{currCat}]->{module}) eq "ARRAY") {
+ $self->{modLen} = scalar(@{@{$self->{data}->{category}}[$self->{currCat}]->{module}});
+ } else {
+ $self->{modLen} = 1;
+ }
+
+ my $tmp = @{$self->{data}->{category}}[$self->{currCat}];
+
+ return $tmp;
+}
+
+sub hasNextMod {
+ my ($self) = @_;
+
+ if($self->{currMod} + 1 >= $self->{modLen}) {
+ return 0;
+ }
+ return 1;
+}
+
+sub getNextMod {
+ my ($self) = @_;
+
+ my $ret = 0;
+
+ $self->{currMod}++;
+
+ if($self->{modLen} == 1) {
+ $ret = @{$self->{data}->{category}}[$self->{currCat}]->{module};
+ } else {
+ $ret = @{@{$self->{data}->{category} }[$self->{currCat}]->{module}}[$self->{currMod}];
+ }
+
+ return $ret;
+}
+
+1;
diff --git a/MainDisplay.pm b/MainDisplay.pm
new file mode 100644
index 00000000..5e42641c
--- /dev/null
+++ b/MainDisplay.pm
@@ -0,0 +1,330 @@
+# Copyright 2012 Steven Tucker
+#
+# This file is part of AdminPanel
+#
+# AdminPanel 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.
+#
+# AdminPanel 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 AdminPanel. If not, see <http://www.gnu.org/licenses/>.
+
+
+#Class MainDisplay
+package MainDisplay;
+
+use strict;
+use warnings;
+use diagnostics;
+use SettingsReader;
+use ConfigReader;
+use Category;
+use Module;
+use Data::Dumper;
+use yui;
+
+sub new {
+
+ my $self = {
+ my $categories = 0,
+ my $event = 0,
+ my $factory = 0,
+ my $mainWin = 0,
+ my $mainLayout = 0,
+ my $menuLayout = 0,
+ my $menus = {
+ my $file = 0,
+ my $help = 0
+ },
+ my $layout = 0,
+ my $leftPane = 0,
+ my $rightPane = 0,
+ my $currCategory = 0,
+ my $confDir = 0,
+ my $title = 0,
+ my $settings = 0,
+ my $exitButton = 0,
+# my $justToGetRidOfERROR = 0,
+ my $replacePoint = 0
+ };
+ bless $self, 'MainDisplay';
+
+## Default values
+ $self->{name} = "Administration panel";
+ $self->{categories} = [];
+ $self->{confDir} = "/etc/apanel",
+ $self->{title} = "apanel",
+ $self->setupGui();
+
+ return $self;
+}
+
+## Begin the program event loop
+sub start {
+ my ($self) = shift;
+ my $reqExit = 0;
+
+ ##Default category selection
+ $self->{currCategory} = @{$self->{categories}}[0];
+ $self->{currCategory}->addButtons($self->{rightPane}, $self->{factory});
+ $self->{rightPaneFrame}->setLabel($self->{currCategory}->{name});
+ $self->{factory}->createSpacing($self->{rightPane}, 1, 1, 1.0 );
+
+ my $launch = 0;
+ while(!$launch) {
+
+ ## Grab Event
+ $self->{event} = $self->{mainWin}->waitForEvent();
+
+ ## Check for window close
+ if ($self->{event}->eventType() == $yui::YEvent::CancelEvent)
+ {
+ last;
+ }
+
+## why i can't test item() with $self->{menus}->{file}[0]?
+ ## Check for Exit button push or menu
+ if($self->{event}->widget() == $self->{exitButton} ||
+ ($self->{event}->item() && ($self->{event}->item()->label() eq $self->{menus}->{file}[0]->label() ))) {
+ last;
+ };
+
+ ## Discover if a menu button was selected.
+ ## If menu button selected, set right panel to display
+ ## selected Category Modules
+ for(@{$self->{categories}}){
+ if( $_->{button} == $self->{event}->widget() ){
+
+ ## Menu item selected, set right pane
+ $self->{mainWin}->startMultipleChanges();
+ ## Remove existing modules
+ $self->{replacePoint}->deleteChildren();
+ $self->{rightPane} = $self->{factory}->createVBox($self->{replacePoint});
+
+ ## Change Current Category to the selected one
+ $self->{currCategory} = $_;
+ ## Add new Module Buttons to Right Pane
+ $self->{currCategory}->addButtons($self->{rightPane}, $self->{factory});
+ $self->{rightPaneFrame}->setLabel($self->{currCategory}->{name});
+ $self->{factory}->createSpacing($self->{rightPane}, 1, 1, 1.0 );
+ $self->{replacePoint}->showChild();
+ $self->{mainWin}->recalcLayout();
+ $self->{mainWin}->doneMultipleChanges();
+
+ last;
+ }
+ }
+
+ ## Check if event is from current Category View
+ ## If icon click, launch the Module
+ for(@{$self->{currCategory}->{modules}}) {
+ if( $_->{button} == $self->{event}->widget() ){
+ $launch = $_->{launch};
+ last;
+ }
+ }
+ }
+
+ return $launch;
+}
+
+sub destroy {
+ my ($self) = shift;
+ $self->{mainWin}->destroy();
+}
+
+sub setupGui {
+ my ($self) = shift;
+
+ my $cmdline = new yui::YCommandLine;
+
+## TODO add parameter check
+ my $pos = $cmdline->find("--name");
+ if ($pos > 0)
+ {
+ $self->{title} = $cmdline->arg($pos+1);
+ }
+ $pos = $cmdline->find("--conf_dir");
+ if ($pos > 0)
+ {
+ $self->{confDir} = $cmdline->arg($pos+1);
+ }
+ else
+ {
+ $self->{confDir} = "/etc/$self->{title}";
+ }
+# print "name = ".$self->{title}."\n";
+# print "conf dir = ".$self->{confDir}."\n";
+
+ $self->loadSettings();
+ yui::YUILog::setLogFileName($self->{settings}->{log});
+ $self->{name} = $self->{settings}->{title};
+ yui::YUI::app()->setApplicationTitle($self->{name});
+ yui::YUI::app()->setApplicationIcon($self->{settings}->{icon});
+
+ $self->{factory} = yui::YUI::widgetFactory;
+ $self->{mainWin} = $self->{factory}->createMainDialog;
+#print "Title: ".yui::YUI::app()->applicationTitle()."\n";
+
+ $self->{mainLayout} = $self->{factory}->createVBox($self->{mainWin});
+ $self->{menuLayout} = $self->{factory}->createHBox($self->{mainLayout});
+
+ ## Menu file
+ ## TODO i8n
+ my $align = $self->{factory}->createAlignment($self->{menuLayout}, 1, 0);
+ my $menu = $self->{factory}->createMenuButton($align, "File");
+ my $item = new yui::YMenuItem("Exit");
+
+ push(@{$self->{menus}->{file}}, $item);
+ $menu->addItem($item);
+ $menu->rebuildMenuTree();
+
+ $align = $self->{factory}->createAlignment($self->{menuLayout}, 2, 0);
+ $menu = $self->{factory}->createMenuButton($align, "Help");
+ $item = new yui::YMenuItem("Help");
+ $menu->addItem($item);
+ push(@{$self->{menus}->{help}}, $item);
+ $item = new yui::YMenuItem("About");
+ $menu->addItem($item);
+ push(@{$self->{menus}->{help}}, $item);
+ $menu->rebuildMenuTree();
+
+ $self->{layout} = $self->{factory}->createHBox($self->{mainLayout});
+
+ #create left Panel Frame no need to add a label for title
+ $self->{leftPaneFrame} = $self->{factory}->createFrame($self->{layout}, $self->{settings}->{category_title});
+ #create right Panel Frame no need to add a label for title (use setLabel when module changes)
+ $self->{rightPaneFrame} = $self->{factory}->createFrame($self->{layout}, "");
+ #create replace point for dynamically created widgets
+ $self->{replacePoint} = $self->{factory}->createReplacePoint($self->{rightPaneFrame});
+
+ $self->{rightPane} = $self->{factory}->createVBox($self->{replacePoint});
+ $self->{leftPane} = $self->{factory}->createVBox($self->{leftPaneFrame});
+
+ #logo from settings
+ my $logo = $self->{factory}->createImage($self->{leftPane}, $self->{settings}->{logo});
+ $logo->setAutoScale(1);
+
+ $self->{leftPaneFrame}->setWeight(0, 25);
+ $self->{rightPaneFrame}->setWeight(0, 75);
+
+ $self->loadCategories();
+ $self->{factory}->createVStretch($self->{leftPane});
+
+ $self->{exitButton} = $self->{factory}->createPushButton($self->{leftPane}, "Exit");
+ $self->{exitButton}->setIcon("$self->{settings}->{images_dir}/quit.png");
+ $self->{exitButton}->setStretchable(0, 1);
+# $self->{exitButton}->setStretchable(1, 1);
+}
+
+## adpanel settings
+sub loadSettings {
+ my ($self) = @_;
+# configuration file name
+ my $fileName = "$self->{confDir}/settings.conf";
+ $self->{settings} = new SettingsReader($fileName);
+}
+
+sub loadCategory {
+ my ($self, $category) = @_;
+
+ push ( @{$self->{categories}}, $category );
+
+ @{$self->{categories}}[-1]->{button} = $self->{factory}->createPushButton(
+ $self->{leftPane},
+ $self->{categories}[-1]->{name}
+ );
+ @{$self->{categories}}[-1]->setIcon();
+
+ @{$self->{categories}}[-1]->{button}->setStretchable(0, 1);
+# @{$self->{categories}}[-1]->{button}->setStretchable(1, 1);
+}
+
+sub loadCategories {
+ my ($self) = @_;
+
+# configuration file name
+ my $fileName = "$self->{confDir}/categories.conf";
+
+ my $inFile = new ConfigReader($fileName);
+ my $tmpCat;
+ my $tmp;
+ my $hasNextCat = $inFile->hasNextCat();
+ while( $hasNextCat ) {
+ $tmp = $inFile->getNextCat();
+ $tmpCat = new Category($tmp->{title}, $tmp->{icon});
+ $self->loadCategory($tmpCat);
+ $hasNextCat = $inFile->hasNextCat();
+ $self->{currCategory} = $tmpCat;
+
+ my $hasNextMod = $inFile->hasNextMod();
+ while( $hasNextMod ) {
+ $tmp = $inFile->getNextMod();
+ my $tmpMod = new Module($tmp->{title},
+ $tmp->{icon},
+ $tmp->{launcher}
+ );
+ $self->{currCategory}->loadModule($tmpMod);
+
+ $hasNextMod = $inFile->hasNextMod();
+ }
+ }
+ undef($tmpCat);
+}
+
+sub menuEventIndex {
+ my ($self) = shift;
+
+ my $index = -1;
+
+ for(my $i = 0; $i < scalar(@{$self->{categories}} ); ++$i)
+ {
+ print "Current Index = ".$index."\n";
+ if($self->{event}->widget() == @{$self->{categories}}[$i]->{button})
+ {
+ $index = $i;
+ print "Index found is : ".$index;
+ last;
+ }
+ }
+ return $index;
+}
+
+1;
+
+=pod
+
+=head1 NAME
+
+ MainDisplay - class for the main window
+
+=head1 SYNOPSIS
+
+ $mainDisplay = new MainDisplay();
+
+=head1 METHODS
+
+=head2 start
+
+ contains the main loop of the application
+ where we can check for events
+
+=head2 setupGui
+
+ creates a popupDialog using a YUI::WidgetFactory
+ and then populate this dialog with some components
+
+=head2 loadCategory
+
+ creates a new button representing a category
+
+=head3 category (String)
+
+=cut
+
diff --git a/Module.pm b/Module.pm
new file mode 100644
index 00000000..990de15f
--- /dev/null
+++ b/Module.pm
@@ -0,0 +1,57 @@
+#!/usr/bin/perl
+
+# Copyright 2012 Steven Tucker
+#
+# This file is part of AdminPanel
+#
+# AdminPanel 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.
+#
+# AdminPanel 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 AdminPanel. If not, see <http://www.gnu.org/licenses/>.
+
+
+#Class Module
+package Module;
+
+use strict;
+use warnings;
+use diagnostics;
+use yui;
+
+sub new {
+ my ($class, $newName, $newIcon, $newLaunch) = @_;
+ my $self = {
+ my $name = 0,
+ my $icon = 0,
+ my $launch = 0,
+ my $button = 0
+ };
+ bless $self, 'Module';
+
+ $self->{name} = $newName;
+ $self->{icon} = $newIcon;
+ $self->{launch} = $newLaunch;
+
+ return $self;
+}
+
+sub setButton {
+ my ($self, $button) = @_;
+ $self->{button} = $button;
+}
+
+sub removeButton {
+ my($self) = @_;
+
+ undef($self->{button});
+}
+
+1;
diff --git a/SettingsReader.pm b/SettingsReader.pm
new file mode 100644
index 00000000..dddcdd4e
--- /dev/null
+++ b/SettingsReader.pm
@@ -0,0 +1,44 @@
+# Copyright 2012 Angelo Naselli
+#
+# This file is part of AdminPanel
+#
+# AdminPanel 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.
+#
+# AdminPanel 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 AdminPanel. If not, see <http://www.gnu.org/licenses/>.
+
+
+#Class SettingsReader
+package SettingsReader;
+
+use strict;
+use warnings;
+use diagnostics;
+use XML::Simple;
+use Data::Dumper;
+
+sub new {
+ my ($class, $fileName) = @_;
+
+ my $self = {
+ my $settings = 0,
+ my $justToGetRidOfERROR = 0
+ };
+ bless $self, 'SettingsReader';
+
+ my $xml = new XML::Simple (KeyAttr=>[]);
+ $self->{settings} = $xml->XMLin($fileName);
+
+ return $self->{settings};
+}
+
+
+1;
diff --git a/apanel.pl b/apanel.pl
new file mode 100755
index 00000000..6e50f2cb
--- /dev/null
+++ b/apanel.pl
@@ -0,0 +1,76 @@
+#!/usr/bin/perl
+
+# Copyright 2012 Steven Tucker
+#
+# This file is part of AdminPanel
+#
+# AdminPanel 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.
+#
+# AdminPanel 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 AdminPanel. If not, see <http://www.gnu.org/licenses/>.
+
+use strict;
+use warnings;
+use diagnostics;
+use FindBin;
+use lib "$FindBin::RealBin";
+use Getopt::Long;
+use Auth;
+use MainDisplay;
+use yui;
+
+my $help=0;
+
+my $result = GetOptions ("help" => \$help);
+
+usage() if($help);
+
+ask_for_authentication() if(require_root_capability());
+
+my $mainWin = new MainDisplay();
+my $launch = $mainWin->start();
+
+while($launch)
+{
+ $mainWin->destroy();
+ undef($mainWin);
+
+ my $err = yui::YUI::app()->runInTerminal("$launch --ncurses");
+ if ($err == -1)
+ {
+ system($launch);
+ }
+
+ $mainWin = new MainDisplay();
+ $launch = $mainWin->start();
+}
+
+$mainWin->destroy();
+undef($mainWin);
+
+sub usage {
+ print "\n";
+ print "Usage apanel [options...]\n\n";
+ print "Options:\n";
+ print "\t--help | -h print this help\n";
+ print "\t--name string specify the window title of the administration panel\n";
+ print "\t--conf_dir path specify the settings.conf file directory\n";
+ print "\n";
+ exit(0);
+}
+
+=pod
+
+=head1 main
+
+ main launcher
+
+=cut
diff --git a/categories.conf b/categories.conf
new file mode 100644
index 00000000..256fc9e9
--- /dev/null
+++ b/categories.conf
@@ -0,0 +1,36 @@
+<?xml version='1.0'?>
+<categories>
+ <category>
+ <title>Software Management</title>
+ <icon>/usr/share/icons/applications_section.png</icon>
+ <module>
+ <title>Add Software</title>
+ <launcher>./modules/test</launcher>
+ <icon>/usr/share/icons/mageiaupdate.png</icon>
+ </module>
+ <module>
+ <title>Remove Software</title>
+ <launcher>./modules/test</launcher>
+ <icon>/usr/share/icons/edit-urpm-sources.png</icon>
+ </module>
+ <module>
+ <title>Update Software</title>
+ <launcher>./modules/test</launcher>
+ <icon>/usr/share/icons/mageiaupdate.png</icon>
+ </module>
+ <module>
+ <title>Edit Sources</title>
+ <launcher>./modules/test</launcher>
+ <icon>/usr/share/icons/edit-urpm-sources.png</icon>
+ </module>
+ </category>
+ <category>
+ <title>Hardware</title>
+ <icon>/usr/share/icons/configuration_section.png</icon>
+ <module>
+ <title>CD/DVD Config</title>
+ <launcher>./modules/test</launcher>
+ <icon>./modules/pythonMod</icon>
+ </module>
+ </category>
+</categories>
diff --git a/extras/README b/extras/README
new file mode 100644
index 00000000..52650fca
--- /dev/null
+++ b/extras/README
@@ -0,0 +1,10 @@
+Please copy extras/org.freedesktop.policykit.pkexec.policy to /usr/share/polkit-1/actions/org.freedesktop.policykit.pkexec.policy
+to make apanel be usable through policykit (mcc is currently using pam, a bit more complicated compared to polkit).
+
+After that you have to make a symbolic link to apanel.pl into /usr/bin/ (i.e. /usr/bin/apanel.pl) and make your local apanel.pl script executable (chmod +x apanel.pl).
+
+This settings will be automatically handled at rpm installation time in future/production.
+
+TODO:
+- support to pam (wip)
+- add testing/develop exceptions (avoid to insert password at develop time)
diff --git a/extras/org.freedesktop.policykit.pkexec.policy b/extras/org.freedesktop.policykit.pkexec.policy
new file mode 100644
index 00000000..b110dba6
--- /dev/null
+++ b/extras/org.freedesktop.policykit.pkexec.policy
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE policyconfig PUBLIC
+ "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/PolicyKit/1/policyconfig.dtd">
+<policyconfig>
+
+ <vendor>APanel PolicyKit Configuration</vendor>
+ <vendor_url>http://hal.freedesktop.org/docs/PolicyKit/</vendor_url>
+
+ <action id="org.freedesktop.policykit.pkexec.run-apanel">
+ <description>Allow APanel GUI</description>
+ <message>Authentication is required to run the program apanel (user=$(user), program=$(program), command_line=$(command_line))</message>
+ <defaults>
+ <allow_any>no</allow_any>
+ <allow_inactive>no</allow_inactive>
+ <allow_active>auth_admin</allow_active>
+ </defaults>
+ <annotate key="org.freedesktop.policykit.exec.path">/usr/bin/apanel.pl</annotate>
+ <annotate key="org.freedesktop.policykit.exec.allow_gui">TRUE</annotate>
+ </action>
+
+</policyconfig>
diff --git a/images/logo_mageia.png b/images/logo_mageia.png
new file mode 100644
index 00000000..32fe51c3
--- /dev/null
+++ b/images/logo_mageia.png
Binary files differ
diff --git a/images/mageia.png b/images/mageia.png
new file mode 100644
index 00000000..6769fda3
--- /dev/null
+++ b/images/mageia.png
Binary files differ
diff --git a/images/quit.png b/images/quit.png
new file mode 100644
index 00000000..322c187e
--- /dev/null
+++ b/images/quit.png
Binary files differ
diff --git a/modules/test.cpp b/modules/test.cpp
new file mode 100644
index 00000000..6f3178ef
--- /dev/null
+++ b/modules/test.cpp
@@ -0,0 +1,137 @@
+// Trivial libyui example.
+//
+// Compile with:
+//
+// g++ -I/usr/include/yui -lyui test.cpp -o test
+//
+#include "YUI.h"
+#include "YApplication.h"
+#include "YWidgetFactory.h"
+#include "YDialog.h"
+#include "YPushButton.h"
+#include "YLayoutBox.h"
+#include "YReplacePoint.h"
+#include "YEvent.h"
+#include "YFrame.h"
+#include <vector>
+
+int main( int argc, char **argv )
+{
+ YUI::app()->setApplicationTitle("Test module");
+ YUI::app()->setApplicationIcon("/usr/share/icons/mageia.png");
+
+ YDialog * dialog = YUI::widgetFactory()->createPopupDialog();
+ YFrame* frame = YUI::widgetFactory()->createFrame(dialog, "Test frame");
+ YLayoutBox * hbox = YUI::widgetFactory()->createHBox(frame);
+ YFrame* lframe = YUI::widgetFactory()->createFrame(hbox, "Left frame");
+ YFrame* rframe = YUI::widgetFactory()->createFrame(hbox, "Right frame");
+ // here we change the widget
+ YReplacePoint* replacePoint = YUI::widgetFactory()->createReplacePoint(rframe);
+
+ YLayoutBox * vbox_rframe = YUI::widgetFactory()->createVBox( replacePoint );
+ YLayoutBox * vbox = YUI::widgetFactory()->createVBox( lframe );
+// vbox->setSize( 1000, 1000 );
+ lframe->setWeight(YD_HORIZ, 25);
+ rframe->setWeight(YD_HORIZ, 75);
+ YUI::widgetFactory()->createLabel ( vbox, "Hello, World!" );
+ YPushButton* addButton = YUI::widgetFactory()->createPushButton( vbox, "Add Button" );
+ YPushButton* removeButton = YUI::widgetFactory()->createPushButton( vbox, "Remove Button" );
+ YPushButton* exitButton = YUI::widgetFactory()->createPushButton( vbox, "&Exit" );
+ YUI::widgetFactory()->createSpacing( vbox, YD_VERT, true, 1.0 );
+
+ //YPushButton* testButton = YUI::widgetFactory()->createPushButton( vbox, "&Cannot be added" );
+ //testButton->hide(); <-- Angelo, I could not see this call in the api
+
+ int bnum = 0;
+ std::vector<YPushButton*>buttons;
+
+ for (;;)
+ {
+ YEvent* event = dialog->waitForEvent();
+ // Check for window close
+ if (event->eventType() == YEvent::CancelEvent)
+ {
+ break;
+ }
+
+ // Check for Exit button push
+ if(event->widget() == (YWidget*)exitButton ) {
+ break;
+ };
+
+ if(event->widget() == (YWidget*)addButton ) {
+ if(bnum < 6) {
+ dialog->startMultipleChanges();
+ replacePoint->deleteChildren();
+ vbox_rframe = YUI::widgetFactory()->createVBox( replacePoint );
+ bnum++;
+ buttons.clear();
+ for (int i=0; i < bnum; ++i)
+ {
+ YPushButton* tmpB = YUI::widgetFactory()->createPushButton( vbox_rframe, "Delete Me" );
+ buttons.push_back(tmpB);
+ }
+ replacePoint->showChild();
+ dialog->recalcLayout();
+ dialog->doneMultipleChanges();
+ }
+ else if (bnum == 6)
+ {
+ dialog->startMultipleChanges();
+ replacePoint->deleteChildren();
+ vbox_rframe = YUI::widgetFactory()->createVBox( replacePoint );
+ buttons.clear();
+ for (int i=0; i < bnum; ++i)
+ {
+ YPushButton* tmpB = YUI::widgetFactory()->createPushButton( vbox_rframe, "Delete Me" );
+ buttons.push_back(tmpB);
+ }
+ YUI::widgetFactory()->createSpacing( vbox_rframe, YD_VERT, false, 1.0 );
+ replacePoint->showChild();
+ dialog->recalcLayout();
+ dialog->doneMultipleChanges();
+ }
+ }
+ if(event->widget() == (YWidget*)removeButton ) {
+ if (bnum > 0)
+ {
+ dialog->startMultipleChanges();
+ replacePoint->deleteChildren();
+ vbox_rframe = YUI::widgetFactory()->createVBox( replacePoint );
+ bnum--;
+ buttons.clear();
+ for (int i=0; i < bnum; ++i)
+ {
+ YPushButton* tmpB = YUI::widgetFactory()->createPushButton( vbox_rframe, "Delete Me" );
+ buttons.push_back(tmpB);
+ }
+ replacePoint->showChild();
+ dialog->recalcLayout();
+ dialog->doneMultipleChanges();
+ }
+ }
+
+
+ for(int i = 0; i < bnum; ++i)
+ {
+ if (event->widget() == (YWidget*)buttons[i]) {
+ dialog->startMultipleChanges();
+ replacePoint->deleteChildren();
+ vbox_rframe = YUI::widgetFactory()->createVBox( replacePoint );
+ bnum--;
+ buttons.clear();
+ for (int i=0; i < bnum; ++i)
+ {
+ YPushButton* tmpB = YUI::widgetFactory()->createPushButton( vbox_rframe, "Delete Me" );
+ buttons.push_back(tmpB);
+ }
+ replacePoint->showChild();
+ dialog->recalcLayout();
+ dialog->doneMultipleChanges();
+ break;
+ }
+ }
+ }
+
+ dialog->destroy();
+}
diff --git a/settings.conf b/settings.conf
new file mode 100644
index 00000000..023f76a7
--- /dev/null
+++ b/settings.conf
@@ -0,0 +1,9 @@
+<?xml version='1.0'?>
+<settings>
+ <title>Admin Panel</title>
+ <logo>images/logo_mageia.png</logo>
+ <icon>images/mageia.png</icon>
+ <log>/tmp/apanel.log</log>
+ <images_dir>/usr/share/icons</images_dir>
+ <category_title>Categories</category_title>
+</settings>