/* * This file is part of the KFTPGrabber project * * Copyright (C) 2003-2004 by the KFTPGrabber developers * Copyright (C) 2003-2004 Jernej Kos * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and * NON-INFRINGEMENT. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Steet, Fifth Floor, Boston, * MA 02110-1301, USA. * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. If you * do not wish to do so, delete this exception statement from your * version. If you delete this exception statement from all source * files in the program, then also delete it here. */ #include "browser/treeview.h" #include "browser/view.h" #include "engine/thread.h" #include "misc.h" #include #include #include #include #include using namespace KFTPGrabberBase; namespace KFTPWidgets { namespace Browser { /* * TreeViewItem class */ TreeViewItem::TreeViewItem(TreeView *parent, const KURL &url) : TQListViewItem(parent), m_tree(parent), m_url(url), m_dirty(false) { // Set the name setText(0, path2Name(url.path(-1))); } TreeViewItem::TreeViewItem(TreeView *tree, TQListViewItem *parent, const KURL &url) : TQListViewItem(parent), m_tree(tree), m_url(url), m_dirty(false) { // Set the name setText(0, path2Name(url.path(-1))); } TreeViewItem::~TreeViewItem() { // The item should be removed from the list as well m_tree->m_treeItems.remove(m_url.path()); } int TreeViewItem::compare(TQListViewItem *i, int col, bool) const { // Hidden files must be on top if (m_url.fileName().at(0) == '.') return -1; return TQListViewItem::compare(i, col, false); } /* * TreeView class */ TreeView::TreeView(TQWidget *parent) : TDEListView(parent) { // Create the columns addColumn(i18n("Directory")); // General tree settings setDragEnabled(true); setAcceptDrops(true); setMinimumWidth(150); setRootIsDecorated(false); header()->hide(); // Reset the view resetView(KURL("/")); m_noItemOpen = false; // Connect signals connect(this, SIGNAL(clicked(TQListViewItem*)), this, SLOT(slotClicked(TQListViewItem*))); connect(this, SIGNAL(doubleClicked(TQListViewItem*)), this, SLOT(slotDoubleClicked(TQListViewItem*))); // Drag and drop m_dropItem = 0L; } TreeView::~TreeView() { // Free the item index m_treeItems.clear(); } void TreeView::resetView(const KURL &url) { // Free the item index m_treeItems.clear(); // Clear the view clear(); header()->resizeSection(0, 0); // Create the root item TreeViewItem *rootItem = new TreeViewItem(this, remoteUrl("/", url)); rootItem->setText(0, url.isLocalFile() ? i18n("Root directory") : url.host()); rootItem->setPixmap(0, loadSmallPixmap("folder_red")); setOpen(rootItem, true); } int TreeView::openUrl(const KURL &url, TQListViewItem *parent) { // Root item should always be open setOpen(firstChild(), true); // Go trough all items in the list and try to find the url TQListViewItem *item; if (!parent) item = firstChild(); else item = parent; while (item) { // Check if the item is correct if (static_cast(item)->m_url.path(-1) == url.path(-1)) { // We have found it ensureItemVisible(item); setCurrentItem(item); setSelected(item, true); // Change viewport TQRect r = itemRect(item); if (r.isValid()) { int x, y; viewportToContents(contentsX(), r.y(), x, y); setContentsPos(x, y); } return 1; } if (item->firstChild()) { // If item has children, go after them if (openUrl(url, item->firstChild()) == 1) return 1; } item = item->nextSibling(); } return 0; } TQListViewItem *TreeView::findItem(TQListViewItem *parent, const TQString &name) { TQListViewItem *item = parent->firstChild(); while (item) { if (item->text(0) == name) return item; item = item->nextSibling(); } // If nothing is found, parent should be returned return parent; } void TreeView::createFolder(const KURL &url, TQPixmap icon) { int numDirs = url.path(1).contains('/', false); TQListViewItem *item = firstChild(); for (int i = 1; i < numDirs; i++) { TQString itemUrl = url.path().section('/', 0, i); if (m_treeItems[itemUrl]) { // Item exists for this URL item = m_treeItems[itemUrl]; } else { // Item not yet created KURL tmp = url; tmp.setPath(itemUrl); item = new TreeViewItem(this, item, tmp); if (i == numDirs - 1) item->setPixmap(0, icon); else item->setPixmap(0, loadSmallPixmap("folder")); m_treeItems.insert(itemUrl, static_cast(item)); } // Mark it as dirty static_cast(item)->m_dirty = true; // Open it if (!m_noItemOpen) setOpen(item, true); } // Root item should always be open setOpen(firstChild(), true); } void TreeView::endUpdate(const KURL &url) { // Remove all items in the selected dir, not marked as dirty TreeViewItem *top = static_cast(firstChild()); TreeViewItem *tmp = 0L; int numDirs = url.path(1).contains('/', false); if (url.path() == "/") { TreeViewItem *i = static_cast(top->firstChild()); while (i) { tmp = static_cast(i->nextSibling()); if (!i->m_dirty) { // Remove item from the index delete i; } else { i->m_dirty = false; } i = tmp; } return; } // URL for items KURL itemURL = url; itemURL.setPath("/"); for (int i = 1; i < numDirs; i++) { TQString sect = url.path().section('/', i, i); itemURL.setPath(url.path().section('/', 0, i)); if (!m_treeItems[itemURL.path()]) { // Item not yet created return; } else { // Item is already present top = m_treeItems[itemURL.path()]; // Check for URL match if (itemURL.path(-1) == url.path(-1)) { // URL match, delete the item's children TreeViewItem *i = static_cast(top->firstChild()); while (i) { tmp = static_cast(i->nextSibling()); if (!i->m_dirty) { // Remove item from the index delete i; } else { i->m_dirty = false; } i = tmp; } return; } } } } void TreeView::clearFolder(const KURL &url) { // Remove url's children TQListViewItem *top = firstChild(); int numDirs = url.path(1).contains('/', false); if (url.path() == "/") { TQListViewItem *i = top->firstChild(); while (i) { // Remove item from the index delete i; i = top->firstChild(); } return; } // URL for items KURL itemURL = url; itemURL.setPath("/"); for (int i = 1; i < numDirs; i++) { TQString sect = url.path().section('/', i, i); itemURL.setPath(url.path().section('/', 0, i)); if (!m_treeItems[itemURL.path()]) { // Item not yet created return; } else { // Item is already present top = m_treeItems[itemURL.path()]; // Check for URL match if (itemURL.path(-1) == url.path(-1)) { // URL match, delete the item's children TQListViewItem *i = top->firstChild(); while (i) { // Remove item from the index delete i; i = top->firstChild(); } return; } } } } void TreeView::removeFolder(const KURL &url) { // Removes a folder at url TQListViewItem *top = firstChild(); int numDirs = url.path(1).contains('/', false); // URL for items KURL itemURL = url; itemURL.setPath("/"); for (int i = 1; i < numDirs; i++) { TQString sect = url.path().section('/', i, i); itemURL.setPath(url.path().section('/', 0, i)); if (!m_treeItems[itemURL.path()]) { // Item not yet created return; } else { // Item is already present top = m_treeItems[itemURL.path()]; // Check for URL match if (itemURL.path(-1) == url.path(-1)) { // Remove item from the index delete top; return; } } } } void TreeView::slotClicked(TQListViewItem *item) { if (!item) return; m_noItemOpen = true; emit pathChanged(static_cast(item)->m_url); m_noItemOpen = false; } void TreeView::slotDoubleClicked(TQListViewItem *item) { if (!item) return; setOpen(item, !item->isOpen()); } void TreeView::startDrag() { dragObject()->drag(); } bool TreeView::acceptDrag(TQDropEvent *e) { return KURLDrag::canDecode(e) && ( e->action() == TQDropEvent::Copy || e->action() == TQDropEvent::Move || e->action() == TQDropEvent::Link ) && acceptDrops() && dragEnabled(); } TQDragObject *TreeView::dragObject() { TreeViewItem *item = static_cast(selectedItem()); // Set the correct pixmap TQPixmap pix = *item->pixmap(0); KURL::List urls; urls.append(item->m_url); TDEIO::MetaData meta; meta.insert(item->m_url.htmlURL().local8Bit(), "D:0"); m_dragObject = new KURLDrag(urls, meta, this, name()); m_dragObject->setPixmap(pix, TQPoint(pix.width() / 2, pix.height() / 2)); return m_dragObject; } void TreeView::contentsDragEnterEvent(TQDragEnterEvent *e) { if (!acceptDrag(e)) { e->accept(false); return; } e->acceptAction(); TQListViewItem *i = itemAt(contentsToViewport(e->pos())); if (i) m_dropItem = i; } void TreeView::contentsDragMoveEvent(TQDragMoveEvent *e) { if (!acceptDrag(e)) { e->accept(false); return; } e->acceptAction(); TQListViewItem *i = itemAt(contentsToViewport(e->pos())); if (i && i != m_dropItem) m_dropItem = i; } void TreeView::contentsDragLeaveEvent(TQDragLeaveEvent*) { m_dropItem = 0L; } void TreeView::contentsDropEvent(TQDropEvent *e) { if (!m_dropItem) return; if (!acceptDrag(e)) { e->acceptAction(false); return; } e->acceptAction(); // Decode the data and try to init transfer TDEIO::MetaData meta; KURL::List urls; KURLDrag::decode(e, urls, meta); // Move the specified file(s) for (KURL::List::iterator i = urls.begin(); i != urls.end(); ++i) { KURL destUrl = static_cast(m_dropItem)->m_url; if (destUrl != (*i)) { if (destUrl.isLocalFile() != (*i).isLocalFile()) { // TODO Queue up a transfer } else { // Rename/move the file destUrl.addPath((*i).fileName()); if ((*i).isLocalFile()) { TDEIO::move((*i), destUrl, false); // Reload the listing static_cast(parent()->parent())->reload(); } else { static_cast(parent()->parent())->m_ftpClient->rename((*i), destUrl); } } } } // Invalidate the drop item m_dropItem = 0L; } } } #include "treeview.moc"