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

Source for file FileDrop.php

Documentation is available at FileDrop.php

  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  3. // +----------------------------------------------------------------------+
  4. // | PHP version 4                                                        |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2004 The PHP Group                                |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 3.0 of the PHP license,       |
  9. // | that is bundled with this package in the file LICENSE, and is        |
  10. // | available through the world-wide-web at the following url:           |
  11. // | http://www.php.net/license/3_0.txt.                                  |
  12. // | If you did not receive a copy of the PHP license and are unable to   |
  13. // | obtain it through the world-wide-web, please send a note to          |
  14. // | license@php.net so we can mail you a copy immediately.               |
  15. // +----------------------------------------------------------------------+
  16. // | Authors: Christian Weiske <cweiske@php.net>                          |
  17. // +----------------------------------------------------------------------+
  18. //
  19. // $Id: FileDrop.php,v 1.3 2006/05/16 10:25:01 cweiske Exp $
  20.  
  21. require_once 'MIME/Type.php';
  22. require_once 'PEAR.php';
  23.  
  24. /**
  25. *   A class which makes it easy to
  26. *   make a GtkWidget accept the dropping
  27. *   of files or folders
  28. *
  29. *   @author Christian Weiske <cweiske@php.net>
  30. *   @package Gtk2
  31. *
  32. *   @date 2006-05-16
  33. *   @license PHP
  34. *
  35. *   @todo
  36. *    - reject files when moving the dragging mouse over the widget, just like opera does
  37. *        how does this work? I don't know, but I suppose I should
  38. *
  39. *   @example
  40. *    Usage:
  41. *    Simply change the text of a widget
  42. *    (accept files with MIME-Types text/plain and text/html and files with .sgml extension):
  43. *        Gtk2_FileDrop::attach($entry, array('text/plain', 'text/html', '.sgml'));
  44. *    Call a callback, and don't change the text (accept directories only):
  45. *        Gtk2_FileDrop::attach($entry, array( 'inode/directory'), array( $this, 'callback'), false);
  46. */
  47. {
  48.     /**
  49.     * A FileDrop error code.
  50.     * returned if the widget doesn't support drops
  51.     */
  52.     const WIDGET_NOT_SUPPORTED = 1;
  53.  
  54.  
  55.  
  56.     /**
  57.     *   Prepares a widget to accept file drops.
  58.     *
  59.     *   @static
  60.     *   @param GtkWidget    The widget which shall accept files
  61.     *   @param array        List of MIME-Types to accept OR extensions, beginning with a dot "."
  62.     *   @param mixed        Callback to call when a drop with valid files happened
  63.     *   @param boolean      If the widget's text/label/content shall be changed automatically
  64.     *
  65.     *   @return boolean     If all was ok
  66.     */
  67.     static function attach($widget$arTypes$objCallback = null$bSetText = true)
  68.     {
  69.         $widget->drag_dest_set(Gtk::DEST_DEFAULT_ALLarray(array('text/uri-list'00))Gdk::ACTION_COPY | Gdk::ACTION_MOVE);
  70.  
  71.         $fd = new Gtk2_FileDrop$arTypes$objCallback$bSetText);
  72.         $widget->connect('drag-data-received'array($fd'dragDataReceived'));
  73.  
  74.         return true;
  75.     }//static function attach($widget, $arTypes, $objCallback = null, $bSetText = true)
  76.  
  77.  
  78.  
  79.     /**
  80.     *   Use attach() instead.
  81.     *
  82.     *   @access private
  83.     */
  84.     private function Gtk2_FileDrop$arTypes$objCallback = null$bSetText = true)
  85.     {
  86.         $this->arTypes     $arTypes;
  87.         $this->objCallback $objCallback;
  88.         $this->bSetText    $bSetText;
  89.     }//private function Gtk2_FileDrop( $arTypes, $objCallback = null, $bSetText = true)
  90.  
  91.  
  92.  
  93.     /**
  94.     *   Prepares a widget to accept directories only.
  95.     *   Just a shortcut for the exhausted programmer.
  96.     *
  97.     *   @static
  98.     *   @param GtkWidget    The widget which shall accept directories
  99.     *
  100.     *   @return boolean     If all was ok
  101.     */
  102.     static function attachDirectory($widget)
  103.     {
  104.         return self::attach($widgetarray('inode/directory'));
  105.     }//static function attachDirectory($widget)
  106.  
  107.  
  108.  
  109.     /**
  110.     *   Data have been dropped over the widget.
  111.     *
  112.     *   @param GtkWidget      The widget on which the data have been dropped
  113.     *   @param GdkDragContext The context of the drop
  114.     *   @param int            X position
  115.     *   @param int            Y position
  116.     *   @param int            Info parameter (0 in our case)
  117.     *   @param int            The time on which the event happened
  118.     */
  119.     function dragDataReceived($widget$context $x$y$data $info$time)
  120.     {
  121.         $arData     explode("\n"$data->data);
  122.         $arAccepted = array();
  123.         $arRejected = array();
  124.         $bDirectories = false;
  125.         foreach ($arData as $strLine{
  126.             $strLine trim($strLine);
  127.             if ($strLine == ''
  128.                 continue; 
  129.             }
  130.             $strFile     = self::getPathFromUrilistEntry($strLine);
  131.             $strFileMime = self::getMimeType($strFile);
  132.             $bAccepted   = false;
  133.             foreach ($this->arTypes as $strType{
  134.                 if ($strType == 'inode/directory'
  135.                     $bDirectories = true; 
  136.                 }
  137.                 if (($strType[0== '.' && self::getFileExtension($strFile== $strType)
  138.                  || $strType == $strFileMime
  139.                  || (strpos($strType'/'!== false && MIME_Type::wildcardMatch($strType$strFileMime))
  140.                 {
  141.                     $arAccepted[$strFile;
  142.                     $bAccepted    = true;
  143.                     break;
  144.                 }
  145.             }//foreach type
  146.             if (!$bAccepted{
  147.                 $arRejected[$strFile;
  148.             }
  149.         }//foreach line
  150.  
  151.         //make directories from the files if dirs are accepted
  152.         //this is done here to give native directories first places on the list
  153.         if ($bDirectories && count($arRejected> 0{
  154.             foreach ($arRejected as $strFile{
  155.                 $arAccepted[dirname$strFile);
  156.             }
  157.         }
  158.  
  159.         if (count($arAccepted== 0{
  160.             //no matching files
  161.             return;
  162.         }
  163.  
  164.         if ($this->bSetText{
  165.             $strClass get_class($widget);
  166.             switch ($strClass{
  167.             case 'GtkEntry':
  168.             case 'GtkLabel':
  169.                 $widget->set_text($arAccepted[0]);
  170.                 break;
  171.             case 'GtkButton':
  172.             case 'GtkToggleButton':
  173.             case 'GtkCheckButton':
  174.             case 'GtkRadioButton':
  175.                 $childs $widget->get_children();
  176.                 $child $childs[0];
  177.                 if (get_class($child== 'GtkLabel'{
  178.                     $child->set_text($arAccepted[0]);
  179.                 else {
  180.                     trigger_error('No label found on widget.');
  181.                 }
  182.                 break;
  183.             case 'GtkCombo':
  184.                 $entry $widget->entry;
  185.                 $entry->set_text($arAccepted[0]);
  186.                 break;
  187.             case 'GtkFileSelection':
  188.                 $widget->set_filename($arAccepted[0]);
  189.                 break;
  190.             case 'GtkList':
  191.                 foreach ($arAccepted as $strFile{
  192.                     $items[= new GtkListItem($strFile);
  193.                 }
  194.                 $widget->append_items($items);
  195.                 $widget->show_all();
  196.                 break;
  197.             default:
  198.                 PEAR::raiseError'Widget class "' $strClass '" is not supported'self::WIDGET_NOT_SUPPORTEDPEAR_ERROR_TRIGGERE_USER_WARNING);
  199.                 break;
  200.             }
  201.         }//if bSetText
  202.  
  203.         if ($this->objCallback !== null{
  204.             call_user_func$this->objCallback$widget$arAccepted);
  205.         }//objCallback !== null
  206.     }//function dragDataReceived($widget, $context , $x, $y, $data , $info, $time)
  207.  
  208.  
  209.  
  210.     /**
  211.     *   Converts a file path gotten from a text/uri-list
  212.     *   drop to a usable local filepath.
  213.     *
  214.     *   Php functions like parse_url can't be used as it is
  215.     *   likely that the dropped URI is no real URI but a
  216.     *   strange thing which tries to look like one
  217.     *   See the explanation at:
  218.     *   http://gtk.php.net/manual/en/tutorials.filednd.urilist.php
  219.     *
  220.     *   @static
  221.     *   @param  string  The line from the uri-list
  222.     *   @return string  The usable local filepath
  223.     */
  224.     static function getPathFromUrilistEntry($strUriFile)
  225.     {
  226.         $strUriFile urldecode($strUriFile);//should be URL-encoded
  227.         $bUrl = false;
  228.         if (substr($strUriFile05== 'file:'{
  229.             //(maybe buggy) file protocol
  230.             if (substr($strUriFile017== 'file://localhost/'{
  231.                 //correct implementation
  232.                 $strFile substr($strUriFile16);
  233.             else if (substr($strUriFile08== 'file:///'{
  234.                 //no hostname, but three slashes - nearly correct
  235.                 $strFile substr($strUriFile7);
  236.             else if ($strUriFile[5== '/'{
  237.                 //theoretically, the hostname should be the first
  238.                 //but no one implements it
  239.                 $strUriFile substr($strUriFile5);
  240.                 for$n = 1; $n < 5; $n++{
  241.                     if ($strUriFile[$n!= '/'
  242.                         break; 
  243.                     }
  244.                 }
  245.                 $strUriFile substr($strUriFile$n - 1);
  246.                 if (!file_exists($strUriFile)) {
  247.                     //perhaps a correct implementation with hostname???
  248.                     $strUriFileNoHost strstr(substr($strUriFile1)'/');
  249.                     if (file_exists($strUriFileNoHost)) {
  250.                         //seems so
  251.                         $strUriFile $strUriFileNoHost;
  252.                     }
  253.                 }
  254.                 $strFile $strUriFile;
  255.             else {
  256.                 //NO slash after "file:" - what is that for a crappy program?
  257.                 $strFile substr ($strUriFile5);
  258.             }
  259.         else if (strstr($strUriFile'://')) {
  260.             //real protocol, but not file
  261.             $strFile $strUriFile;
  262.             $bUrl    = true;
  263.         else {
  264.             //local file?
  265.             $strFile $strUriFile;
  266.         }
  267.         if (!$bUrl && $strFile[2== ':' && $strFile[0== '/'{
  268.             //windows file path
  269.             $strFile str_replace('/''\\'substr($strFile1));
  270.         }
  271.         return $strFile;
  272.     }//static function getPathFromUrilistEntry($strUriFile)
  273.  
  274.  
  275.  
  276.     /**
  277.     *   Returns the extension if a filename
  278.     *   including the leading dot.
  279.     *
  280.     *   @static
  281.     *   @param  string  The filename
  282.     *   @return string  The extension with a leading dot
  283.     */
  284.     static function getFileExtension($strFile)
  285.     {
  286.         $strExt strrchr($strFile'.');
  287.         if ($strExt == false
  288.             return '';
  289.         }
  290.         $strExt str_replace('\\''/'$strExt);
  291.         if (strpos($strExt'/'!== false{
  292.             return '';
  293.         }
  294.         return $strExt;
  295.     }//static function getFileExtension($strFile)
  296.  
  297.  
  298.  
  299.     /**
  300.     *   Determines the mime-type for the given file.
  301.     *
  302.     *   @static
  303.     *   @param  string  The file name
  304.     *   @return string  The MIME type or FALSE in the case of an error
  305.     */
  306.     static function getMimeType($strFile)
  307.     {
  308.         //MIME_Type doesn't return the right type for directories
  309.         //The underlying functions MIME_Type used don't return it right, 
  310.         //so there is no chance to fix MIME_Type itself
  311.         if ((file_exists($strFile&& is_dir($strFile))
  312.           || substr($strFile-1== '/'{
  313.             return 'inode/directory';
  314.         }
  315.         $strMime = MIME_Type::autoDetect($strFile);
  316.         if (!PEAR::isError($strMime)) {
  317.             return $strMime;
  318.         }
  319.  
  320.         //determine by extension | as MIME_TYPE doesn't support this, I have to do this myself
  321.         $strExtension = self::getFileExtension($strFile);
  322.         switch ($strExtension{
  323.             case '.txt' :
  324.                 $strType 'text/plain';
  325.                 break;
  326.             case '.gif' :
  327.                 $strType 'image/gif';
  328.                 break;
  329.             case '.jpg' :
  330.             case '.jpeg':
  331.                 $strType 'image/jpg';
  332.                 break;
  333.             case '.png' :
  334.                 $strType 'image/png';
  335.                 break;
  336.             case '.xml' :
  337.                 $strType 'text/xml';
  338.                 break;
  339.             case '.htm' :
  340.             case '.html':
  341.                 $strType 'text/html';
  342.                 break;
  343.             default:
  344.                 $strType = false;
  345.                 break;
  346.         }
  347.         return $strType;
  348.     }//static function getMimeType($strFile)
  349.  
  350. }//class Gtk2_FileDrop
  351. ?>

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