cvs: pear /PEAR_Frontend_Gtk2 Gtk2.php package.xml /PEAR_Frontend_Gtk2/Gtk2 About.php Channels.php Checks.php Config.php Installation.php Package.php
Packages.php installer.glade run.phpw runicon.png /PEAR_Frontend_Gtk2/Gtk2/pixmaps default.png gnope.org.png pear.chiaraquartet.net.png
pear.php.net.png pecl.php.net.png /PEAR_Frontend_Gtk2/Gtk2/pixmaps/progress load-anim-1.png load-anim-2.png load-anim-3.png load-anim-4.png
load-anim-6.png /PEAR_Frontend_Gtk2/tests ConfigTest.php ExpanderTest.phpw PackageTest.php TimeDiff.php runtests.php

From: Date: Thu, 15 Dec 2005 09:43:21 +0000
Subject: cvs: pear /PEAR_Frontend_Gtk2 Gtk2.php package.xml /PEAR_Frontend_Gtk2/Gtk2 About.php Channels.php Checks.php Config.php Installation.php Package.php
Packages.php installer.glade run.phpw runicon.png /PEAR_Frontend_Gtk2/Gtk2/pixmaps default.png gnope.org.png pear.chiaraquartet.net.png
pear.php.net.png pecl.php.net.png /PEAR_Frontend_Gtk2/Gtk2/pixmaps/progress load-anim-1.png load-anim-2.png load-anim-3.png load-anim-4.png
load-anim-6.png /PEAR_Frontend_Gtk2/tests ConfigTest.php ExpanderTest.phpw PackageTest.php TimeDiff.php runtests.php
Groups: php.pear.cvs 
Request: Send a blank email to pear-cvs+get-36879@lists.php.net to get a copy of this message
cweiske Thu Dec 15 09:43:21 2005 EDT Added files: /pear/PEAR_Frontend_Gtk2 Gtk2.php package.xml /pear/PEAR_Frontend_Gtk2/Gtk2 About.php Channels.php Checks.php Config.php Installation.php Package.php Packages.php installer.glade run.phpw runicon.png /pear/PEAR_Frontend_Gtk2/Gtk2/pixmaps default.png gnope.org.png pear.chiaraquartet.net.png pear.php.net.png pecl.php.net.png /pear/PEAR_Frontend_Gtk2/Gtk2/pixmaps/progress load-anim-1.png load-anim-2.png load-anim-3.png load-anim-4.png load-anim-6.png /pear/PEAR_Frontend_Gtk2/tests ConfigTest.php ExpanderTest.phpw PackageTest.php TimeDiff.php runtests.php Log: Initial commit

http://cvs.php.net/viewcvs.cgi/pear/PEAR_Frontend_Gtk2/Gtk2.php?view=markup&rev=1.1 Index: pear/PEAR_Frontend_Gtk2/Gtk2.php +++ pear/PEAR_Frontend_Gtk2/Gtk2.php <?php require_once 'PEAR/Config.php'; require_once 'PEAR/Frontend.php'; require_once 'PEAR/Frontend/Gtk2/About.php'; require_once 'PEAR/Frontend/Gtk2/Channels.php'; require_once 'PEAR/Frontend/Gtk2/Config.php'; require_once 'PEAR/Frontend/Gtk2/Packages.php'; require_once 'PEAR/Frontend/Gtk2/Installation.php'; /** * Graphical frontend for PEAR, based on PHP-Gtk2 * * TODO: * - Package categories aren't updated/extendet if there is an error at startup loading/packages are refreshed and a new category is required * - channel discovery * - Drop package file onto install button -> install it * - Warn if the package list is older than 5 days * - upgrade-all menu option * - Filter by upgradeable/installed/installable/all packages * - Install pecl packages - error messages aren't shown * * Don't know how to do: * - installation dialog showing has to be updated correctly * - Installation: shrink window if expander is collapsed * * Done: * - better installation ok icon * - Window icon - shows the php icon on windows currently * - When no internet connection on startup, no categories are loaded and no local packages are shown * - When no pear cache directory exists, the check warning is shown - pear cache directory is created now * - uninstall: pear/liveuser is required by installed package "pear/Event_Dispatcher" * - use menu options (deps, nodeps) * - refresh online info (clear cache or so) * - offline mode * - save and load settings * - scroll text in installation * * @author Christian Weiske <cweiske@php.net> */ class PEAR_Frontend_Gtk2 extends PEAR_Frontend { /** * The widgets which shall be loaded from the glade * file into the $arWidgets array * @var array */ protected static $arRequestedWidgets = array( 'dlgInstaller', 'lstCategories', 'lstPackages', 'txtPackageInfo', 'cmbChannel', 'imgChannelLogo', 'lblSelectedCategory', 'hboxCategoryInfo', 'btnInstall','btnUninstall','lblBtnInstall','evboxSelectedCategory','expPackageInfo', 'mnuOptDepsNo','mnuOptDepsReq','mnuOptDepsAll','mnuOptDepNothing', 'mnuOffline','mnuQuit','mnuAbout','mnuUpdateOnline','mnuUpdateLocal', 'dlgProgress', 'lblDescription', 'imgProgress', 'lblProgress', 'progBar' ); protected $nProgressImage = 1; /** * Array with images used for the progress animation */ protected $arAnimationImages = array(); /** * Requested widgets are loaded from glade into this array. * So this is an associative array with all required widgets * from the glade file: name => widget object * @var array */ protected $arWidgets; /** * The PEAR_Frontend_Gtk2_Installation object to use * @var PEAR_Frontend_Gtk2_Installation */ protected $installer = null; protected $selectedPackage = null; protected $strSelectedCategoryName = null; protected $strSelectedCategoryKey = null; /** * The package information class instance * @var PEAR_Frontend_Gtk2_Packages */ protected $packages = null; const CATEGORY_ALL = 12345678; const CATEGORY_SELECTED = 12345679; /** * Special categories which are added to the * channel categories * @var array */ protected static $arSpecialCategories = array( PEAR_Frontend_Gtk2::CATEGORY_ALL => '*All packages', // PEAR_Frontend_Gtk2::CATEGORY_SELECTED => '*Selected for install' ); public function __construct() { $this->loadConfig(); $this->buildDialog(); PEAR_Frontend_Gtk2_Config::loadConfig(); PEAR_Frontend_Gtk2_Config::loadCurrentConfigIntoGui($this); //After all has been initiated, load the data PEAR_Frontend_Gtk2_Channels::loadChannels( $this->arWidgets['cmbChannel'], $this->config, PEAR_Frontend_Gtk2_Config::$strDefaultChannel ); }//public function __construct() function loadConfig() { $this->config = PEAR_Config::singleton(); $this->packages = new PEAR_Frontend_Gtk2_Packages($this->config); }//function loadConfig() public function quitApp() { PEAR_Frontend_Gtk2_Config::loadConfigurationFromGui($this); PEAR_Frontend_Gtk2_Config::saveConfig(); Gtk::main_quit(); }//public function quitApp() /** * load the glade file, load the widgets, connect the signals */ protected function buildDialog() { $this->glade = new GladeXML(dirname(__FILE__) . '/Gtk2/installer.glade'); foreach (self::$arRequestedWidgets as $strWidgetName) { $this->arWidgets[$strWidgetName] = $this->glade->get_widget($strWidgetName); } $this->arWidgets['dlgInstaller']->connect_simple('destroy', array($this, 'quitApp')); $strIcon = dirname(__FILE__) . '/Gtk2/runicon.png'; if (file_exists($strIcon)) { $this->arWidgets['dlgInstaller']->set_icon_from_file($strIcon); } $this->arWidgets['lblSelectedCategory']->set_use_markup(true); $this->arWidgets['cmbChannel']->connect('changed', array($this, 'selectChannel')); $this->arWidgets['lstCategories']->set_model(new GtkListStore(Gtk::TYPE_STRING, Gtk::TYPE_STRING)); $cell_renderer = new GtkCellRendererText(); $column = new GtkTreeViewColumn('test', $cell_renderer, "text", 0); $this->arWidgets['lstCategories']->append_column($column); $this->arWidgets['btnInstall'] ->connect_simple('clicked', array($this, 'installPackage'), true); $this->arWidgets['btnUninstall']->connect_simple('clicked', array($this, 'installPackage'), false); $this->arWidgets['dlgProgress']->connect('delete-event', array($this, 'deleteProgressWindow')); //Menu entries $this->arWidgets['mnuQuit'] ->connect_simple('activate', array($this, 'quitApp')); $this->arWidgets['mnuAbout'] ->connect_simple('activate', array('PEAR_Frontend_Gtk2_About', 'showMe')); $this->arWidgets['mnuUpdateLocal'] ->connect_simple('activate', array($this, 'refreshLocalPackages')); $this->arWidgets['mnuUpdateOnline'] ->connect_simple('activate', array($this, 'refreshOnlinePackages')); //that's channel name and array key of the packages $this->arWidgets['lstPackages']->set_model(new GtkListStore(Gtk::TYPE_STRING, Gtk::TYPE_STRING, Gtk::TYPE_STRING, Gtk::TYPE_STRING, Gtk::TYPE_PHP_VALUE)); $cell_renderer = new GtkCellRendererText(); $colName = new GtkTreeViewColumn('Package', $cell_renderer, "text", 0); $colName->set_resizable(true); $colName->set_sort_column_id(0); $this->arWidgets['lstPackages']->append_column($colName); $colInstalled = new GtkTreeViewColumn('Installed', $cell_renderer, "text", 1); $colInstalled->set_resizable(true); $colInstalled->set_sort_column_id(1); $this->arWidgets['lstPackages']->append_column($colInstalled); $colNew = new GtkTreeViewColumn('New version', $cell_renderer, "text", 2); $colNew->set_resizable(true); $colNew->set_sort_column_id(2); $this->arWidgets['lstPackages']->append_column($colNew); $colSummary = new GtkTreeViewColumn('Summary', $cell_renderer, "text", 3); $colSummary->set_resizable(true); $colSummary->set_sort_column_id(3); $this->arWidgets['lstPackages']->append_column($colSummary); $selCategories = $this->arWidgets['lstCategories']->get_selection(); $selCategories->set_mode(Gtk::SELECTION_SINGLE); $selCategories->connect('changed', array($this, 'selectCategory')); $selPackages = $this->arWidgets['lstPackages']->get_selection(); $selPackages->set_mode(Gtk::SELECTION_SINGLE); $selPackages->connect('changed', array($this, 'selectPackage')); for ($nA = 1; $nA <= 3; $nA++) { $this->arAnimationImages[] = GdkPixbuf::new_from_file(dirname(__FILE__) . '/Gtk2/pixmaps/progress/load-anim-' . $nA . '.png'); } $this->nProgressImage = 0; $this->loadInstaller(); }//protected function buildDialog() protected function loadInstaller() { $this->installer = new PEAR_Frontend_Gtk2_Installation($this->arWidgets['dlgInstaller'], $this->glade); }//protected function loadInstaller() /** * A channel has been selected from the channel combo box * * Has to be public as it is a callback function * * @param GtkComboBox $cmbChannel The channel selection combo box * @param boolean $bSecondTime If the function is being run a second time (because the first run had a problem) - used to detect infinite loops. */ public function selectChannel($cmbChannel, $bSecondTime = false) { $strChannel = $cmbChannel->get_active_text(); $this->setChannelStyles($strChannel); $model = $this->arWidgets['lstCategories']->get_model(); $model->clear(); $this->arWidgets['lstPackages']->get_model()->clear(); //Channel categories $this->packages->setActiveChannel($strChannel); if (!$this->packages->packagesLoaded()) { //show the progress dialog before it gets loaded with the first callback $this->showProgressDialog(true); } try { $arCategories = $this->packages->getCategories(array($this, 'packagesCallback'), $this->getWorkOffline()); } catch (Exception $e) { $this->hideProgressDialog(); $dialog = new GtkMessageDialog( $this->arWidgets['dlgInstaller'], 0, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, 'Can\'t list the categories:' . "\r\n" . $e->getCode() . ': ' . $e->getMessage() . "\r\n\r\nMake sure you have an internet connection." ); $dialog->set_transient_for($this->arWidgets['dlgInstaller']); $dialog->set_position(Gtk::WIN_POS_CENTER_ON_PARENT); $dialog->run(); $dialog->destroy(); if (!$bSecondTime) { //The exception code seem to vary on every run - so I can't check for a certain code. //But as we still can load the local packages, we can work offline. $this->setWorkOffline(true); $this->selectChannel($cmbChannel, true); return; } else { //no chance to do a fix - do nothing return; } } $arCategories = $this->appendSpecialCategories( $arCategories ); foreach ($arCategories as $key => $strCategory) { $model->set($model->append(), 0, $strCategory, 1, $key); } //Clear packages $this->arWidgets['lstPackages']->get_model()->clear(); $this->arWidgets['lstCategories']->get_selection()->select_path('0'); $this->hideProgressDialog(); }//public function selectChannel($cmbChannel, $bSecondTime = false) protected function setChannelStyles($strChannel) { //Logo $strIcon = dirname(__FILE__) . '/Gtk2/pixmaps/' . $strChannel . '.png'; if (!file_exists($strIcon)) { $strIcon = dirname(__FILE__) . '/Gtk2/pixmaps/default.png'; } if (file_exists($strIcon)) { $this->arWidgets['imgChannelLogo']->set_from_file($strIcon); } //Colors $strColorChannel = $strChannel; if (!isset(PEAR_Frontend_Gtk2_Config::$arChannels[$strColorChannel])) { $strColorChannel = 'default'; } $colBg = GdkColor::parse(PEAR_Frontend_Gtk2_Config::$arChannels[$strColorChannel]['background-color']); $colFg = GdkColor::parse(PEAR_Frontend_Gtk2_Config::$arChannels[$strColorChannel]['color']); $this->arWidgets['evboxSelectedCategory']->modify_bg(Gtk::STATE_NORMAL, $colBg); $this->arWidgets['lblSelectedCategory']->modify_fg(Gtk::STATE_NORMAL, $colFg); }//protected function setChannelStyles($strChannel) /** * Appends defined special categories to the given * list * * @param array Array of categories * @return array Array of categories with special ones */ function appendSpecialCategories($arCategories) { foreach (PEAR_Frontend_Gtk2::$arSpecialCategories as $key => $value) { $arCategories[$key] = $value; } return $arCategories; }//function appendSpecialCategories($arCategories) /** * A category has been selected */ function selectCategory($selection) { list($model, $iter) = $selection->get_selected(); if ($iter === null) { $this->arWidgets['lblSelectedCategory']->set_text('No category selected'); return; } $this->strSelectedCategoryName = $model->get_value($iter, 0); $this->strSelectedCategoryKey = $model->get_value($iter, 1); $this->arWidgets['lblSelectedCategory']->set_markup('<b>' . $this->strSelectedCategoryName . '</b>'); if ($this->strSelectedCategoryKey == self::CATEGORY_ALL) { $this->strSelectedCategoryName = null; } $this->showPackageList($this->strSelectedCategoryName); }//function selectCategory($selection) /** * Fill the package list for the given category */ protected function showPackageList($strCategory) { //Show packages $model = $this->arWidgets['lstPackages']->get_model(); $model->clear(); $arPackages = $this->packages->getPackages($strCategory); if (count($arPackages) > 0) { foreach ($arPackages as $key => $package) { $model->set( $model->append(), 0, $package->getName(), 1, $package->getInstalledVersion(), 2, $package->getLatestVersion(), 3, $package->getSummary(), 4, $package ); } } }//protected function showPackageList($strCategory) /** * Update the package list model entries for the given packages. * Useful after installing/uninstalling a package * * @param array $arPackages Array of packages which model entry shall be updated */ protected function updatePackageList($arPackages) { $model = $this->arWidgets['lstPackages']->get_model(); $iter = $model->get_iter_first(); while ($iter !== null) { $package = $model->get_value($iter, 4); if (in_array($package, $arPackages)) { $model->set( $iter, 0, $package->getName(), 1, $package->getInstalledVersion(), 2, $package->getLatestVersion(), 3, $package->getSummary(), 4, $package ); } $iter = $model->iter_next($iter); } }//protected function updatePackageList($arPackages) /** * Callback for the package loading functions */ function packagesCallback($nPackageCount, $nCurrentPackage) { $dlgProgress = $this->arWidgets['dlgProgress']; if ($nPackageCount === true) { //we're done $this->hideProgressDialog(); return; } $this->showProgressDialog(); $this->arWidgets['lblProgress']->set_text($nCurrentPackage . ' / ' . $nPackageCount); $this->arWidgets['progBar']->set_fraction(1/$nPackageCount * $nCurrentPackage); $this->nProgressImage++; if (!isset($this->arAnimationImages[$this->nProgressImage])) { $this->nProgressImage = 0; } //TODO: hold the images in memory $this->arWidgets['imgProgress']->set_from_pixbuf($this->arAnimationImages[$this->nProgressImage]); while (Gtk::events_pending()) { Gtk::main_iteration();} }//function packagesCallback($nPackageCount, $nCurrentPackage) public function selectPackage($selection) { list($model, $iter) = $selection->get_selected(); if ($iter === null) { $strDescription = ''; $this->setSelectedPackage(null); $this->arWidgets['btnUninstall']->hide(); $this->arWidgets['btnInstall'] ->set_sensitive(false); } else { $package = $model->get_value($iter, 4); $this->setSelectedPackage($package); $strDescription = $package->getDescription(); $this->ableInstallButtons($package); if ($package->getInstalledVersion() === null || $package->getInstalledVersion() == '') { $this->arWidgets['lblBtnInstall']->set_label('Inst_all package'); } else { $this->arWidgets['lblBtnInstall']->set_label('Upgr_ade package'); } } $this->arWidgets['txtPackageInfo']->get_buffer()->set_text($strDescription); }//public function selectPackage($selection) /** * Enables or disables the install buttons depending * on the installation status of $package * * @param PEAR_Frontend_Gtk2_Package $package The package to check */ protected function ableInstallButtons($package) { if ($package === null) { return; } $this->arWidgets['btnInstall']->set_sensitive( $package->getLatestVersion() !== null && $package->getLatestVersion() !== '' ); if ($package->getInstalledVersion() == '') { $this->arWidgets['btnUninstall']->hide(); $this->arWidgets['btnUninstall']->set_sensitive(false); } else { $this->arWidgets['btnUninstall']->show(); $this->arWidgets['btnUninstall']->set_sensitive(true); } }//protected function ableInstallButtons($package) protected function updateInstallButtons() { $selection = $this->arWidgets['lstPackages']->get_selection(); list($model, $iter) = $selection->get_selected(); $package = $model->get_value($iter, 4); $this->ableInstallButtons($package); }//protected function updateInstallButtons() protected function getSelectedPackage() { return $this->selectedPackage; }//protected function getSelectedPackage() protected function setSelectedPackage($package) { $this->selectedPackage = $package; }//protected function setSelectedPackage($package) /** * Installs (or uninstalls) the selected package * * @param boolean $bInstall True if the package shall be installed, false if it shall be uninstalled */ function installPackage($bInstall = true) { $strChannel = $this->packages->getActiveChannel(); $package = $this->getSelectedPackage(); if ($package === null) { $dialog = new GtkMessageDialog( $this->arWidgets['dlgInstaller'], 0, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, 'You have to select a package before you can install it.' ); $dialog->run(); $dialog->destroy(); return; } //get changes done in gui into config PEAR_Frontend_Gtk2_Config::loadConfigurationFromGui($this); $this->installer->installPackage( $strChannel, $package->getName(), $package->getLatestVersion(), $bInstall, PEAR_Frontend_Gtk2_Config::$strDepOptions ); $package->refreshLocalInfo(); $this->updatePackageList(array($package)); $this->updateInstallButtons(); }//function installPackage($bInstall = true) /** * Shows the progress dialog if that hasn't already been done * * @param boolean $bInitWithZero If the dialog's labels should be initialized (if the dialog has been hidden) */ protected function showProgressDialog($bInitWithZero = false) { $dlgProgress = $this->arWidgets['dlgProgress']; if ($dlgProgress->window === null || !$dlgProgress->window->is_visible()) { //show it $dlgProgress->modify_bg(Gtk::STATE_NORMAL, GdkColor::parse('#FFFFFF')); $dlgProgress->set_transient_for($this->arWidgets['dlgInstaller']); $dlgProgress->set_position(Gtk::WIN_POS_CENTER_ON_PARENT); if ($bInitWithZero) { $this->arWidgets['lblProgress']->set_text(''); $this->arWidgets['progBar']->set_fraction(0); } $dlgProgress->show_now(); while (Gtk::events_pending()) { Gtk::main_iteration();} } }//protected function showProgressDialog($bInitWithZero = false) /** * Hides the progress dialog */ protected function hideProgressDialog() { $this->arWidgets['dlgProgress']->hide(); while (Gtk::events_pending()) { Gtk::main_iteration();} }//protected function hideProgressDialog() /** * The user may not close the progress window by hand */ public function deleteProgressWindow() { return true; }//public function deleteProgressWindow() /** * Check if the user wants to work offline * @return boolean True, if the offline setting is active (work offline), false if working online */ protected function getWorkOffline() { return $this->arWidgets['mnuOffline']->get_active(); }//protected function getWorkOffline() /** * Set the offline setting * @param boolean $bOffline If the user wants to work offline (true) or not (false) */ protected function setWorkOffline($bOffline) { return $this->arWidgets['mnuOffline']->set_active($bOffline); }//protected function setWorkOffline($bOffline) public function getWidget($strWidget) { return $this->arWidgets[$strWidget]; }//public function getWidget($strWidget) /** * Reload local package information and update the list. */ public function refreshLocalPackages() { $this->packages->refreshLocalPackages(); $this->showPackageList($this->strSelectedCategoryName); }//public function refreshLocalPackages() /** * Reload the online package list and package information, * and update the list here. */ public function refreshOnlinePackages() { $this->packages->refreshRemotePackages(null, array($this, 'packagesCallback')); $this->showPackageList($this->strSelectedCategoryName); }//public function refreshOnlinePackages() }//class PEAR_Frontend_Gtk2 ?> http://cvs.php.net/viewcvs.cgi/pear/PEAR_Frontend_Gtk2/package.xml?view=markup&rev=1.1 Index: pear/PEAR_Frontend_Gtk2/package.xml +++ pear/PEAR_Frontend_Gtk2/package.xml <?xml version="1.0"?> <package version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd"> <name>PEAR_Frontend_Gtk2</name> <channel>pear.php.net</channel> <summary>Graphical PEAR installer based on PHP-Gtk2</summary> <description> This program is a graphical frontend for PEAR, the PHP Extension and Application Repository. It uses PHP-Gtk2 as graphical toolkit and lets you easily browse available packages and install them on your computer. The program is designed to be by end-users, making it as easy as possible to install and uninstall programs. </description> <lead> <name>Christian Weiske</name> <user>cweiske</user> <email>cweiske@php.net</email> <active>yes</active> </lead> <date>2005-12-07</date> <version> <release>0.0.6</release> <api>0.0.3</api> </version> <stability> <release>alpha</release> <api>alpha</api> </stability> <license uri="http://www.gnu.org/licenses/lgpl.html">LGPL</license> <notes> * Install button changes to "upgrade" when installed package is selected * Default dependency option is "onlyreqdep" now * Version in About dialog is taken from package info </notes> <contents> <dir name="/" baseinstalldir="PEAR/Frontend"> <file name="Gtk2.php" role="php"/> <dir name="Gtk2"> <file name="About.php" role="php"> <tasks:replace from="@VERSION_PEAR_Frontend_Gtk2@" to="version" type="package-info" /> </file> <file name="Channels.php" role="php"/> <file name="Checks.php" role="php"/> <file name="Config.php" role="php"/> <file name="Installation.php" role="php"/> <file name="installer.glade" role="php"/> <file name="Package.php" role="php"/> <file name="Packages.php" role="php"/> <file name="run.phpw" role="php"/> <file name="runicon.png" role="php"/> <dir name="pixmaps"> <file name="default.png" role="php"/> <file name="gnope.org.png" role="php"/> <file name="pear.chiaraquartet.net.png" role="php"/> <file name="pear.php.net.png" role="php"/> <file name="pecl.php.net.png" role="php"/> <dir name="progress"> <file name="load-anim-1.png" role="php"/> <file name="load-anim-2.png" role="php"/> <file name="load-anim-3.png" role="php"/> <file name="load-anim-4.png" role="php"/> </dir> </dir> </dir> <dir name="tests" role="test"> <file name="ConfigTest.php" role="php"/> <file name="ExpanderTest.phpw" role="php"/> <file name="PackageTest.php" role="php"/> <file name="runtests.php" role="php"/> <file name="TimeDiff.php" role="php"/> </dir> </dir> </contents> <dependencies> <required> <php> <min>5.1</min> <max>6.0.0</max> </php> <pearinstaller> <min>1.4.5</min> </pearinstaller> <package> <name>Config</name> <channel>pear.php.net</channel> <min>1.10.4</min> </package> <extension> <name>php-gtk</name> <min>2.0.0dev</min> </extension> </required> </dependencies> <phprelease/> <changelog> <release> <version> <release>0.0.6</release> <api>0.0.3</api> </version> <stability> <release>alpha</release> <api>alpha</api> </stability> <date>2005-12-07</date> <license uri="http://www.gnu.org/licenses/lgpl.html">LGPL</license> <notes> * Install button changes to "upgrade" when installed package is selected * Default dependency option is "onlyreqdep" now * Version in About dialog is taken from package info </notes> </release> <release> <version> <release>0.0.5</release> <api>0.0.3</api> </version> <stability> <release>alpha</release> <api>alpha</api> </stability> <date>2005-12-05</date> <license uri="http://www.gnu.org/licenses/lgpl.html">LGPL</license> <notes> * Offline-on-error works better now </notes> </release> <release> <version> <release>0.0.4</release> <api>0.0.3</api> </version> <stability> <release>alpha</release> <api>alpha</api> </stability> <date>2005-12-04</date> <license uri="http://www.gnu.org/licenses/lgpl.html">LGPL</license> <notes> * Fix errors when there is no internet connection * PEAR cache directory is created if it doesn't exist - and no warning is thrown any more * better installation ok icon * Window icon - shows the php icon on windows currently * When no internet connection on startup, no categories are loaded and no local packages are shown </notes> </release> <release> <version> <release>0.0.3</release> <api>0.0.3</api> </version> <stability> <release>alpha</release> <api>alpha</api> </stability> <date>2005-12-03</date> <license uri="http://www.gnu.org/licenses/lgpl.html">LGPL</license> <notes> * Added runicon.png for the Gnope AppRunner * Fixed crash when uninstalling </notes> </release> <release> <version> <release>0.0.2</release> <api>0.0.2</api> </version> <stability> <release>alpha</release> <api>alpha</api> </stability> <date>2005-11-30</date> <license uri="http://www.gnu.org/licenses/lgpl.html">LGPL</license> <notes> - Fixed the php version check - Fixed crash when no php-gtk extension was installed - More comments - Fixed the code according to Alan's complains: - require_once without braces - semi-relative include paths: PEAR/Frontend/Gtk2/Package.php instead of Package.php </notes> </release> <release> <version> <release>0.0.1</release> <api>0.0.1</api> </version> <stability> <release>alpha</release> <api>alpha</api> </stability> <date>2005-11-29</date> <license uri="http://www.gnu.org/licenses/lgpl.html">LGPL</license> <notes> The first public version 0.0.1 has the following features: - Channel support - Installing and uninstalling packages - Switching options for installation: nodeps, alldeps, reqdeps - Package list caching - Working offline You might note that the package transfer is very slow when starting up the first time. This is because data for over 300 PEAR packages need to be transferred, and for each package two separate HTTP connections are made - currently there is no better way, but I'm in contact with Greg to get a better solution. </notes> </release> </changelog> </package> http://cvs.php.net/viewcvs.cgi/pear/PEAR_Frontend_Gtk2/Gtk2/About.php?view=markup&rev=1.1 Index: pear/PEAR_Frontend_Gtk2/Gtk2/About.php +++ pear/PEAR_Frontend_Gtk2/Gtk2/About.php <?php /** * About dialog for the PEAR Gtk2 frontend * * @author Christian Weiske <cweiske@php.net> */ class PEAR_Frontend_Gtk2_About extends GtkAboutDialog { /** * Creates the About dialog and fills it with * the right values (name, version, programmer, ...) */ public function __construct() { parent::__construct(); $this->set_title('About PEAR package installer'); $this->set_version('@VERSION_PEAR_Frontend_Gtk2@'); $this->set_name('PEAR package installer'); $this->set_license("This program is licensed under the LGPL v2.1"); $this->set_comments('Programmed by Christian Weiske <cweiske@php.net>' . "\r\n" . 'Sponsored by Ralf Schwoebel, www.tradebit.com'); $this->set_website('http://gnope.org'); // $this->set_authors(array('Christian Weiske <cweiske@cweiske.de>', 'Ralf Schwöbel')); }//public function __construct() /** * Static function that just creates an instance of the * About dialog, and run()s it afterwards. */ public static function showMe() { $dlg = new PEAR_Frontend_Gtk2_About(); $dlg->run(); }//public static function showMe() }//class PEAR_Frontend_Gtk2_About extends GtkAboutDialog ?> http://cvs.php.net/viewcvs.cgi/pear/PEAR_Frontend_Gtk2/Gtk2/Channels.php?view=markup&rev=1.1 Index: pear/PEAR_Frontend_Gtk2/Gtk2/Channels.php +++ pear/PEAR_Frontend_Gtk2/Gtk2/Channels.php <?php class PEAR_Frontend_Gtk2_Channels { static function loadChannels($cmbChannel, $config, $strDefaultChannel = 'pear.php.net') { $cmbChannel->get_model()->clear(); $arChannels = $config->getRegistry()->getChannels(); $arChannelNames = array(); foreach ($arChannels as $nId => $channel) { if ($channel->getName() != '__uri') { $arChannelNames[] = $channel->getName(); } } natcasesort($arChannelNames); $nPos = 0; $nDefaultChannelId = 0; foreach ($arChannelNames as $strName) { $cmbChannel->append_text($strName); if ($strName == $strDefaultChannel) { $nDefaultChannelId = $nPos; } $nPos++; } $cmbChannel->set_active($nDefaultChannelId); }//static function loadChannels($cmbChannel, $config) }//class PEAR_Frontend_Gtk2_Channels ?> http://cvs.php.net/viewcvs.cgi/pear/PEAR_Frontend_Gtk2/Gtk2/Checks.php?view=markup&rev=1.1 Index: pear/PEAR_Frontend_Gtk2/Gtk2/Checks.php +++ pear/PEAR_Frontend_Gtk2/Gtk2/Checks.php <?php /** * Some checks before the application is started. * That should ensure optimal user experience. * * @author Christian Weiske <cweiske@php.net> */ //Check PHP version if (version_compare('5.1.0dev', phpversion(), '>')) { echo "You need at least PHP 5.1.0 to run that program\r\n"; exit(1); } //Check PHP-Gtk version try { $ext = new ReflectionExtension("php-gtk"); } catch (ReflectionException $e) { echo "You need to install PHP-Gtk2\r\n"; exit(2); } if (version_compare('2.0.0', $ext->getVersion()) < 0) { echo "You need at least PHP-Gtk version 2.0\r\n"; exit(2); } //Do we have Glade? (was a problem on some php-gtk1 windows installations) if (!class_exists('gladexml')) { echo "The GladeXML class is not available, but required.\r\n"; $dialog = new GtkMessageDialog( null,//parent 0, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, 'The GladeXML class is not available, but required.' ); $dialog->run(); $dialog->destroy(); exit(3); } //PEAR cache directory require_once 'PEAR/Config.php'; $config = PEAR_Config::singleton(); $cachedir = $config->get('cache_dir'); if (!file_exists($cachedir)) { //Try to create the directory - if that fails, no problem: //the error message is thrown in the next if-block @mkdir($cachedir, 0777, true); } if (!is_writable($cachedir)) { $message = 'The PEAR cache directory "' . $cachedir . '" is NOT writable!' . "\r\n" . 'It is highly recommended that you make it writable before using the' . ' graphical installer.'; echo $message . "\r\n"; $dialog = new GtkMessageDialog( null,//parent 0, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_NONE, $message ); $dialog->add_button('Close and fix it', 0); $dialog->add_button('Continue the program', 1); $answer = $dialog->run(); $dialog->destroy(); if ($answer == 0) { exit(4); } } ?> http://cvs.php.net/viewcvs.cgi/pear/PEAR_Frontend_Gtk2/Gtk2/Config.php?view=markup&rev=1.1 Index: pear/PEAR_Frontend_Gtk2/Gtk2/Config.php +++ pear/PEAR_Frontend_Gtk2/Gtk2/Config.php <?php /** * This file contains the configuration options * for PEAR_Frontend_Gtk2, beginning with channel * colors/images, default channel and more. * It can load and write the config from an .ini file, * and from and to the GUI. * * @author Christian Weiske <cweiske@php.net> */ class PEAR_Frontend_Gtk2_Config { /** * Color settings for the different channels. * When a channel is selected from the dropdown, * this array is read and the background color * as well as the text color of the bar on the right * top is is set according to this settings here. * * If there is no entry for a specific channel, the * settings in "default" are used. * * @var array */ public static $arChannels = array( 'pear.php.net' => array( 'background-color' => '#339900', 'color' => '#FFF' ), 'pecl.php.net' => array( 'background-color' => '#2C1D83', 'color' => '#FFF' ), 'pear.chiaraquartet.net' => array( 'background-color' => '#333333', 'color' => '#FFF' ), 'tradebit.bogo' => array( 'background-color' => '#FFF', 'color' => '#000' ), 'gnope.org' => array( 'background-color' => '#FFF', 'color' => '#000' ), 'gnope.bogo' => array( 'background-color' => '#FFF', 'color' => '#000' ), 'default' => array( 'background-color' => '#FFF', 'color' => '#000' ) ); /** * The channel which is shown first. * @var string */ public static $strDefaultChannel = 'gnope.org'; /** * Work offline? If yes, then no internet connection is established. * @var boolean */ public static $bWorkOffline = false; /** * What dependency option should be used when installing * a package. * One of: onlyreqdeps, alldeps, nodeps or "". * @var string */ public static $strDepOptions = 'onlyreqdeps'; /** * The dependency options for installation, and the * corresponding widget names from the GUI. * @var array */ protected static $arDepWidgets = array( 'onlyreqdeps' => 'mnuOptDepsReq', 'alldeps' => 'mnuOptDepsAll', 'nodeps' => 'mnuOptDepsNo', '' => 'mnuOptDepNothing' ); /** * Load the config file into the variables here. * * @return boolean True if all is ok, false if not */ public static function loadConfig() { require_once 'Config.php'; $config = new Config(); $root = $config->parseConfig(self::getConfigFilePath(), 'inifile'); if (PEAR::isError($root)) { //we have default values if there is no config file yet return false; } $arRoot = $root->toArray(); if (!isset($arRoot['root']['installer']) || !is_array($arRoot['root']['installer'])) { return false; } $arConf = array_merge(self::getConfigArray(), $arRoot['root']['installer']); self::$bWorkOffline = (boolean)$arConf['offline']; self::$strDepOptions = (string) $arConf['depOption']; return true; }//public static function loadConfig() /** * Save the config in the config file */ public static function saveConfig() { require_once 'Config.php'; $conf = new Config_Container('section', 'installer'); $arConf = self::getConfigArray(); foreach ($arConf as $key => $value) { $conf->createDirective($key, $value); } $config = new Config(); $config->setRoot($conf); $config->writeConfig(self::getConfigFilePath(), 'inifile'); }//public static function saveConfig() /** * The config array with all current values. * Used for loading and storing * * @return array Arra with all the config options: option name => option value */ public static function getConfigArray() { return array( 'offline' => self::$bWorkOffline, 'depOption' => self::$strDepOptions ); }//public static function getConfigArray() /** * The config file path. (Where the config file is/shall be stored) * * @return string The config file path */ protected static function getConfigFilePath() { return PEAR_Config::singleton()->get('data_dir') . DIRECTORY_SEPARATOR . get_class() . '.ini'; }//protected static function getConfigFilePath() /** * Loads the current configuration into the GUI. * Sets all the widgets which reflect the config settings * in a way (e.g. the radio menu group for dep options) * * @param PEAR_Frontend_Gtk2 $fe The current frontend to where the config shall be transferred */ public static function loadCurrentConfigIntoGui(PEAR_Frontend_Gtk2 $fe) { $fe->getWidget('mnuOffline') ->set_active(self::$bWorkOffline); foreach (self::$arDepWidgets as $strValue => $strWidget) { $fe->getWidget($strWidget)->set_active(self::$strDepOptions == $strValue); } }//public static function loadConfigIntoGui(PEAR_Frontend_Gtk2 $fe) /** * Loads the configuration from the GUI to this config. * This needs to be done before saving the config file. * It checks the widgets responsible for the config options and reads their * settings, saving them intho this config class. * * @param PEAR_Frontend_Gtk2 $fe The current frontend to where the config shall be transferred */ public static function loadConfigurationFromGui(PEAR_Frontend_Gtk2 $fe) { self::$bWorkOffline = $fe->getWidget('mnuOffline')->get_active(); foreach (self::$arDepWidgets as $strValue => $strWidget) { if ($fe->getWidget($strWidget)->get_active()) { self::$strDepOptions = $strValue; } } }//public static function loadConfigurationFromGui(PEAR_Frontend_Gtk2 $fe) }//class PEAR_Frontend_Gtk2_Config ?> http://cvs.php.net/viewcvs.cgi/pear/PEAR_Frontend_Gtk2/Gtk2/Installation.php?view=markup&rev=1.1 Index: pear/PEAR_Frontend_Gtk2/Gtk2/Installation.php +++ pear/PEAR_Frontend_Gtk2/Gtk2/Installation.php <?php require_once 'PEAR/Command.php'; require_once 'PEAR/Frontend.php'; /** * Installation dialog and user interaction interface * for the PEAR Gtk2 installer * * @author Christian Weiske <cweiske@php.net> */ class PEAR_Frontend_Gtk2_Installation extends PEAR_Frontend { protected $dlgParent = null; protected $glade = null; protected $dlgInstalling = null; protected $txtLog = null; protected $strPackage = null; protected $strChannel = null; /** * The command which shall be executed (upgrade or uninstall) * @var string */ protected $strCommand = null; /** * If the log detects an unrecoverable error (e.g. failed dependency) * an error symbol is shown, no matter if the callback for "uninstall ok" * is called. * * @var boolean */ protected $bSeriousError = false; /** * Array with widgets from the glade file. They * are loaded in the buildDialog() methods * @var array */ protected $arWidgets = array(); /** * The widgets which shall be loaded from the glade * file into the $arWidgets array * @var array */ protected static $arRequestedWidgets = array( 'dlgInstalling', 'imgInstalling', 'progBarInstaller', 'btnCloseInstalling', 'lblInstalling', 'txtInstalling', 'expLog' ); public function __construct(GtkWidget $parent, GladeXML $glade) { $this->dlgParent = $parent; $this->glade = $glade; $this->buildDialog(); }//public function __construct(GtkWidget $parent) /** * load the glade file, load the widgets, connect the signals */ protected function buildDialog() { foreach (self::$arRequestedWidgets as $strWidgetName) { $this->arWidgets[$strWidgetName] = $this->glade->get_widget($strWidgetName); } $this->txtLog = $this->arWidgets['txtInstalling']; $this->dlgInstalling = $this->arWidgets['dlgInstalling']; $this->dlgInstalling->set_transient_for($this->dlgParent); $this->arWidgets['btnCloseInstalling']->connect_simple('clicked', array($this, 'hideMe')); $this->dlgInstalling->connect('delete-event', array($this, 'deleteWindow')); }//protected function buildDialog() /** * Installs (or uninstalls) the given package. * * @param string $strPackage The package to install * @param string $strChannel The channel on which the package can be found * @param boolean $bInstall If the package shall be installed (true) or uninstalled (false) */ public function installPackage($strChannel, $strPackage, $strVersion, $bInstall = true, $strDepOptions = null) { //Bad code, but PEAR doesn't offer the possibility to do that a better way $GLOBALS['_PEAR_FRONTEND_SINGLETON'] = $this; $this->bSeriousError = false;//there is no serious error *yet* $this->strPackage = $strPackage; $this->strChannel = $strChannel; $strText = $bInstall ? 'I' : 'Uni'; $strText .= 'nstalling ' . $strChannel . '/' . $strPackage; $this->dlgInstalling->set_title($strText); $this->setCurrentAction($strText); $this->setCurrentIcon(Gtk::STOCK_EXECUTE); $this->setPercentage(0); $buffer = $this->txtLog->get_buffer(); $buffer->delete($buffer->get_start_iter(), $buffer->get_end_iter()); // $this->arWidgets['expLog']->set_expanded(false); $this->appendToLog($strText . "\r\n"); $this->showMe(); $cmd = PEAR_Command::factory('install', PEAR_Config::singleton()); if ($bInstall) { $strPackagePath = 'channel://' . $strChannel . '/' . $strPackage . '-' . $strVersion; $strCommand = 'upgrade'; } else { $strPackagePath = 'channel://' . $strChannel . '/' . $strPackage; $strCommand = 'uninstall'; } $this->strCommand = $strCommand; while (Gtk::events_pending()) { Gtk::main_iteration();} if ($strCommand === 'upgrade') { $arOptions = array($strDepOptions => true); } else { $arOptions = array(); } $cmd->run($strCommand, $arOptions, array($strPackagePath)); //own main loop so that the next functions aren't executed until the window is closed Gtk::main(); }//public function installPackage($strChannel, $strPackage, $strVersion, $bInstall = true, $strDepOptions = null) protected function showMe() { $this->dlgInstalling->set_modal(true); $this->dlgInstalling->set_position(Gtk::WIN_POS_CENTER_ON_PARENT); $this->dlgInstalling->show(); while (Gtk::events_pending()) { Gtk::main_iteration();} }//protected function showMe() public function hideMe() { $this->dlgInstalling->set_modal(false); $this->dlgInstalling->hide(); Gtk::main_quit(); }//public function hideMe() /** * The user may not close the window by hand */ public function deleteWindow() { return true; }//public function deleteWindow() protected function appendToLog($strText) { $buffer = $this->txtLog->get_buffer(); $end = $buffer->get_end_iter(); $buffer->insert($end, $strText); $this->txtLog->scroll_to_iter($buffer->get_end_iter(), 0.49); }//protected function appendToLog($strText) protected function setCurrentAction($strText) { $this->arWidgets['lblInstalling']->set_text($strText); }//protected function setCurrentAction($strText) /** * Set the icon for the dialog * * @param int $nId The stock item id */ protected function setCurrentIcon($nId) { $this->arWidgets['imgInstalling']->set_from_stock($nId, Gtk::ICON_SIZE_DIALOG); }//protected function setCurrentIcon($nId) /** * Set the progress bar progress in percent (0-100) */ protected function setPercentage($nPercent) { if ($nPercent <= 0) { $this->arWidgets['progBarInstaller']->set_fraction(0); } else { $this->arWidgets['progBarInstaller']->set_fraction(100/$nPercent); } }//protected function setPercentage($nPercent) protected function setFinished() { if ($this->bSeriousError) { $this->setCurrentIcon(Gtk::STOCK_DIALOG_ERROR); } else { $this->setCurrentIcon(Gtk::STOCK_APPLY); } $this->setPercentage(100); }//protected function setFinished() public function __call($function, $arguments) { $this->appendToLog('__call: ' . $function . ' with ' . count($arguments) . ' arguments.' . "\r\n"); foreach ($arguments as $strName => $strValue) { $this->appendToLog(' arg:' . $strName . ':' . gettype($strValue) . '::' . $strValue . "\r\n"); } while (Gtk::events_pending()) { Gtk::main_iteration();} }//public function __call($function, $arguments) /** * All functions which might be expected in a PEAR_Frontend go here */ public function outputData($data, $command = null) { switch ($command) { case 'install': case 'upgrade': case 'upgrade-all': //FIXME: check for release warnings $data['release_warnings'] $this->setCurrentAction('Installation of ' . $this->strPackage . ' done'); $this->appendToLog($data['data'] . "\r\n"); $this->setFinished(); break; case 'uninstall': if ($this->bSeriousError) { $this->setCurrentAction('Error uninstalling ' . $this->strPackage); $this->arWidgets['expLog']->set_expanded(true); } else { $this->setCurrentAction('Uninstallation of ' . $this->strPackage . ' ok'); $this->appendToLog('Uninstall ok' . "\r\n"); } $this->setFinished(); break; default: if ($command !== null) { var_dump($command); } if (isset($data['headline'])) { $this->setCurrentAction($data['headline']); $this->appendToLog('!!!' . $data['headline'] . '!!!' . "\r\n"); if (stripos($data['headline'], 'error') !== false) { $this->setCurrentIcon(Gtk::STOCK_DIALOG_ERROR); $this->arWidgets['expLog']->set_expanded(true); } } if (is_array($data['data'])) { //could somebody tell me if there is a fixed format? foreach ($data['data'] as $nId => $arSubData) { $this->appendToLog(implode(' / ', $arSubData) . "\r\n"); } } else if (is_string($data['data'])) { $this->appendToLog($data['data'] . "\r\n"); } else { //What's this? $this->appendToLog('PEAR_Frontend_Gtk2_Installation::outputData: Unhandled type "' . gettype($data['data']) . "\"\r\n"); } while (Gtk::events_pending()) { Gtk::main_iteration();} break; } }//public function outputData($data, $command = null) function log($msg, $append_crlf = true) { //require_once 'Gtk2/VarDump.php'; new Gtk2_VarDump(array($level, $msg, $append_crlf), 'msg'); if (strpos($msg, 'is required by installed package') !== false) { $this->bSeriousError = true; } $this->appendToLog($msg . "\r\n"); while (Gtk::events_pending()) { Gtk::main_iteration();} }//function log($msg, $append_crlf = true) }//class PEAR_Frontend_Gtk2_Installation extends PEAR_Frontend ?> http://cvs.php.net/viewcvs.cgi/pear/PEAR_Frontend_Gtk2/Gtk2/Package.php?view=markup&rev=1.1 Index: pear/PEAR_Frontend_Gtk2/Gtk2/Package.php +++ pear/PEAR_Frontend_Gtk2/Gtk2/Package.php <?php /** * A single PEAR package with some of its data * like name, category, installed version, latest version, * summary and description * * @author Christian Weiske <cweiske@php.net> */ class PEAR_Frontend_Gtk2_Package { protected $bFullyLoaded = false; protected $strName = null; protected $strChannel = null; protected $strCategory = null; protected $strSummary = null; protected $strDescription = null; protected $strVersionLatest = null; protected $strVersionInstalled = null; /** * Constructs a package object * * @param string $strName the package name */ public function __construct($strName, $strChannel) { $this->setName($strName); $this->setChannel($strChannel); $this->setFullyLoaded(false); }//public function __construct($strName, $strChannel) /** * Loads the package information array from * PEAR_Registry::packageInfo() into the local variables */ public function incorporateLocalInfo($arPackageInfo) { $this->setSummary($arPackageInfo['summary']); $this->setDescription($arPackageInfo['description']); if (is_array($arPackageInfo['version'])) { $this->setInstalledVersion($arPackageInfo['version']['release']); } else { $this->setInstalledVersion($arPackageInfo['version']); } //require_once 'Gtk2/VarDump.php'; new Gtk2_VarDump($arPackageInfo, '$arPackageInfo'); }//public function incorporateLocalInfo($arPackageInfo) /** * Reloads the local package info. * Useful if the package has been installed or uninstalled */ public function refreshLocalInfo() { $config = PEAR_Config::singleton(); $arData = $config->getRegistry()->packageInfo($this->getName(), null, $this->getChannel()); if ($arData === null) { //no local package data -> uninstalled or not available $this->setInstalledVersion(null); } else { $this->incorporateLocalInfo($arData); } }//public function refreshLocalInfo() /** * Tries to guess the category name from the package name * e.g. Dev_Inspector should have "Dev" as category * If no category can be guessed, "" (empty string) will * be returned * * @param string $strName The package name * @return string The guessed category name */ public static function guessCategory($strName) { $nPos = strpos($strName, '_'); if ($nPos !== false) { $strCategory = substr($strName, 0, $nPos); } else { //no underscore $strCategory = $strName; } return $strCategory; }//public static function guessCategory($strName) public function getName() { return $this->strName; } public function getChannel() { return $this->strChannel; } public function getSummary() { return $this->strSummary; } public function getDescription() { return $this->strDescription; } public function getCategory() { return $this->strCategory; }//public function getCategory() function getInstalledVersion() { return $this->strVersionInstalled; }//function getInstalledVersion() function getLatestVersion() { return $this->strVersionLatest; }//function getLatestVersion() function setName($strName) { $this->strName = $strName; }//function setName($strName) function setCategory($strCategory) { $this->strCategory = $strCategory; }//function setCategory($strCategory) function setChannel($strChannel) { $this->strChannel = $strChannel; }//function setChannel($strChannel) function setSummary($strSummary) { $this->strSummary = $strSummary; }//function setSummary($strSummary) function setDescription($strDescription) { $this->strDescription = $strDescription; }//function setDescription($strDescription) function setFullyLoaded($bFullyLoaded) { $this->bFullyLoaded = $bFullyLoaded; }//function setFullyLoaded($bFullyLoaded) function setInstalledVersion($strVersionInstalled) { if ($strVersionInstalled == '') { $strVersionInstalled = null; } $this->strVersionInstalled = $strVersionInstalled; }//function setInstalledVersion($strVersionInstalled) function setLatestVersion($strVersionLatest) { if (!is_string($strVersionLatest)) { $strVersionLatest = '?'; } if ($strVersionLatest == '') { $strVersionLatest = null; } $this->strVersionLatest = $strVersionLatest; }//function setInstalledVersion($strVersionLatest) }//class PEAR_Frontend_Gtk2_Package ?> http://cvs.php.net/viewcvs.cgi/pear/PEAR_Frontend_Gtk2/Gtk2/Packages.php?view=markup&rev=1.1 Index: pear/PEAR_Frontend_Gtk2/Gtk2/Packages.php +++ pear/PEAR_Frontend_Gtk2/Gtk2/Packages.php <?php require_once 'PEAR/Frontend/Gtk2/Package.php'; require_once 'PEAR/Config.php'; /** * This class deals with packages: local package loading, * remote package loading and so. * * The callback is called after everything has been finished * with parameters (true, true) to signal that it's done. * * @author Christian Weiske <cweiske@php.net> */ class PEAR_Frontend_Gtk2_Packages { /** * The currently active channel name * @var string */ protected $strActiveChannel = null; /** * Array of channel => package arrays * @var array */ protected $arPackages = null; /** * Array of channel => category strings * @var array */ protected $arCategories = null; public static $EXCEPTION_NO_REST = 451; public function __construct($strActiveChannel = null) { $this->setActiveChannel($strActiveChannel); }//public function __construct($strActiveChannel = null) public function setActiveChannel($strActiveChannel) { $this->strActiveChannel = $strActiveChannel; }//public function setActiveChannel($strActiveChannel) public function getActiveChannel() { return $this->strActiveChannel; }//public function getActiveChannel() /** * Returns a list with all packages, or all packages in the given category. * Package list is cached, so that it's faster after the first call. * * @param string $strCategory If given, the list is filtered by category name * @param callback $callback The function to call before a package information is downloaded * @param booleab $bWorkOffline If the user wants to work offline (don't connect to the internet) * * @return array Array of PEAR_Frontend_Gtk2_Package's */ public function getPackages($strCategory = null, $callback = null, $bWorkOffline = false) { if (!$this->packagesLoaded()) { $this->arPackages[$this->strActiveChannel] = PEAR_Frontend_Gtk2_Packages::getAllPackages($this->strActiveChannel, $callback, $bWorkOffline); } if ($strCategory === null) { return $this->arPackages[$this->strActiveChannel]; } $arSelectedPackages = array(); foreach ($this->arPackages[$this->strActiveChannel] as $strName => $package) { if ($package->getCategory() == $strCategory) { $arSelectedPackages[$strName] = $package; } } return $arSelectedPackages; }//public function getPackages($strCategory = null, $callback = null, $bWorkOffline = false) /** * Gets an array of packages for the active channel * (local and remote packages) * * @param string $strChannel Channel to get packages for * @param callback $callback The callback to call for each single remote package * @param boolean $bWorkOffline If the users wants to work offline * * @return array Array of Packages */ public static function getAllPackages($strChannel, $callback = null, $bWorkOffline = false) { return PEAR_Frontend_Gtk2_Packages::getRemotePackages( $strChannel, true, $callback, PEAR_Frontend_Gtk2_Packages::getLocalPackages($strChannel), $bWorkOffline ); }//public static function getAllPackages($strChannel, $callback = null, $bWorkOffline = false) /** * Loads the locally installed packages of the given * channel * * @param string $strChannel The channel name * @param array $arLocalPackages Array with already existing local packages. If set, package info will be incorporated. * @return array Array of locally installed packages * @static */ public static function getLocalPackages($strChannel, $arLocalPackages = array()) { $config = PEAR_Config::singleton(); $arRawPackages = $config->getRegistry()->packageInfo(null, null, $strChannel); $arExisting = is_null($arLocalPackages) ? array() : array_keys($arLocalPackages); $arFound = array(); foreach ($arRawPackages as $strPackageId => $dontuseit) { if (isset($arRawPackages[$strPackageId]['name'])) { $strPackageName = $arRawPackages[$strPackageId]['name']; } else { $strPackageName = $arRawPackages[$strPackageId]['package']; } if (!isset($arLocalPackages[$strPackageName])) { $arLocalPackages[$strPackageName] = new PEAR_Frontend_Gtk2_Package($strPackageName, $strChannel); $arLocalPackages[$strPackageName]->setCategory(PEAR_Frontend_Gtk2_Package::guessCategory($strPackageName)); } $arLocalPackages[$strPackageName]->incorporateLocalInfo($arRawPackages[$strPackageId]); $arFound[$strPackageName] = true; } foreach ($arExisting as $strId => $strPackageName) { if (isset($arFound[$strPackageName])) { unset($arExisting[$strId]); } } //The ones still in here aren't installed locally any more foreach ($arExisting as $strPackageName) { $arLocalPackages[$strPackageName]->setInstalledVersion(null); } return $arLocalPackages; }//public static function getLocalPackages($strChannel, $arLocalPackages = array()) /** * Loads the remotely available packages for the given channel * * @param string $strChannel The channel name * @param boolean $bLoadPackageData If all the package data shall be loaded, not only the names * @param callback $callback The callback to call after a package info has been loaded * @param array $arExistingPackages Array with local packages already loaded * @param boolean $bWorkOffline If we should use the local cache if possible * * @return array Array of remotely available packages (PEAR_Frontend_Gtk2_Package) * @throws Exception If the channel has no REST support or if the connection failed * @static */ public static function getRemotePackages($strChannel, $bLoadPackageData = true, $callback = null, $arExistingPackages = array(), $bWorkOffline = false) { $config = PEAR_Config::singleton(); $channel = $config->getRegistry()->getChannel($strChannel); $strBaseUrl = $channel->getBaseURL('REST1.0'); $strServer = $channel->getServer(); $rest = $config->getREST('1.0'); if ($channel->supportsREST($strServer) && $strBaseUrl) { $arXmlPackages = PEAR_Frontend_Gtk2_Packages::listPackages($strChannel, $bWorkOffline); if (PEAR::isError($arXmlPackages)) { throw new Exception( 'Error listing packages on channel ' . $strChannel . ":\r\n" . $arXmlPackages->getMessage(), $arXmlPackages->getCode() ); } } else { throw new Exception($strChannel . ' has no REST support', PEAR_Frontend_Gtk2_Packages::$EXCEPTION_NO_REST); } if (count($arXmlPackages) == 0 || (count($arXmlPackages) == 1 && $arXmlPackages[0] === null) ) { //No packages... return $arExistingPackages; } foreach ($arXmlPackages as $id => $strName) { if (!isset($arExistingPackages[$strName])) { $arExistingPackages[$strName] = new PEAR_Frontend_Gtk2_Package($strName, $strChannel); } } if ($bLoadPackageData === false) { return $arExistingPackages; } else { return PEAR_Frontend_Gtk2_Packages::loadRemotePackageData($arExistingPackages, $strChannel, $callback, $bWorkOffline); } }//public static function getRemotePackages($strChannel, $bLoadPackageData = true, $callback = null, $arExistingPackages = array(), $bWorkOffline = false) /** * Copy of the PEAR_REST#listPackages function with the change * that this one is able to get the list from the local cache. * * @param string $strChannel The channel which packages shall be listed * @param boolean $bWorkOffline If false, the local cache is used - if true, the online list is loaded * * @return mixed PEAR_Error or array (package list) */ public static function listPackages($strChannel, $bWorkOffline = false) { $config = PEAR_Config::singleton(); $channel = $config->getRegistry()->getChannel($strChannel); $strBaseUrl = $channel->getBaseURL('REST1.0'); $strServer = $channel->getServer(); $rest = $config->getREST('1.0'); if ($bWorkOffline) { //We can't use the retrieveCacheFirst function as it would //try to connect if the local cache is empty $url = $strBaseUrl . 'p/packages.xml'; $cachefile = $config->get('cache_dir') . DIRECTORY_SEPARATOR . md5($url) . 'rest.cachefile'; if (@file_exists($cachefile)) { //local package list cache file $arCache = unserialize(implode('', file($cachefile))); if (PEAR::isError($arCache)) { return $arCache; } if (!is_array($arCache) || !isset($arCache['p'])) { return array(); } if (!is_array($arCache['p'])) { $arCache['p'] = array($arCache['p']); } return $arCache['p']; } else { //no local cache -> return empty package list return array(); } } else { //online => list online packages return $rest->listPackages($strBaseUrl); } }//public static function listPackages($strChannel, $bWorkOffline = false) /** * Loads all available information for the given packages * * @param array $arRemotePackages Array with PEAR_Frontend_Gtk2_Package-s * @param string $strChannel The channel name to retrieve packages from * @param callback $callback The callback to call after a package info has been loaded * @param boolean $bWorkOffline If the local cache *only* shall be used, or (if no local cache is there) * an connection to the internet server shall be made * @param boolean $bUseCache If the cache shall be used. If not, the only chance to get package data is * reading them from the online server (if $bWorkOffline is false) * * @return array Array of packages (locally installed and remotely available) (PEAR_Frontend_Gtk2_Package) * @static */ public static function loadRemotePackageData($arRemotePackages, $strChannel, $callback = null, $bWorkOffline = false, $bUseCache = true) { $config = PEAR_Config::singleton(); $rest10 = $config->getREST('1.0'); $rest = $rest10->_rest;//FIXME: could change in future pear versions $channel = $config->getRegistry()->getChannel($strChannel); $strBaseUrl = $channel->getBaseURL('REST1.0'); $nNumberPackages = count($arRemotePackages); $nCurrentPackageNumber = 0; foreach ($arRemotePackages as $strId => $dontuseit) { if ($callback !== null) { call_user_func_array($callback, array($nNumberPackages, ++$nCurrentPackageNumber)); } $package = $arRemotePackages[$strId]; $inf = PEAR_Frontend_Gtk2_Packages::retrieveCacheFirst( PEAR_Frontend_Gtk2_Packages::getInfoUrl($strBaseUrl, $package->getName()), $config, $rest, $bWorkOffline, $bUseCache ); if (PEAR::isError($inf)) { if (strpos(strtolower($inf->message), '404 not found') !== false) { //FIXME: That is a hack because the error hasn't an error code yet. //We continue because it's an 404 error, maybe the package isn't there yet. //Happens if you installed new packages which haven't been uploaded to the server yet. $package->setCategory($package->guessCategory($package->getName())); continue; } throw new Exception($inf->getMessage()); } if ($inf['ca']['_content'] !== null) { $package->setCategory( $inf['ca']['_content']); } $package->setSummary( $inf['s']); $package->setDescription($inf['d']); $package->setLatestVersion( //FIXME: use preferred_state config option PEAR_Frontend_Gtk2_Packages::retrieveCacheFirst( PEAR_Frontend_Gtk2_Packages::getLatestVersionUrl($strBaseUrl, $package->getName()), $config, $rest, $bWorkOffline, $bUseCache ) ); } if ($callback !== null) { call_user_func_array($callback, array(true, true)); } return $arRemotePackages; }//public static function loadRemotePackageData($arRemotePackages, $strChannel, $callback = null, $bWorkOffline = false, $bUseCache = true) /** * Copy of the PEAR_REST#retrieveCacheFirst() function with the addition * that one can specify if the cache only shall be loaded, or if the cache * is not available, an connection shall be made. * * If the user works offline, and no cache is there, NULL is returned. * * @param string $url The URL to get the data from * @param PEAR_Config $config The PEAR configuration * @param PEAR_REST $rest The REST object which can be used to retrieve the data * @param boolean $bWorkOffline If the local cache *only* shall be used, or (if no local cache is there) * an connection to the internet server shall be made * @param boolean $bUseCache If the cache shall be used. If not, the only chance to get package data is * reading them from the online server (if $bWorkOffline is false) */ public static function retrieveCacheFirst($url, $config, $rest, $bWorkOffline = false, $bUseCache = true) { if ($bUseCache) { $cachefile = $config->get('cache_dir') . DIRECTORY_SEPARATOR . md5($url) . 'rest.cachefile'; if (@file_exists($cachefile)) { return unserialize(implode('', file($cachefile))); } } if ($bWorkOffline) { return null; } else { return $rest->retrieveData($url); } }//public static function retrieveCacheFirst($url, $config, $rest, $bWorkOffline = false, $bUseCache = true) /** * Path to info.xml for the specific package */ public static function getInfoUrl($strBaseUrl, $strPackageName) { return $strBaseUrl . 'p/' . strtolower($strPackageName) . '/info.xml'; }//public static function getInfoUrl($strBaseUrl, $strPackageName) /** * Path to latest.txt for the specific package */ public static function getLatestVersionUrl($strBaseUrl, $strPackageName) { return $strBaseUrl . 'r/' . strtolower($strPackageName) . '/latest.txt'; }//public static function getLatestVersionUrl($strBaseUrl, $strPackageName) /** * Creates an array of categories (strings) of the current * channel server * * @param callback $callback The callback to call when package information is loaded * @param boolean $bWorkOffline If the user wants to work offline (don't try to connect to the internet) * * @return array Array of category strings */ public function getCategories($callback = null, $bWorkOffline = false) { if (!isset($this->arCategories[$this->strActiveChannel])) { $arPackages = $this->getPackages(null, $callback, $bWorkOffline); $this->arCategories[$this->strActiveChannel] = array(); if (count($arPackages) > 0) { foreach ($arPackages as $package) { $strCategory = $package->getCategory(); $this->arCategories[$this->strActiveChannel][$strCategory] = $strCategory; } natcasesort($this->arCategories[$this->strActiveChannel]); } } return $this->arCategories[$this->strActiveChannel]; }//public function getCategories($callback = null) /** * Checks if the packages for the given channel have already been loaded * * @param string $strChannel The channel to check (active channel if null) * @return boolean true if the packages already have been loaded, false if not */ public function packagesLoaded($strChannel = null) { if ($strChannel === null) { $strChannel = $this->strActiveChannel; } return (isset($this->arPackages[$strChannel]) && $this->arPackages[$strChannel] !== null); }//public function packagesLoaded($strChannel = null) /** * Refreshs the package list of the given channel by re-reading * the local package info * * @param string $strChannel The channel to update. If NULL, the active one is used * @return array Package list for the given channel */ public function refreshLocalPackages($strChannel = null) { if ($strChannel === null) { $strChannel = $this->strActiveChannel; } $this->arPackages[$strChannel] = self::getLocalPackages($strChannel, $this->arPackages[$strChannel]); return $this->arPackages[$strChannel]; }//public function refreshLocalPackages($strChannel = null) /** * Refreshs the package list of the given channel by re-reading the remote * package information. * * @param string $strChannel The channel to update. If NULL, the active one is used * @return array Package list for the given channel */ public function refreshRemotePackages($strChannel = null, $callback = null) { if ($strChannel === null) { $strChannel = $this->strActiveChannel; } $this->arPackages[$strChannel] = self::loadRemotePackageData($this->arPackages[$strChannel], $strChannel, $callback, false, false); return $this->arPackages[$strChannel]; }//public function refreshRemotePackages($strChannel = null, $callback = null) }//class PEAR_Frontend_Gtk2_Packages ?> http://cvs.php.net/viewcvs.cgi/pear/PEAR_Frontend_Gtk2/Gtk2/installer.glade?view=markup&rev=1.1 Index: pear/PEAR_Frontend_Gtk2/Gtk2/installer.glade +++ pear/PEAR_Frontend_Gtk2/Gtk2/installer.glade <?xml version="1.0" standalone="no"?> <!--*- mode: xml -*--> <!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd"> <glade-interface> <widget class="GtkWindow" id="dlgInstaller"> <property name="visible">True</property> <property name="title" translatable="yes">PEAR Package Installer</property> <property name="type">GTK_WINDOW_TOPLEVEL</property> <property name="window_position">GTK_WIN_POS_NONE</property> <property name="modal">False</property> <property name="default_width">800</property> <property name="default_height">560</property> <property name="resizable">True</property> <property name="destroy_with_parent">False</property> <property name="decorated">True</property> <property name="skip_taskbar_hint">False</property> <property name="skip_pager_hint">False</property> <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property> <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> <child> <widget class="GtkVBox" id="vboxMain"> <property name="visible">True</property> <property name="homogeneous">False</property> <property name="spacing">0</property> <child> <widget class="GtkHandleBox" id="hdlMenu"> <property name="visible">True</property> <property name="shadow_type">GTK_SHADOW_OUT</property> <property name="handle_position">GTK_POS_LEFT</property> <property name="snap_edge">GTK_POS_TOP</property> <child> <widget class="GtkMenuBar" id="mnubarMain"> <property name="visible">True</property> <child> <widget class="GtkMenuItem" id="menuitem7"> <property name="visible">True</property> <property name="label" translatable="yes">_File</property> <property name="use_underline">True</property> <child> <widget class="GtkMenu" id="menuitem7_menu"> <child> <widget class="GtkImageMenuItem" id="mnuUpdateLocal"> <property name="visible">True</property> <property name="label" translatable="yes">Refresh local packages</property> <property name="use_underline">True</property> <signal name="activate" handler="on_mnuRefreshPackageList_activate" last_modification_time="Thu, 24 Nov 2005 11:39:03 GMT"/> <accelerator key="F5" modifiers="0" signal="activate"/> <child internal-child="image"> <widget class="GtkImage" id="image5"> <property name="visible">True</property> <property name="stock">gtk-refresh</property> <property name="icon_size">1</property> <property name="xalign">0.5</property> <property name="yalign">0.5</property> <property name="xpad">0</property> <property name="ypad">0</property> </widget> </child> </widget> </child> <child> <widget class="GtkImageMenuItem" id="mnuUpdateOnline"> <property name="visible">True</property> <property name="label" translatable="yes">Refresh online packages</property> <property name="use_underline">True</property> <signal name="activate" handler="on_mnuUpdateOnline_activate" last_modification_time="Mon, 28 Nov 2005 15:29:45 GMT"/> <accelerator key="F6" modifiers="0" signal="activate"/> <child internal-child="image"> <widget class="GtkImage" id="image6"> <property name="visible">True</property> <property name="stock">gtk-refresh</property> <property name="icon_size">1</property> <property name="xalign">0.5</property> <property name="yalign">0.5</property> <property name="xpad">0</property> <property name="ypad">0</property> </widget> </child> </widget> </child> <child> <widget class="GtkSeparatorMenuItem" id="separator2"> <property name="visible">True</property> </widget> </child> <child> <widget class="GtkCheckMenuItem" id="mnuOffline"> <property name="visible">True</property> <property name="label" translatable="yes">Work _offline</property> <property name="use_underline">True</property> <property name="active">False</property> <signal name="activate" handler="on_mnuOffline_activate" last_modification_time="Wed, 23 Nov 2005 23:17:19 GMT"/> </widget> </child> <child> <widget class="GtkSeparatorMenuItem" id="separator1"> <property name="visible">True</property> </widget> </child> <child> <widget class="GtkImageMenuItem" id="mnuQuit"> <property name="visible">True</property> <property name="label">gtk-quit</property> <property name="use_stock">True</property> <signal name="activate" handler="PEAR_Frontend_Gtk2::quitDialog" last_modification_time="Mon, 24 Oct 2005 16:24:23 GMT"/> </widget> </child> </widget> </child> </widget> </child> <child> <widget class="GtkMenuItem" id="installation_options1"> <property name="visible">True</property> <property name="label" translatable="yes">Installation o_ptions</property> <property name="use_underline">True</property> <child> <widget class="GtkMenu" id="installation_options1_menu"> <child> <widget class="GtkRadioMenuItem" id="mnuOptDepNothing"> <property name="visible">True</property> <property name="label" translatable="yes">No dependency options</property> <property name="use_underline">True</property> <property name="active">False</property> <signal name="activate" handler="on_mnuOptDepNothing_activate" last_modification_time="Thu, 24 Nov 2005 11:08:22 GMT"/> </widget> </child> <child> <widget class="GtkRadioMenuItem" id="mnuOptDepsNo"> <property name="visible">True</property> <property name="label" translatable="yes">Ignore dependencies</property> <property name="use_underline">True</property> <property name="active">False</property> <property name="group">mnuOptDepNothing</property> <signal name="activate" handler="on_mnuOptDepsNo_activate" last_modification_time="Wed, 23 Nov 2005 21:46:23 GMT"/> </widget> </child> <child> <widget class="GtkRadioMenuItem" id="mnuOptDepsReq"> <property name="visible">True</property> <property name="label" translatable="yes">Required dependencies</property> <property name="use_underline">True</property> <property name="active">False</property> <property name="group">mnuOptDepNothing</property> <signal name="activate" handler="on_mnuOptDepsReq_activate" last_modification_time="Wed, 23 Nov 2005 21:46:23 GMT"/> </widget> </child> <child> <widget class="GtkRadioMenuItem" id="mnuOptDepsAll"> <property name="visible">True</property> <property name="label" translatable="yes">All dependencies</property> <property name="use_underline">True</property> <property name="active">True</property> <property name="group">mnuOptDepNothing</property> <signal name="activate" handler="on_mnuOptDepsAll_activate" last_modification_time="Wed, 23 Nov 2005 21:46:23 GMT"/> </widget> </child> </widget> </child> </widget> </child> <child> <widget class="GtkMenuItem" id="menuitem10"> <property name="visible">True</property> <property name="label" translatable="yes">_Help</property> <property name="use_underline">True</property> <child> <widget class="GtkMenu" id="menuitem10_menu"> <child> <widget class="GtkImageMenuItem" id="mnuAbout"> <property name="visible">True</property> <property name="label">gtk-about</property> <property name="use_stock">True</property> <signal name="activate" handler="self::showAboutDialog" last_modification_time="Mon, 24 Oct 2005 16:24:23 GMT"/> </widget> </child> </widget> </child> </widget> </child> </widget> </child> </widget> <packing> <property name="padding">0</property> <property name="expand">False</property> <property name="fill">True</property> </packing> </child> <child> <widget class="GtkHPaned" id="hpanedMain"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="position">200</property> <child> <widget class="GtkVBox" id="vboxCategories"> <property name="visible">True</property> <property name="homogeneous">False</property> <property name="spacing">0</property> <child> <widget class="GtkHBox" id="hboxChannel"> <property name="visible">True</property> <property name="homogeneous">False</property> <property name="spacing">0</property> <child> <widget class="GtkLabel" id="lblChannel"> <property name="visible">True</property> <property name="label" translatable="yes">_Channel:</property> <property name="use_underline">True</property> <property name="use_markup">False</property> <property name="justify">GTK_JUSTIFY_LEFT</property> <property name="wrap">False</property> <property name="selectable">False</property> <property name="xalign">0.5</property> <property name="yalign">0.5</property> <property name="xpad">0</property> <property name="ypad">0</property> <property name="mnemonic_widget">cmbChannel</property> </widget> <packing> <property name="padding">0</property> <property name="expand">False</property> <property name="fill">False</property> </packing> </child> <child> <widget class="GtkComboBox" id="cmbChannel"> <property name="visible">True</property> <property name="items" translatable="yes">item1 item2</property> </widget> <packing> <property name="padding">0</property> <property name="expand">True</property> <property name="fill">True</property> </packing> </child> </widget> <packing> <property name="padding">0</property> <property name="expand">False</property> <property name="fill">False</property> </packing> </child> <child> <widget class="GtkHSeparator" id="hsepCategories"> <property name="visible">True</property> </widget> <packing> <property name="padding">4</property> <property name="expand">False</property> <property name="fill">False</property> </packing> </child> <child> <widget class="GtkLabel" id="lblCategories"> <property name="visible">True</property> <property name="label" translatable="yes">Cate_gories</property> <property name="use_underline">True</property> <property name="use_markup">False</property> <property name="justify">GTK_JUSTIFY_LEFT</property> <property name="wrap">False</property> <property name="selectable">False</property> <property name="xalign">0.5</property> <property name="yalign">0.5</property> <property name="xpad">0</property> <property name="ypad">0</property> <property name="mnemonic_widget">lstCategories</property> </widget> <packing> <property name="padding">0</property> <property name="expand">False</property> <property name="fill">False</property> </packing> </child> <child> <widget class="GtkScrolledWindow" id="scrwndCategories"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> <property name="shadow_type">GTK_SHADOW_IN</property> <property name="window_placement">GTK_CORNER_TOP_LEFT</property> <child> <widget class="GtkTreeView" id="lstCategories"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="headers_visible">False</property> <property name="rules_hint">False</property> <property name="reorderable">False</property> <property name="enable_search">True</property> </widget> </child> </widget> <packing> <property name="padding">0</property> <property name="expand">True</property> <property name="fill">True</property> </packing> </child> </widget> <packing> <property name="shrink">True</property> <property name="resize">False</property> </packing> </child> <child> <widget class="GtkVBox" id="vboxPackages"> <property name="visible">True</property> <property name="homogeneous">False</property> <property name="spacing">0</property> <child> <widget class="GtkHBox" id="hboxCategoryInfo"> <property name="visible">True</property> <property name="homogeneous">False</property> <property name="spacing">0</property> <child> <widget class="GtkImage" id="imgChannelLogo"> <property name="visible">True</property> <property name="xalign">0.5</property> <property name="yalign">0.5</property> <property name="xpad">0</property> <property name="ypad">0</property> </widget> <packing> <property name="padding">0</property> <property name="expand">False</property> <property name="fill">True</property> </packing> </child> <child> <widget class="GtkEventBox" id="evboxSelectedCategory"> <property name="visible">True</property> <property name="visible_window">True</property> <property name="above_child">False</property> <child> <widget class="GtkLabel" id="lblSelectedCategory"> <property name="visible">True</property> <property name="label" translatable="yes">No category selected</property> <property name="use_underline">False</property> <property name="use_markup">False</property> <property name="justify">GTK_JUSTIFY_LEFT</property> <property name="wrap">False</property> <property name="selectable">False</property> <property name="xalign">0.899999976158</property> <property name="yalign">0.5</property> <property name="xpad">3</property> <property name="ypad">0</property> </widget> </child> </widget> <packing> <property name="padding">0</property> <property name="expand">True</property> <property name="fill">True</property> </packing> </child> <child> <widget class="GtkToolbar" id="tbViewIcons"> <property name="orientation">GTK_ORIENTATION_HORIZONTAL</property> <property name="toolbar_style">GTK_TOOLBAR_BOTH</property> <property name="tooltips">True</property> <property name="show_arrow">True</property> <child> <widget class="GtkRadioToolButton" id="btnViewIcons"> <property name="visible">True</property> <property name="label" translatable="yes">Icons</property> <property name="use_underline">True</property> <property name="visible_horizontal">True</property> <property name="visible_vertical">True</property> <property name="is_important">False</property> <property name="active">False</property> </widget> <packing> <property name="expand">False</property> <property name="homogeneous">True</property> </packing> </child> <child> <widget class="GtkRadioToolButton" id="btnViewList"> <property name="visible">True</property> <property name="label" translatable="yes">List</property> <property name="use_underline">True</property> <property name="visible_horizontal">True</property> <property name="visible_vertical">True</property> <property name="is_important">False</property> <property name="active">False</property> <property name="group">btnViewIcons</property> </widget> <packing> <property name="expand">False</property> <property name="homogeneous">True</property> </packing> </child> </widget> <packing> <property name="padding">2</property> <property name="expand">False</property> <property name="fill">True</property> <property name="pack_type">GTK_PACK_END</property> </packing> </child> </widget> <packing> <property name="padding">0</property> <property name="expand">False</property> <property name="fill">True</property> </packing> </child> <child> <widget class="GtkVPaned" id="vpanedPackages"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="position">300</property> <child> <widget class="GtkScrolledWindow" id="scrwndPackages"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> <property name="shadow_type">GTK_SHADOW_IN</property> <property name="window_placement">GTK_CORNER_TOP_LEFT</property> <child> <widget class="GtkTreeView" id="lstPackages"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="headers_visible">True</property> <property name="rules_hint">False</property> <property name="reorderable">False</property> <property name="enable_search">True</property> </widget> </child> </widget> <packing> <property name="shrink">True</property> <property name="resize">False</property> </packing> </child> <child> <widget class="GtkScrolledWindow" id="scrwndPackageInfo"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> <property name="shadow_type">GTK_SHADOW_IN</property> <property name="window_placement">GTK_CORNER_TOP_LEFT</property> <child> <widget class="GtkTextView" id="txtPackageInfo"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="editable">False</property> <property name="overwrite">False</property> <property name="accepts_tab">True</property> <property name="justification">GTK_JUSTIFY_LEFT</property> <property name="wrap_mode">GTK_WRAP_CHAR</property> <property name="cursor_visible">True</property> <property name="pixels_above_lines">0</property> <property name="pixels_below_lines">0</property> <property name="pixels_inside_wrap">0</property> <property name="left_margin">0</property> <property name="right_margin">0</property> <property name="indent">0</property> <property name="text" translatable="yes"></property> </widget> </child> </widget> <packing> <property name="shrink">True</property> <property name="resize">True</property> </packing> </child> </widget> <packing> <property name="padding">0</property> <property name="expand">True</property> <property name="fill">True</property> </packing> </child> <child> <widget class="GtkHButtonBox" id="hbbInstallation"> <property name="visible">True</property> <property name="layout_style">GTK_BUTTONBOX_END</property> <property name="spacing">5</property> <child> <widget class="GtkButton" id="btnUninstall"> <property name="sensitive">False</property> <property name="can_default">True</property> <property name="can_focus">True</property> <property name="relief">GTK_RELIEF_NORMAL</property> <property name="focus_on_click">True</property> <child> <widget class="GtkAlignment" id="alignment2"> <property name="visible">True</property> <property name="xalign">0.5</property> <property name="yalign">0.5</property> <property name="xscale">0</property> <property name="yscale">0</property> <property name="top_padding">0</property> <property name="bottom_padding">0</property> <property name="left_padding">0</property> <property name="right_padding">0</property> <child> <widget class="GtkHBox" id="hbox3"> <property name="visible">True</property> <property name="homogeneous">False</property> <property name="spacing">2</property> <child> <widget class="GtkImage" id="image3"> <property name="visible">True</property> <property name="stock">gtk-remove</property> <property name="icon_size">4</property> <property name="xalign">0.5</property> <property name="yalign">0.5</property> <property name="xpad">0</property> <property name="ypad">0</property> </widget> <packing> <property name="padding">0</property> <property name="expand">False</property> <property name="fill">False</property> </packing> </child> <child> <widget class="GtkLabel" id="lblBtnUninstall"> <property name="visible">True</property> <property name="label" translatable="yes">_Uninstall</property> <property name="use_underline">True</property> <property name="use_markup">False</property> <property name="justify">GTK_JUSTIFY_LEFT</property> <property name="wrap">False</property> <property name="selectable">False</property> <property name="xalign">0.5</property> <property name="yalign">0.5</property> <property name="xpad">0</property> <property name="ypad">0</property> </widget> <packing> <property name="padding">0</property> <property name="expand">False</property> <property name="fill">False</property> </packing> </child> </widget> </child> </widget> </child> </widget> </child> <child> <widget class="GtkButton" id="btnInstall"> <property name="visible">True</property> <property name="sensitive">False</property> <property name="can_default">True</property> <property name="can_focus">True</property> <property name="relief">GTK_RELIEF_NORMAL</property> <property name="focus_on_click">True</property> <signal name="clicked" handler="self::installPackage" last_modification_time="Mon, 24 Oct 2005 17:31:54 GMT"/> <child> <widget class="GtkAlignment" id="alignment1"> <property name="visible">True</property> <property name="xalign">0.5</property> <property name="yalign">0.5</property> <property name="xscale">0</property> <property name="yscale">0</property> <property name="top_padding">0</property> <property name="bottom_padding">0</property> <property name="left_padding">0</property> <property name="right_padding">0</property> <child> <widget class="GtkHBox" id="hbox2"> <property name="visible">True</property> <property name="homogeneous">False</property> <property name="spacing">2</property> <child> <widget class="GtkImage" id="image2"> <property name="visible">True</property> <property name="stock">gtk-add</property> <property name="icon_size">4</property> <property name="xalign">0.5</property> <property name="yalign">0.5</property> <property name="xpad">0</property> <property name="ypad">0</property> </widget> <packing> <property name="padding">0</property> <property name="expand">False</property> <property name="fill">False</property> </packing> </child> <child> <widget class="GtkLabel" id="lblBtnInstall"> <property name="visible">True</property> <property name="label" translatable="yes">Inst_all package</property> <property name="use_underline">True</property> <property name="use_markup">False</property> <property name="justify">GTK_JUSTIFY_LEFT</property> <property name="wrap">False</property> <property name="selectable">False</property> <property name="xalign">0.5</property> <property name="yalign">0.5</property> <property name="xpad">0</property> <property name="ypad">0</property> </widget> <packing> <property name="padding">0</property> <property name="expand">False</property> <property name="fill">False</property> </packing> </child> </widget> </child> </widget> </child> </widget> </child> </widget> <packing> <property name="padding">0</property> <property name="expand">False</property> <property name="fill">True</property> </packing> </child> </widget> <packing> <property name="shrink">True</property> <property name="resize">True</property> </packing> </child> </widget> <packing> <property name="padding">0</property> <property name="expand">True</property> <property name="fill">True</property> </packing> </child> <child> <widget class="GtkStatusbar" id="statusbar"> <property name="visible">True</property> <property name="has_resize_grip">True</property> </widget> <packing> <property name="padding">0</property> <property name="expand">False</property> <property name="fill">False</property> </packing> </child> </widget> </child> </widget> <widget class="GtkWindow" id="dlgProgress"> <property name="title" translatable="yes">Retrieving data...</property> <property name="type">GTK_WINDOW_TOPLEVEL</property> <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property> <property name="modal">False</property> <property name="default_width">360</property> <property name="default_height">100</property> <property name="resizable">True</property> <property name="destroy_with_parent">False</property> <property name="decorated">True</property> <property name="skip_taskbar_hint">True</property> <property name="skip_pager_hint">False</property> <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> <child> <widget class="GtkVBox" id="vboxProgMain"> <property name="visible">True</property> <property name="homogeneous">False</property> <property name="spacing">0</property> <child> <widget class="GtkHBox" id="hboxProgAnim"> <property name="visible">True</property> <property name="homogeneous">False</property> <property name="spacing">0</property> <child> <widget class="GtkImage" id="imgProgress"> <property name="visible">True</property> <property name="xalign">0.5</property> <property name="yalign">0.5</property> <property name="xpad">50</property> <property name="ypad">0</property> </widget> <packing> <property name="padding">0</property> <property name="expand">False</property> <property name="fill">False</property> </packing> </child> <child> <widget class="GtkLabel" id="lblProgress"> <property name="visible">True</property> <property name="label" translatable="yes">34 / 300</property> <property name="use_underline">False</property> <property name="use_markup">False</property> <property name="justify">GTK_JUSTIFY_LEFT</property> <property name="wrap">False</property> <property name="selectable">False</property> <property name="xalign">0.5</property> <property name="yalign">0.5</property> <property name="xpad">0</property> <property name="ypad">0</property> </widget> <packing> <property name="padding">0</property> <property name="expand">True</property> <property name="fill">True</property> </packing> </child> </widget> <packing> <property name="padding">0</property> <property name="expand">False</property> <property name="fill">True</property> </packing> </child> <child> <widget class="GtkLabel" id="lblDescription"> <property name="visible">True</property> <property name="label" translatable="yes">Loading package data</property> <property name="use_underline">False</property> <property name="use_markup">False</property> <property name="justify">GTK_JUSTIFY_LEFT</property> <property name="wrap">False</property> <property name="selectable">False</property> <property name="xalign">0.5</property> <property name="yalign">0.5</property> <property name="xpad">0</property> <property name="ypad">0</property> </widget> <packing> <property name="padding">2</property> <property name="expand">True</property> <property name="fill">True</property> </packing> </child> <child> <widget class="GtkProgressBar" id="progBar"> <property name="visible">True</property> <property name="orientation">GTK_PROGRESS_LEFT_TO_RIGHT</property> <property name="fraction">0</property> <property name="pulse_step">0.10000000149</property> </widget> <packing> <property name="padding">2</property> <property name="expand">False</property> <property name="fill">False</property> </packing> </child> </widget> </child> </widget> <widget class="GtkWindow" id="dlgInstalling"> <property name="title" translatable="yes">Installing package</property> <property name="type">GTK_WINDOW_TOPLEVEL</property> <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property> <property name="modal">True</property> <property name="default_width">600</property> <property name="resizable">True</property> <property name="destroy_with_parent">False</property> <property name="decorated">True</property> <property name="skip_taskbar_hint">False</property> <property name="skip_pager_hint">False</property> <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property> <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> <child> <widget class="GtkVBox" id="vboxInstalling"> <property name="visible">True</property> <property name="homogeneous">False</property> <property name="spacing">0</property> <child> <widget class="GtkHBox" id="hboxInstallingProgress"> <property name="visible">True</property> <property name="homogeneous">False</property> <property name="spacing">0</property> <child> <widget class="GtkImage" id="imgInstalling"> <property name="visible">True</property> <property name="xalign">0.5</property> <property name="yalign">0.5</property> <property name="xpad">10</property> <property name="ypad">10</property> </widget> <packing> <property name="padding">0</property> <property name="expand">False</property> <property name="fill">True</property> </packing> </child> <child> <widget class="GtkVBox" id="vboxInstallingProgressTextual"> <property name="visible">True</property> <property name="homogeneous">False</property> <property name="spacing">0</property> <child> <widget class="GtkLabel" id="lblInstalling"> <property name="visible">True</property> <property name="label" translatable="yes">Loading files from the channel server</property> <property name="use_underline">False</property> <property name="use_markup">False</property> <property name="justify">GTK_JUSTIFY_LEFT</property> <property name="wrap">False</property> <property name="selectable">False</property> <property name="xalign">0</property> <property name="yalign">0.5</property> <property name="xpad">10</property> <property name="ypad">3</property> </widget> <packing> <property name="padding">0</property> <property name="expand">False</property> <property name="fill">False</property> </packing> </child> <child> <widget class="GtkProgressBar" id="progBarInstaller"> <property name="visible">True</property> <property name="orientation">GTK_PROGRESS_LEFT_TO_RIGHT</property> <property name="fraction">0.199999988079</property> <property name="pulse_step">0.10000000149</property> </widget> <packing> <property name="padding">5</property> <property name="expand">False</property> <property name="fill">True</property> </packing> </child> </widget> <packing> <property name="padding">0</property> <property name="expand">True</property> <property name="fill">True</property> </packing> </child> </widget> <packing> <property name="padding">0</property> <property name="expand">False</property> <property name="fill">True</property> </packing> </child> <child> <widget class="GtkExpander" id="expLog"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="expanded">False</property> <property name="spacing">0</property> <child> <widget class="GtkScrolledWindow" id="scrwndInstalling"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property> <property name="shadow_type">GTK_SHADOW_IN</property> <property name="window_placement">GTK_CORNER_TOP_LEFT</property> <child> <widget class="GtkTextView" id="txtInstalling"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="editable">False</property> <property name="overwrite">False</property> <property name="accepts_tab">True</property> <property name="justification">GTK_JUSTIFY_LEFT</property> <property name="wrap_mode">GTK_WRAP_CHAR</property> <property name="cursor_visible">True</property> <property name="pixels_above_lines">0</property> <property name="pixels_below_lines">0</property> <property name="pixels_inside_wrap">0</property> <property name="left_margin">0</property> <property name="right_margin">0</property> <property name="indent">0</property> <property name="text" translatable="yes"></property> </widget> </child> </widget> </child> <child> <widget class="GtkLabel" id="lblExpLog"> <property name="visible">True</property> <property name="label" translatable="yes">Log view</property> <property name="use_underline">False</property> <property name="use_markup">False</property> <property name="justify">GTK_JUSTIFY_LEFT</property> <property name="wrap">False</property> <property name="selectable">False</property> <property name="xalign">0.5</property> <property name="yalign">0.5</property> <property name="xpad">0</property> <property name="ypad">0</property> </widget> <packing> <property name="type">label_item</property> </packing> </child> </widget> <packing> <property name="padding">0</property> <property name="expand">True</property> <property name="fill">True</property> </packing> </child> <child> <widget class="GtkHButtonBox" id="bboxInstallingMain"> <property name="visible">True</property> <property name="layout_style">GTK_BUTTONBOX_END</property> <property name="spacing">0</property> <child> <widget class="GtkButton" id="btnCloseInstalling"> <property name="visible">True</property> <property name="can_default">True</property> <property name="can_focus">True</property> <property name="label">gtk-close</property> <property name="use_stock">True</property> <property name="relief">GTK_RELIEF_NORMAL</property> <property name="focus_on_click">True</property> </widget> </child> </widget> <packing> <property name="padding">0</property> <property name="expand">False</property> <property name="fill">True</property> </packing> </child> </widget> </child> </widget> </glade-interface> http://cvs.php.net/viewcvs.cgi/pear/PEAR_Frontend_Gtk2/Gtk2/run.phpw?view=markup&rev=1.1 Index: pear/PEAR_Frontend_Gtk2/Gtk2/run.phpw +++ pear/PEAR_Frontend_Gtk2/Gtk2/run.phpw <?php /** * Start the PEAR_Frontend_Gtk2 program * @author Christian Weiske <cweiske@php.net> */ require_once('PEAR/Frontend/Gtk2/Checks.php'); require_once('PEAR/Frontend/Gtk2.php'); $pf = new PEAR_Frontend_Gtk2(); Gtk::main(); ?> http://cvs.php.net/viewcvs.cgi/pear/PEAR_Frontend_Gtk2/tests/ConfigTest.php?view=markup&rev=1.1 Index: pear/PEAR_Frontend_Gtk2/tests/ConfigTest.php +++ pear/PEAR_Frontend_Gtk2/tests/ConfigTest.php <?php require_once 'PHPUnit2/Framework/TestCase.php'; require_once 'PEAR/Frontend/Gtk2/Config.php'; require_once dirname(__FILE__) . '/TimeDiff.php'; class PEAR_Frontend_Gtk2_Tests_ConfigTest extends PHPUnit2_Framework_TestCase { public function testRead() { var_dump(PEAR_Frontend_Gtk2_Config::loadConfig()); }//public function testRead() public function testSave() { PEAR_Frontend_Gtk2_Config::saveConfig(); }//public function testSave() }//class PEAR_Frontend_Gtk2_Tests_ConfigTest extends PHPUnit2_Framework_TestCase ?> http://cvs.php.net/viewcvs.cgi/pear/PEAR_Frontend_Gtk2/tests/ExpanderTest.phpw?view=markup&rev=1.1 Index: pear/PEAR_Frontend_Gtk2/tests/ExpanderTest.phpw +++ pear/PEAR_Frontend_Gtk2/tests/ExpanderTest.phpw <?php $window = new GtkWindow(); $window->set_title('GtkExpander test'); $window->connect_simple('destroy', array('gtk', 'main_quit')); $expander = new GtkExpander('Expand me'); $expander->set_expanded(false); $expander->add(new GtkLabel("1\r\n2\r\n3\r\n4\r\n5\r\n6")); $expander->connect_after('activate', 'expanded'); function expanded($expander) { if (!$expander->get_expanded()) { echo "ba"; $expander->set_size_request(1,1); $window = $expander->get_parent(); $window->set_default_size(1,1); } } $window->add($expander); $window->show_all(); Gtk::main(); ?> http://cvs.php.net/viewcvs.cgi/pear/PEAR_Frontend_Gtk2/tests/PackageTest.php?view=markup&rev=1.1 Index: pear/PEAR_Frontend_Gtk2/tests/PackageTest.php +++ pear/PEAR_Frontend_Gtk2/tests/PackageTest.php <?php require_once 'PHPUnit2/Framework/TestCase.php'; require_once 'PEAR/Frontend/Gtk2/Packages.php'; require_once dirname(__FILE__) . '/TimeDiff.php'; class PEAR_Frontend_Gtk2_Tests_PackageTest extends PHPUnit2_Framework_TestCase { protected $nCallbackCount = 0; public function testPearCache() { $config = PEAR_Config::singleton(); $cachedir = $config->get('cache_dir'); $this->assertTrue(is_writable($cachedir), 'PEAR cache directory is NOT writable! ' . $cachedir); }//public function testPearCache() public function testGetRemotePackages() { //first, check without extra information $arPacks = PEAR_Frontend_Gtk2_Packages::getRemotePackages('gnope.org', false); $this->assertTrue(count($arPacks) > 0); $inspector = self::findPackage($arPacks, 'Dev_Inspector'); $this->assertNotNull($inspector); $this->assertEquals('Dev_Inspector', $inspector->getName()); $this->assertNull($inspector->getSummary()); $this->assertNull($inspector->getDescription()); $this->assertNull($inspector->getCategory()); $this->assertEquals('gnope.org', $inspector->getChannel()); //Now, with extra information loaded $arPacks = PEAR_Frontend_Gtk2_Packages::getRemotePackages('gnope.org', true); $this->assertTrue(count($arPacks) > 0); $inspector = self::findPackage($arPacks, 'Dev_Inspector'); $this->assertNotNull($inspector); $this->assertEquals('Dev_Inspector', $inspector->getName()); $this->assertNotNull($inspector->getSummary()); $this->assertNotNull($inspector->getDescription()); $this->assertNotNull($inspector->getCategory()); $this->assertEquals('gnope.org', $inspector->getChannel()); }//public function testGetRemotePackages() public function testGetLocalPackages() { $arPacks = PEAR_Frontend_Gtk2_Packages::getLocalPackages('pear'); $this->assertTrue(count($arPacks) > 0); $this->assertNotNull($arPacks['PHPUnit']); $this->assertNotNull($arPacks['PEAR']); }//public function testGetLocalPackages() public function testMergePackageData() { $arPacks = PEAR_Frontend_Gtk2_Packages::getLocalPackages('pear'); $arLocalPackIds = array(); foreach ($arPacks as $strName => $objPack) { $arLocalPackIds[$strName] = $strName; $this->assertNotNull($objPack->getInstalledVersion()); $this->assertNull($objPack->getLatestVersion()); } $nCount = count($arPacks); $this->nCallbackCount = 0; $arAllPacks = PEAR_Frontend_Gtk2_Packages::getRemotePackages('pear', true, array($this, 'packageCallback')); $this->assertTrue(count($arAllPacks) >= $nCount); $this->assertEquals(count($arAllPacks), $this->nCallbackCount); foreach ($arLocalPackIds as $strName) { $this->assertTrue(isset($arAllPacks[$strName])); $this->assertNotNull($arPacks[$strName]->getInstalledVersion()); } foreach ($arAllPacks as $strName => $package) { $this->assertNotNull($package->getLatestVersion()); } }//public function testMergePackageData() public function testGuessCategory() { $this->assertEquals('Dev' , PEAR_Frontend_Gtk2_Package::guessCategory('Dev_Inspector')); $this->assertEquals('PEAR' , PEAR_Frontend_Gtk2_Package::guessCategory('PEAR_Frontend_Gtk')); $this->assertEquals('' , PEAR_Frontend_Gtk2_Package::guessCategory('DevInspector')); }//public function testGuessCategory() public function testGetCategories() { $pcks = new PEAR_Frontend_Gtk2_Packages('pear'); $arCategories = $pcks->getCategories(); $arPackages = $pcks->getPackages(); $this->assertTrue(count($arPackages) > 0); foreach ($arPackages as $package) { $this->assertTrue(isset($arCategories[$package->getCategory()])); } }//public function testGetCategories() public function packageCallback($nPackageCount, $nCurrentPackage) { if ($nPackageCount !== true) { $this->nCallbackCount++; } // echo $nCurrentPackage . '/' . $nPackageCount . "\r\n"; }//public function packageCallback($nPackageCount, $nCurrentPackage) protected static function findPackage($arPackages, $strPackageName) { foreach ($arPackages as $nId => $package) { if ($package->getName() == 'Dev_Inspector') { break; } } if ($arPackages[$nId]->getName() !== $strPackageName) { return null; } else { return $arPackages[$nId]; } }//protected static function findPackage($arPackages, $strPackageName) }//class PEAR_Frontend_Gtk2_Tests_PackageTest extends PHPUnit_TestCase ?> http://cvs.php.net/viewcvs.cgi/pear/PEAR_Frontend_Gtk2/tests/TimeDiff.php?view=markup&rev=1.1 Index: pear/PEAR_Frontend_Gtk2/tests/TimeDiff.php +++ pear/PEAR_Frontend_Gtk2/tests/TimeDiff.php <?php class TimeDiff { static $arBeginTimes = array(); public static function start($nIndex = 0) { self::$arBeginTimes[$nIndex] = microtime(1); }//public static function start($nIndex = 0) public static function stop($nIndex = 0) { $flEnd = microtime(1); return $flEnd - self::$arBeginTimes[$nIndex]; }//public static function stop($nIndex = 0) public static function printStop($nIndex = 0, $strExtraText = null) { $flDiff = self::stop($nIndex); if ($strExtraText == null) { echo 'TimeDiff #' . $nIndex . ': ' . $flDiff . "\r\n"; } else { echo 'TimeDiff ' . $strExtraText . ': ' . $flDiff . "\r\n"; } }//public static function printStop($nIndex = 0) }//class TimeDiff ?> http://cvs.php.net/viewcvs.cgi/pear/PEAR_Frontend_Gtk2/tests/runtests.php?view=markup&rev=1.1 Index: pear/PEAR_Frontend_Gtk2/tests/runtests.php +++ pear/PEAR_Frontend_Gtk2/tests/runtests.php <?php /** * PEAR_Frontend_Gtk2 unit tests * @author Christian Weiske <cweiske@cweiske.de> */ if (!defined('PHPUnit2_MAIN_METHOD')) { define('PHPUnit2_MAIN_METHOD', 'PEAR_Frontend_Gtk2_Tests_AllTests::main'); } require_once 'PHPUnit2/Framework/TestSuite.php'; require_once 'PHPUnit2/TextUI/TestRunner.php'; require_once 'PackageTest.php'; require_once 'ConfigTest.php'; class PEAR_Frontend_Gtk2_Tests_AllTests { public static function main() { PHPUnit2_TextUI_TestRunner::run(self::suite()); } public static function suite() { $suite = new PHPUnit2_Framework_TestSuite('PHPUnit Framework'); // $suite->addTestSuite('PEAR_Frontend_Gtk2_Tests_PackageTest'); // $suite->addTestSuite('PEAR_Frontend_Gtk2_Tests_ConfigTest'); return $suite; } } if (PHPUnit2_MAIN_METHOD == 'PEAR_Frontend_Gtk2_Tests_AllTests::main') { PEAR_Frontend_Gtk2_Tests_AllTests::main(); } ?>
« previous php.pear.cvs (#36879) next »