<?php
if( !extension_loaded('gtk')) {
dl( 'php_gtk.' . PHP_SHLIB_SUFFIX);
}
$fdnd = new FileDragNDrop();
$fdnd->buildDialog();
$fdnd->display();
class FileDragNDrop
{
function buildDialog() {
$this->window =& new GtkWindow();
$this->window->set_title('FileDropper');
$this->window->set_default_size(200, 200);
$this->window->connect_object('destroy', array('gtk', 'main_quit'));
$scrolledwindow =& new GtkScrolledWindow();
$scrolledwindow->set_policy(GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
$this->window->add($scrolledwindow);
$this->tree =& new GtkCTree(3, 0, array('title', 'url', 'local path'));
$scrolledwindow->add($this->tree);
$this->ndToplevel = $this->tree->insert_node(null, null, array('Files', '', ''), 0, null, null, null, null, false, true);
$this->tree->connect('key-press-event', array(&$this, 'keyPressedTree'));
$this->tree->connect( 'drag-data-received', array( &$this, 'dragDataReceived'));
$this->targets = array( array( 'text/uri-list', 0, 0));
$this->tree->drag_dest_set( GTK_DEST_DEFAULT_ALL, $this->targets, GDK_ACTION_COPY | GDK_ACTION_MOVE);
$this->tree->drag_source_set(GDK_BUTTON1_MASK, $this->targets, GDK_ACTION_COPY);
$this->tree->connect('drag-data-get', array(&$this, 'dragDataGet'));
}
function display() {
$this->window->show_all();
gtk::main();
}
function keyPressedTree($tree, $objEvent) {
if ($objEvent->keyval == GDK_KEY_Delete) {
$ar = $tree->selection;
foreach ($ar as $objNode) {
$tree->remove_node($objNode);
}
}
}
function dragDataReceived($tree, $context , $x, $y, $data , $info, $time) {
if (count($tree->selection) != 1) {
$parent = $this->ndToplevel;
} else {
$parent = $tree->selection[0];
}
$strData = $data->data;
$arData = explode("\n", $strData);
foreach ($arData as $strLine) {
$strFile = trim($strLine);
if ($strFile == '') { continue; }
$tree->insert_node($parent, null, array(basename(urldecode($strFile)), $strFile, $this->getPathFromUrilistEntry($strFile)), 0, null, null, null, null, false, true);
}
$tree->columns_autosize();
}
/**
* converts a file path gotten from a text/uri-list
* drop to a usable local filepath
* @param string The line from the uri-list
* @return string The usable local filepath
*/
function getPathFromUrilistEntry($strUriFile)
{
$strUriFile = urldecode($strUriFile);//should be URL-encoded
$bUrl = false;
if (substr($strUriFile, 0, 5) == 'file:')
{ //(maybe buggy) file protocol
if (substr($strUriFile, 0, 17) == 'file://localhost/') {
//correct implementation
$strFile = substr($strUriFile, 16);
} else if (substr($strUriFile, 0, 8) == 'file:///') {
//no hostname, but three slashes - nearly correct
$strFile = substr($strUriFile, 7);
} else if ($strUriFile[5] == '/') {
//theoretically, the hostname should be the first
//but no one implements it
$strUriFile = substr($strUriFile, 5);
for( $n = 1; $n < 5; $n++) {
if ($strUriFile[$n] != '/') { break; }
}
$strUriFile = substr($strUriFile, $n - 1);
if (!file_exists($strUriFile)) {
//perhaps a correct implementation with hostname???
$strUriFileNoHost = strstr(substr($strUriFile, 1), '/');
if (file_exists($strUriFileNoHost)) {
//seems so
$strUriFile = $strUriFileNoHost;
}
}
$strFile = $strUriFile;
} else {
//NO slash after "file:" - what is that for a crappy program?
$strFile = substr ($strUriFile, 5);
}
} else if (strstr($strUriFile, '://')) {
//real protocol, but not file
$strFile = $strUriFile;
$bUrl = true;
} else {
//local file?
$strFile = $strUriFile;
}
if (!$bUrl && $strFile[2] == ':' && $strFile[0] == '/') {
//windows file path
$strFile = str_replace('/', '\\', substr($strFile, 1));
}
return $strFile;
}
function dragDataGet($tree, $context, $selection_data, $info, $time) {
if( count( $tree->selection) < 1) { return false; }
$node = $tree->selection[0];
$file = $tree->node_get_text( $node, 2);
if( $file == '') { return false; }
$selection_data->set($selection_data->target, 8, $this->pathurlencode($this->getUriFromFile($file)) . "\r\n");
}
/**
* converts a file name to a URI
* useful to convert a file to the text/uri-list compatible format
* @param string The file
* @return string The URI
*/
function getUriFromFile($strFile) {
if (strstr($strFile, '://')) {
//real URL
$strUri = $strFile;
} else {
//normal file
if (substr($strFile, 1, 2) == ':\\') {
//windows path c:\programs\bla\blu\file.bli
$strUri = 'file://localhost/' . str_replace('\\', '/', $strFile);
} else {
//should be nice unix file
//@fixme: convert relative names to absolute ones?
$strUri = 'file://localhost' . realpath($strFile);
}
}
return $strUri;
}
function pathurlencode($uri) {
$uri = urlencode($uri);
$uri = str_replace('%3A', ':', $uri);
$uri = str_replace('%2F', '/', $uri);
$uri = str_replace('%26', '&', $uri);
$uri = str_replace('%40', '@', $uri);
$uri = str_replace('%3A', ':', $uri);
$uri = str_replace('%3F', '?', $uri);
return $uri;
}
}
?>
|