<?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; } } ?> |