PEAR_Frontend_Gtk2
[ class tree: PEAR_Frontend_Gtk2 ] [ index: PEAR_Frontend_Gtk2 ] [ all elements ]

Source for file Gtk2.php

Documentation is available at Gtk2.php

  1. <?php
  2. require_once 'PEAR/Frontend/Gtk2/Checks.php';
  3. require_once 'PEAR/Config.php';
  4. require_once 'PEAR/Frontend.php';
  5.  
  6. require_once 'PEAR/Frontend/Gtk2/About.php';
  7. require_once 'PEAR/Frontend/Gtk2/ChannelDialog.php';
  8. require_once 'PEAR/Frontend/Gtk2/Channels.php';
  9. require_once 'PEAR/Frontend/Gtk2/Config.php';
  10. require_once 'PEAR/Frontend/Gtk2/Packages.php';
  11. require_once 'PEAR/Frontend/Gtk2/Installation.php';
  12.  
  13. require_once 'Gtk2/FileDrop.php';
  14.  
  15. /**
  16. *   Graphical frontend for PEAR, based on PHP-Gtk2
  17. *
  18. *   TODO:
  19. *   - Package categories aren't updated/extendet if there is an error at startup loading/packages are refreshed and a new category is required
  20. *   - Warn if the package list is older than 5 days
  21. *   - upgrade-all menu option
  22. *   - Filter by upgradeable/installed/installable/all packages
  23. *   - Channel server icons in channel.xml -> use them and cache locally
  24. *   - Config settings window
  25. *
  26. *   Don't know how to do:
  27. *   - installation dialog showing has to be updated correctly
  28. *   - Installation: shrink window if expander is collapsed
  29. *
  30. *   Done:
  31. *   - Drop package file onto install button -> install it
  32. *   - Install pecl packages - error messages aren't shown
  33. *   - channel discovery
  34. *   - better installation ok icon
  35. *   - Window icon - shows the php icon on windows currently
  36. *   - When no internet connection on startup, no categories are loaded and no local packages are shown
  37. *   - When no pear cache directory exists, the check warning is shown - pear cache directory is created now
  38. *   - uninstall: pear/liveuser is required by installed package "pear/Event_Dispatcher"
  39. *   - use menu options (deps, nodeps)
  40. *   - refresh online info (clear cache or so)
  41. *   - offline mode
  42. *   - save and load settings
  43. *   - scroll text in installation
  44. *
  45. *   @author Christian Weiske <cweiske@php.net>
  46. */
  47. class PEAR_Frontend_Gtk2 extends PEAR_Frontend
  48. {
  49.     /**
  50.     *   The widgets which shall be loaded from the glade
  51.     *   file into the $arWidgets array
  52.     *   @var array 
  53.     */
  54.     protected static $arRequestedWidgets = array(
  55.         'dlgInstaller''lstCategories''lstPackages''txtPackageInfo',
  56.         'cmbChannel''imgChannelLogo''lblSelectedCategory''hboxCategoryInfo',
  57.         'btnInstall','btnUninstall','lblBtnInstall','evboxSelectedCategory','expPackageInfo',
  58.  
  59.         'mnuOptDepsNo','mnuOptDepsReq','mnuOptDepsAll','mnuOptDepNothing',
  60.         'mnuOptForce',
  61.         'mnuOffline','mnuQuit','mnuAbout','mnuUpdateOnline','mnuUpdateLocal',
  62.         'mnuChannels','mnuConfig','mnuInstallLocal',
  63.  
  64.         'dlgProgress''lblDescription''imgProgress''lblProgress''progBar'
  65.     );
  66.  
  67.     protected $nProgressImage = 1;
  68.  
  69.     /**
  70.     *   Array with images used for the progress animation
  71.     */
  72.     protected $arAnimationImages = array();
  73.  
  74.     /**
  75.     *   Requested widgets are loaded from glade into this array.
  76.     *   So this is an associative array with all required widgets
  77.     *   from the glade file: name => widget object
  78.     *   @var array 
  79.     */
  80.     protected $arWidgets;
  81.  
  82.     /**
  83.     *   The PEAR_Frontend_Gtk2_Installation object to use
  84.     *   @var PEAR_Frontend_Gtk2_Installation 
  85.     */
  86.     protected $installer = null;
  87.  
  88.     /**
  89.     *   The channel dialog
  90.     *   @var PEAR_Frontend_Gtk2_ChannelDialog 
  91.     */
  92.     protected $channelDialog = null;
  93.  
  94.     protected $selectedPackage          = null;
  95.     protected $strSelectedCategoryName  = null;
  96.     protected $strSelectedCategoryKey   = null;
  97.  
  98.     /**
  99.     *   The package information class instance
  100.     *   @var PEAR_Frontend_Gtk2_Packages 
  101.     */
  102.     protected $packages = null;
  103.  
  104.     /**
  105.     *   Last package file that has been installed
  106.     *
  107.     *   @var string 
  108.     */
  109.     protected $strLastFile = null;
  110.  
  111.     const CATEGORY_ALL      = 12345678;
  112.     const CATEGORY_SELECTED = 12345679;
  113.  
  114.  
  115.  
  116.     /**
  117.     *   Special categories which are added to the
  118.     *   channel categories
  119.     *   @var array 
  120.     */
  121.     protected static $arSpecialCategories = array(
  122.         PEAR_Frontend_Gtk2::CATEGORY_ALL      => '*All packages',
  123. //        PEAR_Frontend_Gtk2::CATEGORY_SELECTED => '*Selected for install'
  124.     );
  125.  
  126.  
  127.     public function __construct()
  128.     {
  129.         $this->loadConfig();
  130.         PEAR_Frontend_Gtk2_Config::loadConfig();
  131.         $this->buildDialog();
  132.         PEAR_Frontend_Gtk2_Config::loadCurrentConfigIntoGui($this);
  133.         $this->loadChannels(PEAR_Frontend_Gtk2_Config::$strDefaultChannel);
  134.         $this->selectPackageByName(PEAR_Frontend_Gtk2_Config::$strDefaultPackage);
  135.     }//public function __construct()
  136.  
  137.  
  138.  
  139.     function loadConfig()
  140.     {
  141.         $this->config   = PEAR_Config::singleton();
  142.         $this->packages = new PEAR_Frontend_Gtk2_Packages($this->config);
  143.     }//function loadConfig()
  144.  
  145.  
  146.  
  147.     /**
  148.     *   Fill the channel dropdown with channel names
  149.     *
  150.     *   @param string   $strDefaultChannel  The channel to set active
  151.     */
  152.     public function loadChannels($strDefaultChannel = null)
  153.     {
  154.         if ($strDefaultChannel == null{
  155.             $strDefaultChannel $this->arWidgets['cmbChannel']->get_active_text();
  156.         }
  157.  
  158.         //After all has been initiated, load the data
  159.         PEAR_Frontend_Gtk2_Channels::loadChannels(
  160.             $this->arWidgets['cmbChannel'],
  161.             $this->config,
  162.             $strDefaultChannel
  163.         );
  164.     }//public function loadChannels($strDefault = null)
  165.  
  166.  
  167.  
  168.     public function quitApp()
  169.     {
  170.         PEAR_Frontend_Gtk2_Config::loadConfigurationFromGui($this);
  171.         PEAR_Frontend_Gtk2_Config::saveConfig();
  172.         Gtk::main_quit();
  173.     }//public function quitApp()
  174.  
  175.  
  176.  
  177.     /**
  178.     *   load the glade file, load the widgets, connect the signals
  179.     */
  180.     protected function buildDialog()
  181.     {
  182.         $this->glade = new GladeXML(dirname(__FILE__'/Gtk2/installer.glade');
  183.         foreach (self::$arRequestedWidgets as $strWidgetName{
  184.             $this->arWidgets[$strWidgetName$this->glade->get_widget($strWidgetName);
  185.         }
  186.  
  187.         $this->arWidgets['dlgInstaller']->connect_simple('destroy'array($this'quitApp'));
  188.         $strIcon = dirname(__FILE__'/Gtk2/runicon.png';
  189.         if (file_exists($strIcon)) {
  190.             $this->arWidgets['dlgInstaller']->set_icon_from_file($strIcon);
  191.         }
  192.  
  193.         $this->arWidgets['lblSelectedCategory']->set_use_markup(true);
  194.  
  195.         $this->arWidgets['cmbChannel']->connect('changed'array($this'selectChannel'));
  196.  
  197.         $this->arWidgets['lstCategories']->set_model(new GtkListStore(Gtk::TYPE_STRINGGtk::TYPE_STRING));
  198.         $cell_renderer = new GtkCellRendererText();
  199.         $column = new GtkTreeViewColumn('test'$cell_renderer"text"0);
  200.         $this->arWidgets['lstCategories']->append_column($column);
  201.  
  202.         $this->arWidgets['btnInstall']  ->connect_simple('clicked'array($this'installPackage')true);
  203.         $this->arWidgets['btnUninstall']->connect_simple('clicked'array($this'installPackage')false);
  204.  
  205.         //drop files onto install button
  206.         Gtk2_FileDrop::attach(
  207.             $this->arWidgets['btnInstall'],
  208.             array('application/x-tgz','.tgz'),
  209.             array($this'onFilesDropped'),
  210.             false
  211.         );
  212.         //and onto package list
  213.         Gtk2_FileDrop::attach(
  214.             $this->arWidgets['lstPackages'],
  215.             array('application/x-tgz','.tgz'),
  216.             array($this'onFilesDropped'),
  217.             false
  218.         );
  219.  
  220.         $this->arWidgets['dlgProgress']->connect('delete-event'array($this'deleteProgressWindow'));
  221.  
  222.         //Menu entries
  223.         $this->arWidgets['mnuQuit']         ->connect_simple('activate'array($this'quitApp'));
  224.         $this->arWidgets['mnuAbout']        ->connect_simple('activate'array('PEAR_Frontend_Gtk2_About''showMe'));
  225.         $this->arWidgets['mnuInstallLocal'->connect_simple('activate'array($this'onInstallLocalPackage'));
  226.         $this->arWidgets['mnuUpdateLocal']  ->connect_simple('activate'array($this'refreshLocalPackages'));
  227.         $this->arWidgets['mnuUpdateOnline'->connect_simple('activate'array($this'refreshOnlinePackages'));
  228.         $this->arWidgets['mnuChannels']     ->connect_simple('activate'array($this'showChannelDialog'));
  229.  
  230.  
  231.         //that's channel name and array key of the packages
  232.         $this->arWidgets['lstPackages']->set_model(new GtkListStore(Gtk::TYPE_STRINGGtk::TYPE_STRINGGtk::TYPE_STRINGGtk::TYPE_STRINGGtk::TYPE_PHP_VALUE));
  233.         $cell_renderer = new GtkCellRendererText();
  234.  
  235.         $colName = new GtkTreeViewColumn('Package'$cell_renderer"text"0);
  236.         $colName->set_resizable(true);
  237.         $colName->set_sort_column_id(0);
  238.         $this->arWidgets['lstPackages']->append_column($colName);
  239.  
  240.         $colInstalled = new GtkTreeViewColumn('Installed'$cell_renderer"text"1);
  241.         $colInstalled->set_resizable(true);
  242.         $colInstalled->set_sort_column_id(1);
  243.         $this->arWidgets['lstPackages']->append_column($colInstalled);
  244.  
  245.         $colNew = new GtkTreeViewColumn('New version'$cell_renderer"text"2);
  246.         $colNew->set_resizable(true);
  247.         $colNew->set_sort_column_id(2);
  248.         $this->arWidgets['lstPackages']->append_column($colNew);
  249.  
  250.         $colSummary = new GtkTreeViewColumn('Summary'$cell_renderer"text"3);
  251.         $colSummary->set_resizable(true);
  252.         $colSummary->set_sort_column_id(3);
  253.         $this->arWidgets['lstPackages']->append_column($colSummary);
  254.  
  255.         $selCategories $this->arWidgets['lstCategories']->get_selection();
  256.         $selCategories->set_mode(Gtk::SELECTION_SINGLE);
  257.         $selCategories->connect('changed'array($this'selectCategory'));
  258.  
  259.         $selPackages $this->arWidgets['lstPackages']->get_selection();
  260.         $selPackages->set_mode(Gtk::SELECTION_SINGLE);
  261.         $selPackages->connect('changed'array($this'selectPackage'));
  262.  
  263.         for ($nA = 1; $nA <= 3; $nA++{
  264.             $this->arAnimationImages[= GdkPixbuf::new_from_file(dirname(__FILE__'/Gtk2/pixmaps/progress/load-anim-' $nA '.png');
  265.         }
  266.         $this->nProgressImage = 0;
  267.  
  268.         $this->loadInstaller();
  269.     }//protected function buildDialog()
  270.  
  271.  
  272.  
  273.     protected function loadInstaller()
  274.     {
  275.         $this->installer = new PEAR_Frontend_Gtk2_Installation($this->arWidgets['dlgInstaller']$this->glade);
  276.         PEAR_Frontend::setFrontendObject($this->installer);
  277.     }//protected function loadInstaller()
  278.  
  279.  
  280.  
  281.     public function getInstaller()
  282.     {
  283.         return $this->installer;
  284.     }//public function getInstaller()
  285.  
  286.  
  287.  
  288.     public function showChannelDialog()
  289.     {
  290.         if ($this->channelDialog === null{
  291.             $this->channelDialog = new PEAR_Frontend_Gtk2_ChannelDialog($this->glade$this);
  292.         }
  293.         $this->channelDialog->show();
  294.     }//public function showChannelDialog()
  295.  
  296.  
  297.  
  298.     /**
  299.     *   A channel has been selected from the channel combo box
  300.     *
  301.     *   Has to be public as it is a callback function
  302.     *
  303.     *   @param GtkComboBox  $cmbChannel     The channel selection combo box
  304.     *   @param boolean      $bSecondTime    If the function is being run a second time (because the first run had a problem) - used to detect infinite loops.
  305.     */
  306.     public function selectChannel($cmbChannel$bSecondTime = false)
  307.     {
  308.         $strChannel $cmbChannel->get_active_text();
  309.  
  310.         $this->setChannelStyles($strChannel);
  311.  
  312.         $model $this->arWidgets['lstCategories']->get_model();
  313.         $model->clear();
  314.         $this->arWidgets['lstPackages']->get_model()->clear();
  315.  
  316.         //Channel categories
  317.         $this->packages->setActiveChannel($strChannel);
  318.  
  319.         if (!$this->packages->packagesLoaded()) {
  320.             //show the progress dialog before it gets loaded with the first callback
  321.             $this->showProgressDialog(true);
  322.         }
  323.  
  324.         try {
  325.             $arCategories $this->packages->getCategories(array($this'packagesCallback')$this->getWorkOffline());
  326.         catch (Exception $e{
  327.             $this->hideProgressDialog();
  328.             $dialog = new GtkMessageDialog(
  329.                 $this->arWidgets['dlgInstaller'],
  330.                 0,
  331.                 Gtk::MESSAGE_ERROR,
  332.                 Gtk::BUTTONS_OK,
  333.                 'Can\'t list the categories:' "\r\n"
  334.                 . $e->getCode(': ' $e->getMessage()
  335.                 . "\r\n\r\nMake sure you have an internet connection."
  336.             );
  337.             $dialog->set_transient_for($this->arWidgets['dlgInstaller']);
  338.             $dialog->set_position(Gtk::WIN_POS_CENTER_ON_PARENT);
  339.             $dialog->run();
  340.             $dialog->destroy();
  341.  
  342.             if (!$bSecondTime{
  343.                 //The exception code seem to vary on every run - so I can't check for a certain code.
  344.                 //But as we still can load the local packages, we can work offline.
  345.                 $this->setWorkOffline(true);
  346.                 $this->selectChannel($cmbChanneltrue);
  347.                 return;
  348.             else {
  349.                 //no chance to do a fix - do nothing
  350.                 return;
  351.             }
  352.         }
  353.  
  354.         $arCategories $this->appendSpecialCategories(
  355.             $arCategories
  356.         );
  357.  
  358.         foreach ($arCategories as $key => $strCategory{
  359.             $model->set($model->append()0$strCategory1$key);
  360.         }
  361.  
  362.         //Clear packages
  363.         $this->arWidgets['lstPackages']->get_model()->clear();
  364.         $this->arWidgets['lstCategories']->get_selection()->select_path('0');
  365.  
  366.         $this->hideProgressDialog();
  367.     }//public function selectChannel($cmbChannel, $bSecondTime = false)
  368.  
  369.  
  370.  
  371.     protected function setChannelStyles($strChannel)
  372.     {
  373.         //Logo
  374.         $strIcon dirname(__FILE__'/Gtk2/pixmaps/' $strChannel '.png';
  375.         if (!file_exists($strIcon)) {
  376.             $strIcon dirname(__FILE__'/Gtk2/pixmaps/default.png';
  377.         }
  378.         if (file_exists($strIcon)) {
  379.             $this->arWidgets['imgChannelLogo']->set_from_file($strIcon);
  380.         }
  381.  
  382.         //Colors
  383.         $strColorChannel $strChannel;
  384.         if (!isset(PEAR_Frontend_Gtk2_Config::$arChannels[$strColorChannel])) {
  385.             $strColorChannel 'default';
  386.         }
  387.         $colBg = GdkColor::parse(PEAR_Frontend_Gtk2_Config::$arChannels[$strColorChannel]['background-color']);
  388.         $colFg = GdkColor::parse(PEAR_Frontend_Gtk2_Config::$arChannels[$strColorChannel]['color']);
  389.  
  390.         $this->arWidgets['evboxSelectedCategory']->modify_bg(Gtk::STATE_NORMAL$colBg);
  391.         $this->arWidgets['lblSelectedCategory']->modify_fg(Gtk::STATE_NORMAL$colFg);
  392.     }//protected function setChannelStyles($strChannel)
  393.  
  394.  
  395.  
  396.     /**
  397.     *   Appends defined special categories to the given
  398.     *   list
  399.     *
  400.     *   @param  array   Array of categories
  401.     *   @return array   Array of categories with special ones
  402.     */
  403.     function appendSpecialCategories($arCategories)
  404.     {
  405.         foreach (PEAR_Frontend_Gtk2::$arSpecialCategories as $key => $value{
  406.             $arCategories[$key$value;
  407.         }
  408.         return $arCategories;
  409.     }//function appendSpecialCategories($arCategories)
  410.  
  411.  
  412.  
  413.     /**
  414.     *   A category has been selected
  415.     */
  416.     function selectCategory($selection)
  417.     {
  418.         list($model$iter$selection->get_selected();
  419.         if ($iter === null{
  420.             $this->arWidgets['lblSelectedCategory']->set_text('No category selected');
  421.             return;
  422.         }
  423.  
  424.         $this->strSelectedCategoryName  $model->get_value($iter0);
  425.         $this->strSelectedCategoryKey   $model->get_value($iter1);
  426.         $this->arWidgets['lblSelectedCategory']->set_markup('<b>' $this->strSelectedCategoryName '</b>');
  427.  
  428.         if ($this->strSelectedCategoryKey == self::CATEGORY_ALL{
  429.             $this->strSelectedCategoryName = null;
  430.         }
  431.         $this->showPackageList($this->strSelectedCategoryName);
  432.     }//function selectCategory($selection)
  433.  
  434.  
  435.  
  436.     /**
  437.     *   Fill the package list for the given category
  438.     */
  439.     protected function showPackageList($strCategory)
  440.     {
  441.         //Show packages
  442.         $model $this->arWidgets['lstPackages']->get_model();
  443.         $model->clear();
  444.         $arPackages $this->packages->getPackages($strCategory);
  445.         if (count($arPackages> 0{
  446.             foreach ($arPackages as $key => $package{
  447.                 $model->set(
  448.                     $model->append(),
  449.                     0$package->getName(),
  450.                     1$package->getInstalledVersion(),
  451.                     2$package->getLatestVersion(),
  452.                     3$package->getSummary(),
  453.                     4$package
  454.                 );
  455.             }
  456.         }
  457.     }//protected function showPackageList($strCategory)
  458.  
  459.  
  460.  
  461.     /**
  462.     *   Selects the given package
  463.     *
  464.     *   @param string $strPackage   The package name (without channel!)
  465.     */
  466.     public function selectPackageByName($strPackage)
  467.     {
  468.         if ($strPackage === null{
  469.             return;
  470.         }
  471.  
  472.         //select the "*all*" category to make sure the package
  473.         // is shown
  474.         $selection $this->arWidgets['lstCategories']->get_selection();
  475.         $model     $this->arWidgets['lstCategories']->get_model();
  476.         $selection->select_iter(
  477.             $model->get_iter_from_string(
  478.                 //gets number of children - 1 = from 0
  479.                 $model->iter_n_children(null- 1
  480.             )
  481.         );
  482.  
  483.         //now, select the package
  484.         $model $this->arWidgets['lstPackages']->get_model();
  485.         $iter  $model->get_iter_first();
  486.         while ($iter !== null{
  487.             if ($model->get_value($iter0== $strPackage{
  488.                 $this->arWidgets['lstPackages']->get_selection()->select_iter(
  489.                     $iter
  490.                 );
  491.                 break;
  492.             }
  493.             $iter $model->iter_next($iter);
  494.         }
  495.     }//public function selectPackageByName($strPackage)
  496.  
  497.  
  498.  
  499.     /**
  500.     *   Update the package list model entries for the given packages.
  501.     *   Useful after installing/uninstalling a package
  502.     *
  503.     *   @param array    $arPackages     Array of packages which model entry shall be updated
  504.     */
  505.     protected function updatePackageList($arPackages)
  506.     {
  507.         $model $this->arWidgets['lstPackages']->get_model();
  508.         $iter  $model->get_iter_first();
  509.         while ($iter !== null{
  510.             $package $model->get_value($iter4);
  511.             if (in_array($package$arPackages)) {
  512.                 $model->set(
  513.                     $iter,
  514.                     0$package->getName(),
  515.                     1$package->getInstalledVersion(),
  516.                     2$package->getLatestVersion(),
  517.                     3$package->getSummary(),
  518.                     4$package
  519.                 );
  520.             }
  521.             $iter $model->iter_next($iter);
  522.         }
  523.     }//protected function updatePackageList($arPackages)
  524.  
  525.  
  526.  
  527.     /**
  528.     *   Callback for the package loading functions
  529.     */
  530.     function packagesCallback($nPackageCount$nCurrentPackage)
  531.     {
  532.         $dlgProgress $this->arWidgets['dlgProgress'];
  533.         if ($nPackageCount === true{
  534.             //we're done
  535.             $this->hideProgressDialog();
  536.             return;
  537.         }
  538.         $this->showProgressDialog();
  539.         $this->arWidgets['lblProgress']->set_text($nCurrentPackage ' / ' $nPackageCount);
  540.         $this->arWidgets['progBar']->set_fraction(1/$nPackageCount $nCurrentPackage);
  541.  
  542.         $this->nProgressImage++;
  543.         if (!isset($this->arAnimationImages[$this->nProgressImage])) {
  544.             $this->nProgressImage = 0;
  545.         }
  546.         //TODO: hold the images in memory
  547.         $this->arWidgets['imgProgress']->set_from_pixbuf($this->arAnimationImages[$this->nProgressImage]);
  548.         while (Gtk::events_pending()) Gtk::main_iteration();}
  549.     }//function packagesCallback($nPackageCount, $nCurrentPackage)
  550.  
  551.  
  552.  
  553.     public function selectPackage($selection)
  554.     {
  555.         list($model$iter$selection->get_selected();
  556.         if ($iter === null{
  557.             $strDescription '';
  558.             $this->setSelectedPackage(null);
  559.             $this->arWidgets['btnUninstall']->hide();
  560.             $this->arWidgets['btnInstall']  ->set_sensitive(false);
  561.         else {
  562.             $package $model->get_value($iter4);
  563.             $this->setSelectedPackage($package);
  564.             $strDescription $package->getDescription();
  565.             $this->ableInstallButtons($package);
  566.             if ($package->getInstalledVersion(=== null || $package->getInstalledVersion(== ''{
  567.                 $this->arWidgets['lblBtnInstall']->set_label('Inst_all package');
  568.             else {
  569.                 $this->arWidgets['lblBtnInstall']->set_label('Upgr_ade package');
  570.             }
  571.         }
  572.  
  573.         $this->arWidgets['txtPackageInfo']->get_buffer()->set_text($strDescription);
  574.     }//public function selectPackage($selection)
  575.  
  576.  
  577.  
  578.     /**
  579.     *   Enables or disables the install buttons depending
  580.     *   on the installation status of $package
  581.     *
  582.     *   @param PEAR_Frontend_Gtk2_Package $package  The package to check
  583.     */
  584.     protected function ableInstallButtons($package)
  585.     {
  586.         if ($package === null{
  587.             return;
  588.         }
  589.  
  590.         $this->arWidgets['btnInstall']->set_sensitive(
  591.             $package->getLatestVersion(!== null
  592.             && $package->getLatestVersion(!== ''
  593.         );
  594.  
  595.         if ($package->getInstalledVersion(== ''{
  596.             $this->arWidgets['btnUninstall']->hide();
  597.             $this->arWidgets['btnUninstall']->set_sensitive(false);
  598.         else {
  599.             $this->arWidgets['btnUninstall']->show();
  600.             $this->arWidgets['btnUninstall']->set_sensitive(true);
  601.         }
  602.     }//protected function ableInstallButtons($package)
  603.  
  604.  
  605.  
  606.     protected function updateInstallButtons()
  607.     {
  608.         $selection $this->arWidgets['lstPackages']->get_selection();
  609.         list($model$iter$selection->get_selected();
  610.         $package $model->get_value($iter4);
  611.         $this->ableInstallButtons($package);
  612.     }//protected function updateInstallButtons()
  613.  
  614.  
  615.  
  616.     protected function getSelectedPackage()
  617.     {
  618.         return $this->selectedPackage;
  619.     }//protected function getSelectedPackage()
  620.  
  621.  
  622.  
  623.     protected function setSelectedPackage($package)
  624.     {
  625.         $this->selectedPackage $package;
  626.     }//protected function setSelectedPackage($package)
  627.  
  628.  
  629.  
  630.     /**
  631.     *   Installs (or uninstalls) the selected package
  632.     *
  633.     *   @param boolean $bInstall    True if the package shall be installed, false if it shall be uninstalled
  634.     */
  635.     function installPackage($bInstall = true)
  636.     {
  637.         $strChannel $this->packages->getActiveChannel();
  638.         $package $this->getSelectedPackage();
  639.         if ($package === null{
  640.             $dialog = new GtkMessageDialog(
  641.                 $this->arWidgets['dlgInstaller']0Gtk::MESSAGE_ERRORGtk::BUTTONS_OK,
  642.                 'You have to select a package before you can install it.'
  643.             );
  644.             $dialog->run();
  645.             $dialog->destroy();
  646.             return;
  647.         }
  648.  
  649.         //get changes done in gui into config
  650.         PEAR_Frontend_Gtk2_Config::loadConfigurationFromGui($this);
  651.  
  652.         $this->installer->installPackage(
  653.             $strChannel,
  654.             $package->getName(),
  655.             $package->getLatestVersion(),
  656.             $bInstall,
  657.             PEAR_Frontend_Gtk2_Config::$strDepOptions,
  658.             PEAR_Frontend_Gtk2_Config::$bForceInstall
  659.         );
  660.  
  661.         $package->refreshLocalInfo();
  662.         $this->updatePackageList(array($package));
  663.         $this->updateInstallButtons();
  664.     }//function installPackage($bInstall = true)
  665.  
  666.  
  667.  
  668.     /**
  669.     *   Shows the progress dialog if that hasn't already been done
  670.     *
  671.     *   @param boolean  $bInitWithZero  If the dialog's labels should be initialized (if the dialog has been hidden)
  672.     */
  673.     protected function showProgressDialog($bInitWithZero = false)
  674.     {
  675.         $dlgProgress $this->arWidgets['dlgProgress'];
  676.         if ($dlgProgress->window === null || !$dlgProgress->window->is_visible()) {
  677.             //show it
  678.             $dlgProgress->modify_bg(Gtk::STATE_NORMALGdkColor::parse('#FFFFFF'));
  679.             $dlgProgress->set_transient_for($this->arWidgets['dlgInstaller']);
  680.             $dlgProgress->set_position(Gtk::WIN_POS_CENTER_ON_PARENT);
  681.  
  682.             if ($bInitWithZero{
  683.                 $this->arWidgets['lblProgress']->set_text('');
  684.                 $this->arWidgets['progBar']->set_fraction(0);
  685.             }
  686.  
  687.             $dlgProgress->show_now();
  688.             while (Gtk::events_pending()) Gtk::main_iteration();}
  689.         }
  690.     }//protected function showProgressDialog($bInitWithZero = false)
  691.  
  692.  
  693.  
  694.     /**
  695.     *   Hides the progress dialog
  696.     */
  697.     protected function hideProgressDialog()
  698.     {
  699.         $this->arWidgets['dlgProgress']->hide();
  700.         while (Gtk::events_pending()) Gtk::main_iteration();}
  701.     }//protected function hideProgressDialog()
  702.  
  703.  
  704.  
  705.     /**
  706.     *   The user may not close the progress window by hand
  707.     */
  708.     public function deleteProgressWindow()
  709.     {
  710.         return true;
  711.     }//public function deleteProgressWindow()
  712.  
  713.  
  714.  
  715.     /**
  716.     *   Check if the user wants to work offline
  717.     *   @return boolean     True, if the offline setting is active (work offline), false if working online
  718.     */
  719.     protected function getWorkOffline()
  720.     {
  721.         return $this->arWidgets['mnuOffline']->get_active();
  722.     }//protected function getWorkOffline()
  723.  
  724.  
  725.  
  726.     /**
  727.     *   Set the offline setting
  728.     *   @param boolean $bOffline    If the user wants to work offline (true) or not (false)
  729.     */
  730.     protected function setWorkOffline($bOffline)
  731.     {
  732.         return $this->arWidgets['mnuOffline']->set_active($bOffline);
  733.     }//protected function setWorkOffline($bOffline)
  734.  
  735.  
  736.  
  737.     public function getWidget($strWidget)
  738.     {
  739.         return $this->arWidgets[$strWidget];
  740.     }//public function getWidget($strWidget)
  741.  
  742.  
  743.  
  744.     /**
  745.     *   Reload local package information and update the list.
  746.     */
  747.     public function refreshLocalPackages()
  748.     {
  749.         $this->packages->refreshLocalPackages();
  750.         $this->showPackageList($this->strSelectedCategoryName);
  751.     }//public function refreshLocalPackages()
  752.  
  753.  
  754.  
  755.     /**
  756.     *   Reload the online package list and package information,
  757.     *   and update the list here.
  758.     */
  759.     public function refreshOnlinePackages()
  760.     {
  761.         $this->packages->refreshRemotePackages(nullarray($this'packagesCallback'));
  762.         $this->showPackageList($this->strSelectedCategoryName);
  763.     }//public function refreshOnlinePackages()
  764.  
  765.  
  766.  
  767.     /**
  768.     *   Let the user select a .tgz package file that will be installed.
  769.     */
  770.     public function onInstallLocalPackage()
  771.     {
  772.         $fcd = new GtkFileChooserDialog(
  773.             'Select a package file to install',
  774.             $this->arWidgets['dlgInstaller'],
  775.             Gtk::FILE_CHOOSER_ACTION_OPEN,
  776.             array(
  777.                 Gtk::STOCK_CANCELGtk::RESPONSE_NO,
  778.                 Gtk::STOCK_OPENGtk::RESPONSE_YES
  779.             )
  780.         );
  781.         $fcd->set_select_multiple(false);
  782.         if ($this->strLastFile !== null{
  783.             $fcd->set_filename($this->strLastFile);
  784.         }
  785.  
  786.         $ffilter = new GtkFileFilter();
  787.         $ffilter->add_pattern('*.tgz');
  788.         $ffilter->add_pattern('*');
  789.         $fcd->set_filter($ffilter);
  790.  
  791.         if ($fcd->run(== Gtk::RESPONSE_NO{
  792.             $fcd->destroy();
  793.             return;
  794.         }
  795.         $strFile $fcd->get_filename();
  796.         $fcd->destroy();
  797.         if (!file_exists($strFile)) {
  798.             //FIXME: Error message
  799.             return;
  800.         }
  801.  
  802.         $this->installFile($strFile);
  803.     }//public function onInstallLocalPackage()
  804.  
  805.  
  806.  
  807.     /**
  808.     *   Some files have been dropped on the install button
  809.     */
  810.     public function onFilesDropped($widget$arFiles)
  811.     {
  812.         $strFile reset($arFiles);
  813.         $this->installFile($strFile);
  814.     }//public function onFilesDropped($widget, $arFiles)
  815.  
  816.  
  817.  
  818.     /**
  819.     *   Install the given package file
  820.     *
  821.     *   @param string $strFile  File to install
  822.     */
  823.     protected function installFile($strFile)
  824.     {
  825.         //get changes done in gui into config
  826.         PEAR_Frontend_Gtk2_Config::loadConfigurationFromGui($this);
  827.  
  828.         $this->installer->installPackage(
  829.             null,
  830.             $strFile,
  831.             null,
  832.             true,
  833.             PEAR_Frontend_Gtk2_Config::$strDepOptions,
  834.             PEAR_Frontend_Gtk2_Config::$bForceInstall
  835.         );
  836.  
  837.         $this->refreshLocalPackages();
  838.         $this->strLastFile $strFile;
  839.     }//protected function installFile($strFile)
  840.  
  841.  
  842.  
  843.     public function userConfirm()
  844.     {
  845.         //just to make sure that the class is recognized as proper PEAR_Frontend class
  846.     }//public function userConfirm()
  847.  
  848.  
  849.  
  850.     /**
  851.     *   A fatal error occured
  852.     *
  853.     *   @param PEAR_Error $error The error
  854.     */
  855.     public function displayFatalError($error)
  856.     {
  857.         $strMessage $error->getMessage();
  858.  
  859.         //404 occurs often and isn't that bad, so we can ignore it
  860.         //404 occurs, if a package exists but hasn't released a version.
  861.         if (strpos(strtolower($strMessage)'404 not found'=== false{
  862.             $dialog = new GtkMessageDialog(
  863.                 $this->arWidgets['dlgInstaller'],
  864.                 Gtk::DIALOG_MODAL,
  865.                 Gtk::MESSAGE_ERROR,
  866.                 Gtk::BUTTONS_OK,
  867.                 'A fatal error occured:' "\r\n" $strMessage
  868.             );
  869.             $answer $dialog->run();
  870.             $dialog->destroy();
  871.         }
  872.     }//public function displayFatalError($error)
  873.  
  874. }//class PEAR_Frontend_Gtk2
  875. ?>

Documentation generated on Mon, 11 Mar 2019 14:39:43 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.