Source for file Gtk.php
Documentation is available at Gtk.php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
* A Gtk GUI frontend for the PEAR_PackageFileManager class.
* A PHP-GTK 1 frontend for the PEAR_PackageFileManager class.
* It makes it easier for developers to create and maintain
* PEAR package.xml files.
* - Update existing package files or create new ones
* - Import values from an existing package file
* - Drag-n-Drop package directory into the application for easy
* loading (requires PEAR::Gtk_FileDrop)
* - Set package level information (package name, description, etc.)
* - Set release level information (version, release notes, etc.)
* - Easily add maintainers
* - Browse package files as a tree and click to add a dependency
* - Add install time global and file replacements
* - Package file preview window
* - Package the package using the new package file
* More detail can be found in
* doc/PEAR_PackageFileManager_GUI_Gtk/example.php
* if (!extension_loaded('gtk')) {
* dl( 'php_gtk.' . PHP_SHLIB_SUFFIX);
* require_once 'PEAR/PackageFileManager/GUI/Gtk.php';
* $pfmGtk =& new PEAR_PackageFileManager_GUI_Gtk();
* @todo Allow other (non-package) dependencies (Maybe)
* @package PEAR_PackageFileManager_GUI_Gtk
* @copyright © (c) Copyright 2005 Scott Mattocks
* @version API: @version@ CVS: $Id:$
* @link http://pear.php.net/package/PEAR_PackageFileManager_GUI_Gtk
* PEAR_PackageFileManager instance.
var $_packageFileManager;
* PEAR_PackageFileManager options array
* The GtkNotebook used to display the different tasks.
* The GtkText that will display the warnings.
* The GtkWindow that will hold the preview information.
* Keep track of whether or not the file has been previewed
* Keep track of whether or not the file has been saved in
* Creates the package file manager and then calls the
* method to create the rest of the application.
* @param boolean $isMain Whether or not this class is the
* main application for this Gtk loop
// Instantiate the package file manager.
require_once 'PEAR/PackageFileManager.php';
$this->_packageFileManager = & new PEAR_PackageFileManager ();
// Create the application.
$this->_createApplication ($isMain);
* Please note: The regular issues associated with show_all()
* still apply. show_all() does not always trickle all of the
* way down to the very last child widget. For more info please
* see the PHP-GTK website {@link http://gtk.php.net}
* Returns the main application window.
* This is a standard PEAR-PHP-GTK method. It has
* been added for consistency. It would be useful if
* the PEAR_Frontend_Gtk class had a "New Package"
* feature. The PEAR_Frontend_Gtk code could just
* instantiate this class and call getWidget(). It
* could then show the window when ever it wanted or
* make some changes to the window itself. It could
* even pull the child from the window and embed the
* rest of this application in itself.
* Creates and shows an about window.
* The about window contains the package name, current
* package version number, the list of developers and where
* to find the latest information for the package.
* It would be nice if this window also told the user what
* version of PEAR_PackageFileManager was being used but I
* don't know that that information is necessarily part of
$aboutWin = & new GtkWindow ();
$aboutWin->set_title ('PEAR_PackageFileManager');
$aboutFrame = & new GtkFrame ('About');
$aboutWin->add ($aboutFrame);
// Add the data in an organized manner.
// The best way is probably with a GtkTable.
$table = & new GtkTable ();
$table->set_col_spacings (3 );
// Create an array of row labels.
$labels = array ('Package',
// Attach each child in the first column.
foreach ($labels as $row => $label) {
$label = & new GtkLabel ($label . ':');
$label->set_alignment (0 , 0 );
$table->attach ($label, 0 , 1 , $row, $row + 1 );
// Create an array of values.
$values = array ('PEAR_PackageFileManager_GUI_Gtk',
// Add the values in the second column.
foreach ($values as $row => $value) {
$label = & new GtkLabel ($value);
$label->set_alignment (0 , 0 );
$table->attach ($label, 1 , 2 , $row, $row + 1 );
$closeBox = & new GtkHBox ();
$closeButton = & new GtkButton ('Close');
$closeButton->connect_object ('clicked', array (&$aboutWin, 'destroy'));
$closeBox->pack_end ($closeButton, false , false , 3 );
$table->attach ($closeBox, 0 , 2 , count($labels), count($labels) + 1 );
// Add the table and show everything.
$aboutFrame->add ($table);
* Shows the warnings in the text area.
* Each warning will be displayed on its own line.
* @param string $message Optional message to add to the warnings.
foreach ($this->_packageFileManager->getWarnings () as $warning) {
* Checks to see if the file has been saved before destroying the
* The user should save their file before the application closes.
* If they have not, they will be prompted to save or close any
* This method will also kill the main gtk loop if told to. If
* this class is imbedded in another class, you probably don't
* want to do that. Pass false to the constructor to prevent
* @param boolean $killMainLoop
// Check to see if the file was saved.
// Prompt the user with a GtkDialog window.
$dialog = & new GtkDialog ();
$vBox->pack_start (new GtkLabel ('Your package file has not been saved. Would you like to save it now?'));
// Kill the main loop if requested.
* Creates the main PHP-GTK application.
* @param boolean $isMain Whether or not this class is the
* main application for this Gtk loop
function _createApplication ($isMain)
$this->widget = & new GtkWindow ();
$this->widget->set_title ('PackageFileManager');
//$this->widget->connect_object('destroy', array(&$this, 'checkBeforeQuit'), $isMain);
$this->widget->connect_object ('destroy', array ('gtk', 'main_quit'));
// The main container for the window.
$vBox->pack_start ($this->_buildMenu (), false , true , 3 );
$vBox->pack_start ($this->_buildNotebook ());
* Builds the application's menu.
* The menu is used for such things as the open and save
* dialogs. The menu should also have an about option and
* @return object A container holding the menu.
$menuBar = & new GtkMenuBar ();
$accel = & new GtkAccelGroup ();
$this->widget->add_accel_group ($accel);
// Create the main (only) menu item.
$fileHeader = & new GtkMenuItem ('File');
$helpHeader = & new GtkMenuItem ('Help');
// Add the menu item to the menu bar.
$menuBar->append ($fileHeader);
$menuBar->append ($helpHeader);
$fileMenu = & new GtkMenu ();
$helpMenu = & new GtkMenu ();
// Allow users to preview the package file (debugPackageFile)
$preview = & new GtkMenuItem ('');
$previewLabel = $preview->child;
$previewKey = $previewLabel->parse_uline ('_Preview');
$preview->add_accelerator ('activate', $accel, $previewKey, GDK_CONTROL_MASK , GTK_ACCEL_VISIBLE );
$preview->lock_accelerators ();
$preview->connect_object ('activate', array (&$this, '_previewFile'));
$fileMenu->append ($preview);
// Allow users to save the package file (writePackageFile)
$save = & new GtkMenuItem ('');
$saveLabel = $save->child;
$saveKey = $saveLabel->parse_uline ('_Save');
$save->add_accelerator ('activate', $accel, $saveKey, GDK_CONTROL_MASK , GTK_ACCEL_VISIBLE );
$save->lock_accelerators ();
$save->connect_object ('activate', array (&$this, '_writePackageFile'));
$fileMenu->append ($save);
// Allow users to package the package.
$package = & new GtkMenuItem ('');
$packageLabel = $package->child;
$packageKey = $packageLabel->parse_uline ('P_ackage');
$package->add_accelerator ('activate', $accel, $packageKey, GDK_CONTROL_MASK , GTK_ACCEL_VISIBLE );
$package->lock_accelerators ();
$package->connect_object ('activate', array (&$this, '_packagePackage'));
$fileMenu->append ($package);
$exit = & new GtkMenuItem ('Exit');
$exit->connect_object ('activate', array ('gtk', 'main_quit'));
$fileMenu->append ($exit);
$about = & new GtkMenuItem ('About...');
$about->connect ('activate', array (&$this, 'about'));
$helpMenu->append ($about);
$fileHeader->set_submenu ($fileMenu);
$helpHeader->set_submenu ($helpMenu);
* Builds the main display widget.
* To make the user interface more navigable, a GtkNotebook
* is used. This lets the user appear to be working through
* a wizard when they are actually just changing pages.
function &_buildNotebook ()
// Add the package info page.
$this->_addNotebookPage ($this->_createPackagePage ());
// Add the release info page.
$this->_addNotebookPage ($this->_createReleasePage ());
// Add the addMaintainer page.
// This can't happen until the options are set!
//$this->_addNotebookPage($this->_createAddMaintainerPage());
// Add the addDependencies page.
// This can't happen until the options are set!
//$this->_addNotebookPage($this->_createAddDependenciesPage());
// Add the addReplacements page.
// This can't happen until the options are set!
//$this->_addNotebookPage($this->_createAddReplacementsPage());
// Add the warnings page.
$this->_addNotebookPage ($this->_createWarningsPage ());
// When the page is switched, get any new warnings.
$this->notebook->connect_object ('switch-page', array (&$this, 'showWarnings'));
* Appends the given container to the notebook.
* @param array $page array(container, label)
* @param boolean $last Whether this page should be the last page or not
function _addNotebookPage ($page, $last = true )
// Add the container and the tab label.
$this->notebook->append_page ($page[0 ], $page[1 ]);
// Make this the second to last page.
$this->notebook->insert_page ($page[0 ], $page[1 ], $position);
* Creates the page for displaying the package file manager
* options that relate to the entire package, regardless of
* Package options are those such as: base install directory,
* the license, the package name, etc.
function _createPackagePage ()
// Create some containers.
$mainVBox = & new GtkVBox ();
// Create the hbox for the file selection.
$packageDirHBox = & new GtkHBox ();
// We need an entries for the file.
$packageDirEntry = & new GtkEntry ();
$packageDirButton = & new GtkButton ('Select');
// Allow users to drop files in the entry box if possible.
@include_once 'Gtk/FileDrop.php';
Gtk_FileDrop ::attach ($packageDirEntry, array ('inode/directory'));
// Create the file selection.
$packageDirFS = & new GtkFileSelection ('Package Directory');
$packageDirFS->set_position (GTK_WIN_POS_CENTER );
// Set the default path to the pear directory.
require_once 'PEAR/Config.php';
$pearConfig = & new PEAR_Config ();
$packageDirFS->set_filename ($pearConfig->get ('php_dir'));
// Make the ok button set the entry value.
$okButton = $packageDirFS->ok_button;
$okButton->connect_object ('clicked', array (&$this, '_setPackageDirEntry'), $packageDirEntry, $packageDirFS);
// Make the cancel button hide the selection.
$cancelButton = $packageDirFS->cancel_button;
$cancelButton->connect_object ('clicked', array (&$packageDirFS, 'hide'));
// Make the button show the file selection.
$packageDirButton->connect_object ('clicked', array (&$packageDirFS, 'show'));
// Pack the package file directory pieces.
$packageDirLabel = & new GtkLabel ('Package File Directory');
$packageDirLabel->set_usize (140 , -1 );
$packageDirLabel->set_alignment (0 , .5 );
$packageDirHBox->pack_start ($packageDirLabel, false , false , 3 );
$packageDirHBox->pack_start ($packageDirEntry, false , false , 3 );
$packageDirHBox->pack_start ($packageDirButton, false , false , 3 );
// We need an entry for the package name.
$packageNameEntry = & new GtkEntry ();
$packageNameBox = & new GtkHBox ();
$packageNameLabel = & new GtkLabel ('Package Name');
$packageNameLabel->set_usize (140 , -1 );
$packageNameLabel->set_alignment (0 , .5 );
$packageNameBox->pack_start ($packageNameLabel, false , false , 3 );
$packageNameBox->pack_start ($packageNameEntry, false , false , 3 );
// We need a simple entry box for the base install directory.
$baseEntry = & new GtkEntry ();
$baseBox = & new GtkHBox ();
$baseLabel = & new GtkLabel ('Base Install Dir');
$baseLabel->set_usize (140 , -1 );
$baseLabel->set_alignment (0 , .5 );
$baseBox->pack_start ($baseLabel, false , false , 3 );
$baseBox->pack_start ($baseEntry, false , false , 3 );
// We need an entry for the summary.
$summaryEntry = & new GtkEntry ();
$summaryBox = & new GtkHBox ();
$summaryLabel = & new GtkLabel ('Package Summary');
$summaryLabel->set_usize (140 , -1 );
$summaryLabel->set_alignment (0 , .5 );
$summaryBox->pack_start ($summaryLabel, false , false , 3 );
$summaryBox->pack_start ($summaryEntry, false , false , 3 );
// We need a text area for the description.
$descriptionText = & new GtkText ();
$descriptionBox = & new GtkVBox ();
$descriptionLabel = & new GtkLabel ('Package Description');
$descriptionLabel->set_usize (140 , -1 );
$descriptionLabel->set_alignment (0 , .5 );
$descriptionText->set_editable (true );
$descriptionText->set_line_wrap (true );
$descriptionText->set_word_wrap (true );
$descriptionText->set_usize (-1 , 100 );
$descriptionBox->pack_start ($descriptionLabel, false , false , 3 );
$descriptionBox->pack_start ($descriptionText, true , true , 3 );
// We need a button to do the work.
$submitButton = & new GtkButton ('Submit');
$submitButton->connect_object ('clicked', array (&$this, '_setPackageOptions'), $packageDirEntry, $packageNameEntry, $baseEntry, $summaryEntry, $descriptionText);
$submitBox = & new GtkHBox ();
$submitBox->pack_end ($submitButton, false , false , 5 );
// Import the options if there is a package.xml file
// in the package directory.
$packageDirEntry->connect ('changed', array (&$this, '_importPackageOptions'), $packageNameEntry, $baseEntry, $summaryEntry, $descriptionText);
$mainVBox->pack_start ($packageDirHBox, false , false , 3 );
$mainVBox->pack_start ($packageNameBox, false , false , 3 );
$mainVBox->pack_start ($baseBox, false , false , 3 );
$mainVBox->pack_start ($summaryBox, false , false , 3 );
$mainVBox->pack_start ($descriptionBox, true , true , 3 );
$mainVBox->pack_start ($submitBox, false , false , 3 );
return array (&$mainVBox, new GtkLabel ('Package'));
* Creates the page for displaying the package file
* manager release options fields.
* The release options consist of features including, the
* release date, the package version and state, and the
* Options that do not relate to individual releases are
* covered on a seperate page.
function _createReleasePage ()
// Create some containers.
$mainVBox = & new GtkVBox ();
// We need a combo list for the version.
$stateCombo = & new GtkCombo ();
$stateList = $stateCombo->list;
$stateEntry = $stateCombo->entry;
$stateList->set_selection_mode (GTK_SELECTION_SINGLE );
$stateEntry->set_text ('Select One');
$stateEntry->set_editable (false );
// Add the states to the select box.
$states = array ('alpha', 'beta', 'stable');
for ($i = 0; $i < count($states); $i++ ) {
$item = & new GtkListItem ();
$label = & new GtkLabel ($states[$i]);
$box->pack_start ($label, false , false , 10 );
$stateCombo->set_item_string ($item, $states[$i]);
$item->set_data ('state', $states[$i]);
// Put the state combo in a box.
$stateBox = & new GtkHBox ();
$stateLabel = & new GtkLabel ('State');
$stateLabel->set_usize (140 , -1 );
$stateLabel->set_alignment (0 , .5 );
$stateBox->pack_start ($stateLabel, false , false , 3 );
$stateBox->pack_start ($stateCombo, false , false , 3 );
// We need a simple entry box for the version.
$verEntry = & new GtkEntry ();
$verBox = & new GtkHBox ();
$verLabel = & new GtkLabel ('Version');
$verLabel->set_usize (140 , -1 );
$verLabel->set_alignment (0 , .5 );
$verBox->pack_start ($verLabel, false , false , 3 );
$verBox->pack_start ($verEntry, false , false , 3 );
// Create a text box for the release notes.
$notes->set_word_wrap (false );
$notes->set_line_wrap (true );
$notes->set_editable (true );
// Put the notes stuff in a box with a label.
$notesBox = & new GtkVBox ();
$notesLabel = & new GtkLabel ('Release Notes');
$notesLabel->set_alignment (0 , .5 );
$notesBox->pack_start ($notesLabel, false , false , 3 );
$notesBox->pack_start ($notes, false , false , 3 );
// We need a button to do the work.
$submitButton = & new GtkButton ('Submit');
$submitButton->connect_object ('clicked', array (&$this, '_setReleaseOptions'), $stateCombo, $verEntry, $notes);
$submitBox = & new GtkHBox ();
$submitBox->pack_end ($submitButton, false , false , 5 );
// Pack the containers into the main container.
$mainVBox->pack_start ($stateBox, false , false , 3 );
$mainVBox->pack_start ($verBox, false , false , 3 );
$mainVBox->pack_start ($notesBox, false , false , 6 );
$mainVBox->pack_start ($submitBox, false , false , 6 );
return array ($mainVBox, new GtkLabel ('Release'));
* Creates a page for displaying (and clearing) warnings.
* The warnings page consists of a text area and a button.
* The text area should be set to wrap text but not be
* editable. The button should clear the text area of any
function _createWarningsPage ()
// Pack everything in a vBox.
$sWin = & new GtkScrolledWindow ();
$sWin->set_policy (GTK_POLICY_AUTOMATIC , GTK_POLICY_AUTOMATIC );
// Set up the warnings area.
// Add a button to clear the warnings area.
$button = & new GtkButton ('Clear');
$button->connect_object ('clicked', array (&$this->warningsArea, 'delete_text'), 0 , -1 );
$hBox->pack_end ($button, false , false , 5 );
$vBox->pack_start ($sWin, true , true , 10 );
$vBox->pack_start ($hBox, false , true );
return array ($vBox, new GtkLabel ('Warnings'));
* Creates a page for gathering information about developers.
* The add maintainer page needs to get the developer's name,
* handle, email address and role. The role should be a
* GtkCombo which doesn't allow the user to enter anything
* that is not a valid role.
function _createAddMaintainersPage ()
// To lay things out, use a combination of h and v boxes.
$mainVBox = & new GtkVBox ();
$mainHBox = & new GtkHBox ();
$leftVBox = & new GtkVBox ();
$rightVBox = & new GtkVBox ();
$subHBox = & new GtkHBox ();
// We need to display the current maintainers in a cList
$currentList = & new GtkCList (3 , array ('Developer', 'Email', 'Role'));
// Make the first two columns auto resize and sort
$currentList->set_column_auto_resize (0 , true );
$currentList->set_column_auto_resize (1 , true );
$currentList->set_auto_sort (true );
// Add the current maintainers to the list.
$this->_listDevelopers ($currentList);
// We need three entries and three labels.
$handleEntry = & new GtkEntry ();
$handleLabel = & new GtkLabel ('Handle');
$nameEntry = & new GtkEntry ();
$nameLabel = & new GtkLabel ('Name');
$emailEntry = & new GtkEntry ();
$emailLabel = & new GtkLabel ('Email');
// We also need a combo for the developer role.
$roleLabel = & new GtkLabel ('Role');
$roleCombo = & new GtkCombo ();
$roleList = $roleCombo->list;
$roleEntry = $roleCombo->entry;
$roleList->set_selection_mode (GTK_SELECTION_SINGLE );
$roleEntry->set_text ('Select One');
$roleEntry->set_editable (false );
// Add the roles to the select box.
$roles = array ('Contributor', 'Developer', 'Helper', 'Lead');
for ($i = 0; $i < count($roles); $i++ ) {
$item = & new GtkListItem ();
$label = & new GtkLabel ($roles[$i]);
$box->pack_start ($label, false , false , 10 );
$roleCombo->set_item_string ($item, $roles[$i]);
$item->set_data ('role', $roles[$i]);
// We need a button to do the work.
$button = & new GtkButton ('Add Maintainer');
$button->connect_object ('clicked', array (&$this, '_addMaintainer'), $handleEntry, $roleCombo, $nameEntry, $emailEntry, $currentList);
// All of the labels should be aligned.
$handleLabel->set_alignment (1 , .5 );
$nameLabel->set_alignment (1 , .5 );
$emailLabel->set_alignment (1 , .5 );
$roleLabel->set_alignment (1 , .5 );
// The left VBox is for the labels.
$leftVBox->pack_start ($handleLabel, false , true , 3 );
$leftVBox->pack_start ($nameLabel, false , true , 3 );
$leftVBox->pack_start ($emailLabel, false , true , 3 );
$leftVBox->pack_start ($roleLabel, false , true , 3 );
// The right VBox is for the entries and the combo.
$rightVBox->pack_start ($handleEntry, false , false , 0 );
$rightVBox->pack_start ($nameEntry, false , false , 0 );
$rightVBox->pack_start ($emailEntry, false , false , 0 );
$rightVBox->pack_start ($roleCombo, false , false , 0 );
// The two VBoxes go in the main HBox.
$mainHBox->pack_start ($leftVBox, true , true , 2 );
$mainHBox->pack_start ($rightVBox, true , true , 20 );
// The subHBox holds the button.
$subHBox->pack_end ($button, false , false , 20 );
// The label and the two HBoxes go in the main VBox.
$mainVBox->pack_start ($mainHBox, false , false , 10 );
$mainVBox->pack_start ($subHBox, false , false , 2 );
$mainVBox->pack_start ($currentList, false , false , 2 );
// Return the page information.
return array (&$mainVBox, new GtkLabel ('Maintainers'));
* Add the widgets that make up the dependencies page.
* The dependencies page consists of one widget to
* display installed packages, one widget to display
* packages selected as dependencies, a button to clear
* the selected list and a button to add the dependencies.
function _createAddDependenciesPage ()
// An HBox holds everything.
$mainVBox = & new GtkVBox ();
// Two VBoxes hold the tree and list.
$topVBox = & new GtkVBox ();
$bottomVBox = & new GtkVBox ();
$buttonHBox = & new GtkHBox ();
// We need a label to make to tell people to click
// the package make it optional.
$instructions = & new GtkLabel ('Click a package to make it an optional dependency.');
// Put the tree in a scrolling window.
$treeScrolledWindow = & new GtkScrolledWindow ();
$treeScrolledWindow->set_policy (GTK_POLICY_NEVER , GTK_POLICY_AUTOMATIC );
$listScrolledWindow = & new GtkScrolledWindow ();
$listScrolledWindow->set_policy (GTK_POLICY_AUTOMATIC , GTK_POLICY_AUTOMATIC );
$treeScrolledWindow->set_usize (200 , 150 );
$listScrolledWindow->set_usize (200 , 150 );
$cTree = & new GtkCTree (1 , 0 );
$cTree->set_line_style (GTK_CTREE_LINES_SOLID );
$root = & $cTree->insert_node (NULL , NULL , array ('Packages'), 0 , NULL , NULL , NULL , NULL , NULL , NULL );
// Use PEAR_Registry to build the tree.
require_once 'PEAR/Registry.php';
$reg = new PEAR_Registry ();
// Loop through the packages and add a node for each
// package with a child for the version.
foreach ($reg->packageInfo () as $package) {
// I don't know why but some return info from PEAR_Registry
// has no package name. That aint cool!
if (empty ($package['package'])) {
$name = & $cTree->insert_node ($root, NULL , array ($package['package']), 0 , NULL , NULL , NULL , NULL , NULL , NULL );
$version = & $cTree->insert_node ($name, NULL , array ($package['version']), 0 , NULL , NULL , NULL , NULL , NULL , NULL );
// Set some data so that we can tell what the user
$cTree->node_set_row_data ($version, array ($package['package'], $package['version'], ''));
// Add the older versions if there are any.
if (count($package['changelog'])) {
foreach($package['changelog'] as $change) {
if ($change['version'] != $package['version']) {
$oldVersion = & $cTree->insert_node ($name, NULL , array ($change['version']), 0 , NULL , NULL , NULL , NULL , NULL , NULL );
$cTree->node_set_row_data ($oldVersion, array ($package['package'], $change['version'], ''));
// Create a GtkCList to show the added dependencies.
$cList = & new GtkCList (3 , array ('Package', 'Version', 'Optional'));
// Make the first column automatically adjust to
$cList->set_column_auto_resize (0 , true );
// Automatically sort the entries.
$cList->set_auto_sort (true );
// When the user selects a package we want to toggle
$cList->connect ('select-row', array (&$this, '_toggleOptional'));
// Connect the tree-select-row so that the user
$cTree->connect ('tree-select-row', array (&$this, '_treeToCList'), $cList);
// Show dependencies from import in cList.
$this->_getDependencies ($cList);
// Add some buttons to make things a little easier to
$clearButton = & new GtkButton ('Clear');
$addButton = & new GtkButton ('Add Dependencies');
// We also want an auto detect button.
$autoButton = & new GtkButton ('Auto Detect');
// The clear but should clear out the cList.
// Clearing dependencies already in a package file
$clearButton->connect_object ('clicked', array (&$cList, 'clear'));
$clearButton->connect_object ('clicked', array (&$this->_packageFileManager, 'setOptions'), $this->_options + array ('deps' => array ()));
// The auto detect button should be connected to the PFM
// detectDependencies method.
$autoButton->connect_object ('clicked', array (&$this->_packageFileManager, 'detectDependencies'));
// We need to let the user know that it did something.
$autoButton->connect_object_after ('clicked', array (&$this, '_getDependencies'), $cList);
// The add button should add the dependencies from the cList
$addButton->connect_object ('clicked', array (&$this, '_addDependencies'), $cList);
$treeScrolledWindow->add ($cTree);
$topVBox->pack_start ($treeScrolledWindow);
$listScrolledWindow->add ($cList);
$bottomVBox->pack_start ($listScrolledWindow);
$buttonHBox->pack_start ($clearButton, false , false , 3 );
$buttonHBox->pack_start ($autoButton, false , false , 3 );
$buttonHBox->pack_end ($addButton, false , false , 3 );
$mainVBox->pack_start ($topVBox);
$mainVBox->pack_start ($bottomVBox);
$mainVBox->pack_start ($instructions);
$mainVBox->pack_start ($buttonHBox);
return array (&$mainVBox, new GtkLabel ('Depenedencies'));
* Creates the container and label for the add replacements
* Replacements are install time search and replace strings
* that can be used to set certain package variables to
* values found on the user's system or that are specific
* to the version of the installed package.
* This package uses a replacement to put the proper version
* number in the about window so that I don't have to go and
* recode that every time.
* @return array The page container and a label for the tab.
function _createAddReplacementsPage ()
$mainVBox = & new GtkVBox ();
$globalVBox = & new GtkVBox ();
$globalHBox0 = & new GtkHBox ();
$globalHBox1 = & new GtkHBox ();
$globalHBox2 = & new GtkHBox ();
$globalHBox3 = & new GtkHBox ();
$fileVBox = & new GtkVBOX ();
$fileHBox0 = & new GtkHBox ();
$fileHBox1 = & new GtkHBox ();
$fileHBox2 = & new GtkHBox ();
$fileHBox3 = & new GtkHBox ();
$fileHBox4 = & new GtkHBox ();
// Create two success/failure labels.
$globalSuccess = & new GtkLabel ('');
$fileSuccess = & new GtkLabel ('');
// There are two types of replacements: Global and file.
// First we will set up the global replacements.
// We can do this with a few combo boxes. We will use
// one for the type and one for the to value. The to
// values are basically predefined sets that won't
// change much. I am not concerned about hard coding
// these values into the application.
// We need to work kind of backwards and create the many
// to widgets first. Then we can create the type combo.
$globalToPHP = & new GtkEntry ();
$globalToPEAR = & new GtkCombo ();
$globalToPackage = & new GtkCombo ();
$globalToWidgets = array ('php-const' => &$globalToPHP,
'pear-config' => &$globalToPEAR,
'package-info' => &$globalToPackage
// We need a box for the to widgets so that we can swap
$globalToWidgetBox = & new GtkHBox ();
// The PHP widget is easy. It is just an entry because
// there are way to many constants to list.
// The PEAR widget on the other hand has a shorter list
// of valid values. We will get them using PEAR_Config.
$globalToPEARList = $globalToPEAR->list;
$globalToPEAREntry = $globalToPEAR->entry;
$globalToPEARList->set_selection_mode (GTK_SELECTION_SINGLE );
$globalToPEAREntry->set_text ('Select One');
$globalToPEAREntry->set_editable (false );
// Add the valid values to the list.
require_once 'PEAR/Config.php';
$pearConfig = & new PEAR_Config ();
foreach ($pearConfig->getKeys () as $pearConfigKey) {
$item = & new GtkListItem ();
$label = & new GtkLabel ($pearConfigKey);
$box->pack_start ($label, false , false , 10 );
$globalToPEAR->set_item_string ($item, $pearConfigKey);
$item->set_data ('type', $pearConfigKey);
$globalToPEARList->add ($item);
// The package-info widget is a little different. I can't
// find a method to get the legal values for this set of
// replacements. Therefore, I have to hard code the array.
// It will also serve as the array for the file replacements.
$globalToPackageList = $globalToPackage->list;
$globalToPackageEntry = $globalToPackage->entry;
$globalToPackageList->set_selection_mode (GTK_SELECTION_SINGLE );
$globalToPackageEntry->set_text ('Select One');
$globalToPackageEntry->set_editable (false );
$packageOptions = array ('name', 'summary', 'description', 'version',
'license', 'state', 'notes', 'date');
foreach ($packageOptions as $option) {
$item = & new GtkListItem ();
$label = & new GtkLabel ($option);
$box->pack_start ($label, false , false , 10 );
$globalToPackage->set_item_string ($item, $option);
$item->set_data ('type', $option);
$globalToPackageList->add ($item);
// The globalType combo will not change.
$globalTypeCombo = & new GtkCombo ();
$globalTypeList = $globalTypeCombo->list;
$globalTypeEntry = $globalTypeCombo->entry;
$globalTypeList->set_selection_mode (GTK_SELECTION_SINGLE );
$globalTypeEntry->set_text ('Select One');
$globalTypeEntry->set_editable (false );
// When the entry's value changes, we want to change the
$globalTypeEntry->connect ('changed', array (&$this, '_switchToWidget'), $globalToWidgets, $globalToWidgetBox);
// Add the globalTypes to the select box.
$globalTypes = array ('php-const', 'pear-config', 'package-info');
for ($i = 0; $i < count($globalTypes); $i++ ) {
$item = & new GtkListItem ();
$label = & new GtkLabel ($globalTypes[$i]);
$box->pack_start ($label, false , false , 10 );
$globalTypeCombo->set_item_string ($item, $globalTypes[$i]);
$item->set_data ('type', $globalTypes[$i]);
$globalTypeList->add ($item);
// The last part of the global puzzle is the from widget.
// This is just an entry that will hold the value in the
// package files that should be replaced.
$globalFromEntry = & new GtkEntry ();
// It also helps to have buttons to do the actual work.
$globalButtonBox = & new GtkHBox ();
$globalAddButton = & new GtkButton ('Add Replacement');
$globalAddButton->connect_object ('clicked', array ($this, '_addReplacement'), NULL , $globalTypeCombo, $globalToWidgetBox, $globalFromEntry, $globalSuccess);
$globalButtonBox->pack_end ($globalAddButton, false , false , 5 );
// Next we will set up the file specific replacments.
// For this we will need a way to get all of the files
// that are to be included in the packaging. If PFM
// doesn't have a public method for getting these files
// then we will not be able to do this. It will be up to
// the developer to edit the file manually.
// Until there is a public method, we can use the
// PEAR_PackageFileManager_File class to get all of the
// Start by creating the widgets for each field.
$fileFileCombo = & new GtkCombo ();
$fileTypeCombo = & new GtkCombo ();
$fileFromEntry = & new GtkEntry ();
$fileToWidgetBox = & new GtkHBox ();
$fileToPHP = & new GtkEntry ();
$fileToPEAR = & new GtkCombo ();
$fileToPackage = & new GtkCombo ();
$fileToWidgets = array ('php-const' => &$fileToPHP,
'pear-config' => &$fileToPEAR,
'package-info' => &$fileToPackage
// Next fill the file combo list.
$fileFileList = $fileFileCombo->list;
$fileFileEntry = $fileFileCombo->entry;
$fileFileList->set_selection_mode (GTK_SELECTION_SINGLE );
$fileFileEntry->set_text ('Select One');
$fileFileEntry->set_editable (false );
// Create a file list generator.
// We can't do this until after we have the package options.
require_once 'PEAR/PackageFileManager/File.php';
$pfmFile = new PEAR_PackageFileManager_File ($this->_packageFileManager, $this->_options);
foreach ($pfmFile->dirList ($this->_options['packagedirectory']) as $file) {
if (PEAR ::isError ($file)) {
$this->_pushWarning ($result->getCode (), array ());
// Shorten file to a relative path from the package directory.
$shortFile = substr($file, strlen($this->_options['packagedirectory']));
$item = & new GtkListItem ();
$label = & new GtkLabel ($shortFile);
$box->pack_start ($label, false , false , 10 );
$fileFileCombo->set_item_string ($item, $shortFile);
$item->set_data ('type', $file);
$fileFileList->add ($item);
// The PHP widget is easy. It is just an entry because
// there are way to many constants to list.
// The PEAR widget on the other hand has a shorter list
// of valid values. We will get them using PEAR_Config.
$fileToPEARList = $fileToPEAR->list;
$fileToPEAREntry = $fileToPEAR->entry;
$fileToPEARList->set_selection_mode (GTK_SELECTION_SINGLE );
$fileToPEAREntry->set_text ('Select One');
$fileToPEAREntry->set_editable (false );
// Add the valid values to the list.
foreach ($pearConfig->getKeys () as $pearConfigKey) {
$item = & new GtkListItem ();
$label = & new GtkLabel ($pearConfigKey);
$box->pack_start ($label, false , false , 10 );
$fileToPEAR->set_item_string ($item, $pearConfigKey);
$item->set_data ('type', $pearConfigKey);
$fileToPEARList->add ($item);
// The package-info widget is a little different. I can't
// find a method to get the legal values for this set of
// replacements. Therefore, I have to hard code the array.
// It will also serve as the array for the file replacements.
$fileToPackageList = $fileToPackage->list;
$fileToPackageEntry = $fileToPackage->entry;
$fileToPackageList->set_selection_mode (GTK_SELECTION_SINGLE );
$fileToPackageEntry->set_text ('Select One');
$fileToPackageEntry->set_editable (false );
$packageOptions = array ('name', 'summary', 'description', 'version',
'license', 'state', 'notes', 'date');
foreach ($packageOptions as $option) {
$item = & new GtkListItem ();
$label = & new GtkLabel ($option);
$box->pack_start ($label, false , false , 10 );
$fileToPackage->set_item_string ($item, $option);
$item->set_data ('type', $option);
$fileToPackageList->add ($item);
// The fileType combo will not change.
$fileTypeCombo = & new GtkCombo ();
$fileTypeList = $fileTypeCombo->list;
$fileTypeEntry = $fileTypeCombo->entry;
$fileTypeList->set_selection_mode (GTK_SELECTION_SINGLE );
$fileTypeEntry->set_text ('Select One');
$fileTypeEntry->set_editable (false );
// When the entry's value changes, we want to change the
$fileTypeEntry->connect ('changed', array (&$this, '_switchToWidget'), $fileToWidgets, $fileToWidgetBox);
// Add the fileTypes to the select box.
$fileTypes = array ('php-const', 'pear-config', 'package-info');
for ($i = 0; $i < count($fileTypes); $i++ ) {
$item = & new GtkListItem ();
$label = & new GtkLabel ($fileTypes[$i]);
$box->pack_start ($label, false , false , 10 );
$fileTypeCombo->set_item_string ($item, $fileTypes[$i]);
$item->set_data ('type', $fileTypes[$i]);
$fileTypeList->add ($item);
// The last part of the file puzzle is the from widget.
// This is just an entry that will hold the value in the
// package files that should be replaced.
$fileFromEntry = & new GtkEntry ();
// It also helps to have buttons to do the actual work.
$fileButtonBox = & new GtkHBox ();
$fileAddButton = & new GtkButton ('Add Replacement');
$fileAddButton->connect_object ('clicked', array ($this, '_addReplacement'), $fileFileCombo, $fileTypeCombo, $fileToWidgetBox, $fileFromEntry, $fileSuccess);
$fileButtonBox->pack_end ($fileAddButton, false , false , 5 );
$globalHBox0->pack_start ($globalSuccess, true ,true , 5 );
$globalHBox1->pack_start (new GtkLabel ('Type:'), false ,false , 5 );
$globalHBox1->pack_end ($globalTypeCombo, false ,false , 5 );
$globalHBox2->pack_start (new GtkLabel ('From: (ex: @php_bin@)'), false ,false , 5 );
$globalHBox2->pack_end ($globalFromEntry, false ,false , 5 );
$globalHBox3->pack_start (new GtkLabel ('To:'), false ,false , 5 );
$globalHBox3->pack_end ($globalToWidgetBox, false ,false , 5 );
// The global to widget box starts off the php-const entry.
$globalToWidgetBox->pack_start ($globalToPHP, false , false , 0 );
// Put the hBoxes in the vBox.
$globalVBox->pack_start ($globalHBox0, false , false , 5 );
$globalVBox->pack_start ($globalHBox1, false , false , 5 );
$globalVBox->pack_start ($globalHBox2, false , false , 5 );
$globalVBox->pack_start ($globalHBox3, false , false , 5 );
$globalVBox->pack_start ($globalButtonBox, false , false , 5 );
// Pack up the file pieces.
$fileHBox0->pack_start ($fileSuccess, true ,true , 5 );
$fileHBox1->pack_start (new GtkLabel ('File:'), false ,false , 5 );
$fileHBox1->pack_end ($fileFileCombo, false ,false , 5 );
$fileHBox2->pack_start (new GtkLabel ('Type:'), false ,false , 5 );
$fileHBox2->pack_end ($fileTypeCombo, false ,false , 5 );
$fileHBox3->pack_start (new GtkLabel ('From: (ex: @php_bin@)'), false ,false , 5 );
$fileHBox3->pack_end ($fileFromEntry, false ,false , 5 );
$fileHBox4->pack_start (new GtkLabel ('To:'), false ,false , 5 );
$fileHBox4->pack_end ($fileToWidgetBox, false ,false , 5 );
// The file to widget box starts off the php-const entry.
$fileToWidgetBox->pack_start ($fileToPHP, false , false , 0 );
// Put the hBoxes in the vBox.
$fileVBox->pack_start ($fileHBox0, false , false , 5 );
$fileVBox->pack_start ($fileHBox1, false , false , 5 );
$fileVBox->pack_start ($fileHBox2, false , false , 5 );
$fileVBox->pack_start ($fileHBox3, false , false , 5 );
$fileVBox->pack_start ($fileHBox4, false , false , 5 );
$fileVBox->pack_start ($fileButtonBox, false , false , 5 );
// Create a pretty frame for the global and file pieces.
$globalFrame = & new GtkFrame ('Global Replacements');
$fileFrame = & new GtkFrame ('File Replacements');
$globalFrame->set_shadow_type (GTK_SHADOW_OUT );
$fileFrame->set_shadow_type (GTK_SHADOW_OUT );
// Add the global and file boxes to the frames.
$globalFrame->add ($globalVBox);
$fileFrame->add ($fileVBox);
// Put the global and file frames in the main box.
$mainVBox->pack_start ($globalFrame, false , false , 5 );
$mainVBox->pack_start ($fileFrame, false , false , 5 );
return array (&$mainVBox, new GtkLabel ('Replacements'));
* Updates the package file directory entry with the value
* from the file selection.
* Takes the value of the file selection and assigns it to
* the entry widget. We have to use a helper method because
* we need the value in real time. After the value is set,
* the file selection is hidden.
* @param object &$entry The GtkEntry that should get the value.
* @param object &$fileSelection The GtkFileSelection holding the value.
function _setPackageDirEntry (&$entry, &$fileSelection)
$entry->set_text ($fileSelection->get_filename ());
* Sets that relate to the entire package, regardless of
* Package options are those such as: base install directory,
* the license, the package name, etc. We can't set the options
* until we have the rest from the release page. Therefore we
* must temporarily store them in the _options member.
* If all goes well, the user will be taken to the next page.
* @param object $dirEntry The GtkEntry holding the package directory.
* @param object $nameEntry The GtkEntry holding the package name.
* @param object $baseInstall The GtkEntry holding the base install directory.
* @see _setReleaseOptions()
function _setPackageOptions ($dirEntry, $nameEntry, $baseInstall,
$summaryEntry, $descriptionText)
// Create an array to hold the information.
// Check to see of a package directory was given.
if ($dirEntry->get_text ()) {
$options['packagedirectory'] = $dirEntry->get_text ();
// Check to see if a package name was given.
if ($nameEntry->get_text ()) {
$options['package'] = $nameEntry->get_text ();
// Check to see fi a baseinstall directory was given.
if ($baseInstall->get_text ()) {
$options['baseinstalldir'] = $baseInstall->get_text ();
// Check to see if a package summary was given.
if ($summaryEntry->get_text ()) {
$options['summary'] = $summaryEntry->get_text ();
// Check to see if a package description was given.
if ($descriptionText->get_chars (0 , -1 )) {
$options['description'] = $descriptionText->get_chars (0 , -1 );
// Add to the options array. After we get the release
// options, these options array will be passed to the
$this->_options += $options;
* Sets the package file anager release options.
* The release options consist of features including, the
* release date, the package version and state, and the
* Options that do not relate to individual releases are
* adde with {@link _setPackageOptions}.
* This method sets all the options including the package
* options. If there are errors, the user will be taken to
* the warnings page. If there are no errors the user will
* be taken to the add maintainers page.
* @param object $state The GtkCombo holding the state.
* @param object $verEntry The GtkEntry holding the version.
* @param object $notesArea The GtkText holding the release notes.
* @see _setPackageOptions()
function _setReleaseOptions ($state, $verEntry, $notesArea)
$stateItem = $state->list ->selection [0 ];
$options['state'] = $stateItem->get_data ('state');
if ($verEntry->get_text ()) {
$options['version'] = $verEntry->get_text ();
if ($notesArea->get_chars (0 , -1 )) {
$options['notes'] = $notesArea->get_chars (0 , -1 );
// Add to the options array. When the file is saved,
// the options array will be passed to the package
$this->_options += $options;
// Set the options so that other things can be done.
$result = $this->_packageFileManager->setOptions ($this->_options);
if (PEAR ::isError ($result)) {
$this->_pushWarning ($result->getCode (), array ());
// Now that the options are set, we can create some of
$this->_addNotebookPage ($this->_createAddMaintainersPage (), false );
$this->_addNotebookPage ($this->_createAddDependenciesPage (), false );
$this->_addNotebookPage ($this->_createAddReplacementsPage (), false );
* Calls the package file manager's debug method.
* The file should always be previewed before it is saved.
* @see _writePackageFile()
$previewWindow = & new GtkWindow ();
$previewWindow->set_title ('Preview');
// Create some containers for layout.
$frame = & new GtkFrame ('package.xml');
$sWin = & new GtkScrolledWindow ();
// Set some display properties.
$sWin->set_policy (GTK_POLICY_AUTOMATIC , GTK_POLICY_AUTOMATIC );
$text->set_editable (false );
$text->set_line_wrap (false );
$text->set_usize (200 , 200 );
// Add everything together.
$previewWindow->add ($vBox);
$vBox->pack_start ($frame);
// Get the preview and check for errors.
// I am calling writePackageFile with cli interface directly
// because I don't ever want the user to see entities. It
// is possible that they are running this app with PHP
// reporting as cgi. This accomplishes the same thing as
// debugPackageFile() in command line mode.
$result = $this->_packageFileManager->writePackageFile (false );
if (PEAR ::isError ($result)) {
$this->_pushWarning ($result->getCode (), array ());
// Get rid of the widgets to conserve resources.
// Clear out any text that may be left over.
$text->delete_text (0 , -1 );
$text->insert_text ($preview, 0 );
// Add a close button and a save button.
$bottomBox = & new GtkHBox ();
$closeButton = & new GtkButton ('Close');
$saveButton = & new GtkButton ('Save');
$saveButton->connect_object ('clicked', array (&$this, '_writePackageFile'));
$saveButton->connect_object_after ('clicked', array (&$previewWindow, 'destroy'));
$closeButton->connect_object ('clicked', array (&$previewWindow, 'destroy'));
// Pack the buttons together and add it to the window.
$bottomBox->pack_start ($closeButton, false , false , 3 );
$bottomBox->pack_end ($saveButton, false , false , 3 );
$vBox->pack_start ($bottomBox, false , false , 3 );
$previewWindow->show_all ();
// Track that the file has been previewed.
* Writes the package file to package.xml.
* The package file should be tested first using the
* {@link _previewFile} method. The file is written to the
* directory given as the package file directory on the
* If there are problems writing the file, the user will
* be taken to the warnings page.
* @see _previewPackageFile()
function _writePackageFile ()
// Check that the file has been previewed first.
$this->showWarnings('You must preview the file before you can save it.');
$result = $this->_packageFileManager->writePackageFile ();
if (PEAR ::isError ($result)) {
$this->_pushWarning ($result->getCode (), array ());
// Update the saved state.
* Uses PEAR to package the package.
* Does the same thing that calling $ pear package package.xml
* would do but doesn't require the user to use the command
function _packagePackage ()
// Check the saved state.
// Don't need to check previewed because you can't save
$this->showWarnings('You must save the file before you can package it.');
require_once 'PEAR/Packager.php';
$packager = & new PEAR_Packager ();
$retVal = $packager->package ($this->_options['packagedirectory'] . '/' . 'package.xml');
if (PEAR ::isError ($result)) {
$this->_pushWarning ($result->getCode (), array ());
* Adds the dependencies from the package file to the cList.
* This method adds the dependencies currently listed in the
* package file to the cList. This will not retrieve any real
* @param object $cList The list that should display the packages.
function _getDependencies ($cList)
$options = $this->_packageFileManager->getOptions ();
foreach ($options['deps'] as $dep) {
$this->_addToCList ($cList, array ($dep['name'], $dep['version'], ($dep['optional'] == 'yes' ? 'optional' : '')));
* Swaps out the current to widget with the needed one.
* The to widget gets changed to a widget that will let
* the user enter an appropriate value. This can be either
* This method can be used for both the global and file
* @param object $entry The GtkEntry whose value was changed.
* @param array &$toWidgets The possible to widgets.
* @param object $toBox The box that will hold the widget.
function _switchToWidget ($entry, &$toWidgets, $toBox)
// Figure out what the selected value is.
$selection = $entry->get_text ();
// Make sure something was selected.
// Unparent the box's current child.
$boxChild = $toBox->children [0 ];
$child = $boxChild->widget;
// Add the correct widget to the box.
$toBox->pack_start ($toWidgets[$selection], false , false , 0 );
* Adds the replacement information to the package file manager.
* Both the global and file replacements use this method. The
* difference is that global replacements do not supply a file
* @param object $pathWidget The widget holding the file path.
* @param object $typeWidget The widget holding the replace type.
* @param object $toWidget The widget holding the to value.
* @param object $fromWidget The widget holding the from value.
* @param object $status The label that will inform success.
function _addReplacement ($pathWidget, $typeWidget, $toWidget, $fromWidget, $success)
// Reset the previewed and saved states.
// Check to see if a widget was passed for the path.
if (!isset ($pathWidget)) {
$pathItem = $pathWidget->list ->selection [0 ];
// Make sure something was selected.
// Collect the rest of the data.
$typeItem = $typeWidget->list ->selection [0 ];
$type = $typeItem->get_data ('type');
$toWidgetChild = $toWidget->children [0 ];
$toWidget = $toWidgetChild->widget;
$to = $toWidget->get_text ();
$toItem = $toWidget->list ->selection [0 ];
$to = $toItem->get_data ('type');
$from = $fromWidget->get_text ();
// Make sure something was selected.
if (!isset ($type) || !isset ($to) || !isset ($from)) {
$this->showWarnings((isset ($pathWidget) ? 'File' : 'Global') . ' Replacement information is missing. Please make sure all fields are filled.');
// Figure out which type of replacement this is <global|file>.
if (!isset ($pathWidget)) {
// If no file path widget, this must be global.
$result = $this->_packageFileManager->addGlobalReplacement ($type, $from, $to);
// If there is a file path widget this must be a file
$result = $this->_packageFileManager->addReplacement ($path, $type, $from, $to);
if (PEAR ::isError ($result)) {
$this->_pushWarning ($result->getCode (), array ());
// Make a note on the replacements page.
$success->set_text ('Replacement failed for ' . $from);
// Then jump to the warnings.
// Make a note about successful replacement.
$success->set_text ($from . ' will be replaced with ' . $to);
// Update the from widget as a second visual indication
$fromWidget->set_text ('');
* Adds the data array to the GtkCList.
* First this method checks to see if the data is already
* present. (It only checks the first column.) Then it
* @param object $cList The GtkCList to which data will be added.
* @param array $data The elements to be added to the list.
function _addToCList ($cList, $data)
// Look for the same first data element and remove it if found.
for ($i = 0; $i < $cList->rows; ++ $i) {
if ($data[0 ] == $cList->get_text ($i, 0 )) {
// Add the package to the clist.
$cList->insert (0 , $data);
* Takes data from the GtkCTree and puts it in the GtkCList.
* This is used to take the values from the dependency tree
* and put them in the dependency list. Values are not added
* as dependencies until the add dependencies button is
* When a row is selected, the tree and node are passed to this
* method. When the node is created, some data was stored with
* it. That data is the package name and the version. After the
* data is extracted, it is passed to the cList.
* @param object $tree The GtkCTree containing the selected node.
* @param object $node The GtkCTree that was selected.
* @param mixed $unknown Who knows. Seriously, if you do email me.
* It gets passed by the event and we don't
* know what it is. I will add it to the
* docs if you can tell me. Thanks.
* @param object $list The GtkCList that will hold the data from
* the selected tree node.
function _treeToCList ($tree, $node, $unknown, $list)
// Get the data associated with this row.
$data = $tree->node_get_row_data ($node);
// Only add if there is some data.
// This will prevent package nodes from being
// added. We only want version nodes.
$this->_addToCList ($list, $data);
* Toggles the optional status of a dependency when it is
* PFM lets you mark a package as an optional dependency.
* This means that a given package will be used if it is
* available but it is not required for proper operation.
* This package is optionally dependent on Gtk_FileDrop
* and also PHP_Compat. This package will work without
* them but if you have them it will add more features.
* @param object $cList The GtkClist that holds the data.
* @param integer $row The row that was selected (starts at 0)
* @param integer $col The column that was selected (starts at 0)
* @param object $event The 'select-row' event
function _toggleOptional ($cList, $row, $col, $event)
// Figure out the current status.
$optional = $cList->get_text ($row, 2 );
// Set the last column to be the oposite of what it is now.
$cList->set_text ($row, 2 , ($optional == 'optional' ? '' : 'optional'));
* Adds the selected packages as dependencies.
* All packages from the GtkCList are added as dependencies to
* the package being built. As of 2005-03-18, only package
* dependencies may be added using this tool. Other types (php,
* etc.) may be added at a later date.
* @param object $cList The GtkCList holding the packages.
function _addDependencies ($cList)
// Clear the previewed and saved states.
// Loop through all of the packages in the list.
for ($i = 0; $i < $cList->rows; ++ $i) {
// Get the optional status.
$optional = $cList->get_text ($i, 2 );
// Attempt to add the package as a dependency.
$result = $this->_packageFileManager->addDependency ($cList->get_text ($i, 0 ), $cList->get_text ($i, 1 ), 'ge', 'pkg', !empty ($optional));
if (PEAR ::isError ($result)) {
$this->_pushWarning ($result->getCode (), array ());
// There is no need to stop adding the rest just
* Adds a maintainer to the package file.
* Checks that all of the information was given then tries
* to add the maintainer. If there is a problem, the user
* will be taken to the warnings page.
* @param object $handle The entry that has the developer's handle.
* @param object $role The combo that has the developer's role.
* @param object $name The entry that has the developer's name.
* @param object $email The entry that has the developer's email.
* @param object $currentList The GtkCList that will show the developers.
function _addMaintainer ($handle, $role, $name, $email, $currentList)
// Reset the previewed and saved states.
// The role is a little tricky.
$handleText = $handle->get_text ();
$nameText = $name->get_text ();
$emailText = $email->get_text ();
$roleItem = $role->list ->selection [0 ];
// Make sure something was selected.
$roleText = strtolower($roleItem->get_data ('role'));
// Check to make sure everything is there.
if (empty ($handleText) || empty ($nameText) || empty ($emailText) || empty ($roleText)) {
// Add the warning to the warning stack.
$this->showWarnings('Maintainer information is missing. Please check all fields.');
$result = $this->_packageFileManager->addMaintainer ($handleText, $roleText, $nameText, $emailText);
if (PEAR ::isError ($result)) {
$this->_pushWarning ($result->getCode (), array ());
// Update the current list.
$this->_addToCList ($currentList, array ($nameText, $emailText, $roleText));
* Adds the developers from the previous release to the given
* This method is used when the developers page is created. It
* puts the developers from the previous release into the cList.
* Developers added as of this release are added by
* {@link _addMaintainer()}.
* @param object $cList The GtkCList that will have the developer added.
function _listDevelopers ($cList)
// Then add each developer.
$options = $this->_packageFileManager->getOptions ();
foreach ($options['maintainers'] as $maintainer) {
$this->_addToCList ($cList, array ($maintainer['name'],
* Imports the options from a previously created file.
* After importing the options, this method also updates the
* values of some widgets.
* @param object $packageDirEntry The GtkEntry holding the package directory.
* @param object $pacakgeNameEntry The GtkEntry holding the package name.
* @param object $baseEntry The GtkEntry holding the base install directory.
* @param object $summaryEntry The GtkEntry holding the package summary.
* @param object $descriptiontText The GtkText holding the package description.
function _importPackageOptions ($packageDirEntry, $packageNameEntry, $baseEntry, $summaryEntry, $descriptionText)
// Figure out if there is a package file in the given
if (@is_dir($packageDirEntry->get_text ())) {
$packageFile = $packageDirEntry->get_text () . '/package.xml';
} elseif (strrpos($packageDirEntry->get_text (), 'package.xml')) {
// Check if the path is straight to the file not the
$packageFile = $packageDirEntry->get_text ();
// No package file to load.
// If we can't read it, we can't load it.
// We have a readable package file. Hopefully it will
$result = $this->_packageFileManager->importOptions ($packageFile);
if (PEAR ::isError ($result)) {
// Try setting a bunch of garbage options first if
// PFM complains about running setOptions().
// Please note, this is a dirty hack to make up for
// some deficiencies in PFM-1.5.0
if ($result->getCode() == PEAR_PACKAGEFILEMANAGER_RUN_SETOPTIONS) {
$tmpOptions = array('packagedirectory' => '/tmp',
$result2 = $this->_packageFileManager->setOptions($tmpOptions);
// Check to see if our garbage was accepted.
if (PEAR::isError($result2)) {
$this->_pushWarning($result2->getCode(), array());
$result2 = $this->_packageFileManager->importOptions($packageFile);
if (PEAR::isError($result2)) {
// Still no luck. Give up.
$this->_pushWarning($result2->getCode(), array());
// An error, but not about setting options.
$this->_pushWarning ($result->getCode (), array ());
// No problems. Load the data into the widgets.
$options = $this->_packageFileManager->getOptions ();
$packageNameEntry->set_text ($options['package']);
$baseEntry->set_text ($options['baseinstalldir']);
$summaryEntry->set_text ($options['summary']);
// First clear out any text in the description area.
$descriptionText->delete_text (0 , -1 );
$descriptionText->insert_text ($options['description'], 0 );
* Adds a warning to the warning stack.
* After adding the error to the stack, the user is taken to the
* warnings page. When the page is switched, warnings are popped
* @param array $info Associative array of message replacement info.
function _pushWarning ($code, $info)
// Add the warning to the package file manager warnings.
$this->_packageFileManager->pushWarning ($code, $info);
// Then jump to the warnings page.
Documentation generated on Mon, 11 Mar 2019 14:21:08 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.
|