summaryrefslogtreecommitdiffstats
path: root/kftpgrabber/src/widgets/browser/detailsview.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kftpgrabber/src/widgets/browser/detailsview.cpp')
-rw-r--r--kftpgrabber/src/widgets/browser/detailsview.cpp596
1 files changed, 596 insertions, 0 deletions
diff --git a/kftpgrabber/src/widgets/browser/detailsview.cpp b/kftpgrabber/src/widgets/browser/detailsview.cpp
new file mode 100644
index 0000000..5206d3d
--- /dev/null
+++ b/kftpgrabber/src/widgets/browser/detailsview.cpp
@@ -0,0 +1,596 @@
+/*
+ * This file is part of the KFTPGrabber project
+ *
+ * Copyright (C) 2003-2006 by the KFTPGrabber developers
+ * Copyright (C) 2003-2006 Jernej Kos <kostko@jweb-network.net>
+ *
+ * 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/detailsview.h"
+#include "browser/treeview.h"
+#include "browser/view.h"
+#include "browser/locationnavigator.h"
+#include "browser/dirlister.h"
+#include "browser/actions.h"
+
+#include "misc/config.h"
+#include "misc/kftpapi.h"
+#include "misc/filter.h"
+
+#include "kftpqueue.h"
+
+#include <qheader.h>
+#include <qpainter.h>
+
+#include <kpopupmenu.h>
+#include <kurldrag.h>
+
+using namespace KFTPCore::Filter;
+
+namespace KFTPWidgets {
+
+namespace Browser {
+
+DetailsView::DetailsView(QWidget *parent, View *view, KFTPSession::Session *session)
+ : KFileDetailView(parent, 0),
+ m_view(view),
+ m_treeView(0),
+ m_refreshing(false),
+ m_shouldDisableResize(true),
+ m_autoResizeEnabled(true)
+{
+ m_resizeTimer = new QTimer(this);
+ connect(m_resizeTimer, SIGNAL(timeout()), this, SLOT(updateColumnWidths()));
+
+ m_dirLister = new DirLister(this);
+ m_dirLister->setSession(session);
+
+ connect(m_dirLister, SIGNAL(clear()), this, SLOT(slotClear()));
+ connect(m_dirLister, SIGNAL(completed()), this, SLOT(slotCompleted()));
+ connect(m_dirLister, SIGNAL(deleteItem(KFileItem*)), this, SLOT(slotDeleteItem(KFileItem*)));
+ connect(m_dirLister, SIGNAL(refreshItems()), this, SLOT(slotRefreshItems()));
+ connect(m_dirLister, SIGNAL(siteChanged(const KURL&)), this, SLOT(slotSiteChanged(const KURL&)));
+
+ m_navigator = new LocationNavigator(this);
+
+ connect(m_navigator, SIGNAL(urlChanged(const KURL&)), this, SLOT(slotUrlChanged(const KURL&)));
+
+ connect(this, SIGNAL(executed(QListViewItem*)), this, SLOT(slotItemExecuted()));
+ connect(this, SIGNAL(returnPressed(QListViewItem*)), this, SLOT(slotItemExecuted()));
+ connect(this, SIGNAL(contextMenu(KListView*, QListViewItem*, const QPoint&)), this, SLOT(slotContextMenu(KListView*, QListViewItem*, const QPoint&)));
+ connect(this, SIGNAL(itemRenamed(QListViewItem*, const QString&, int)), this, SLOT(slotItemRenamed(QListViewItem*, const QString&)));
+
+ // Setup the header
+ QHeader *viewHeader = header();
+ viewHeader->setResizeEnabled(true);
+ viewHeader->setMovingEnabled(false);
+
+ connect(viewHeader, SIGNAL(sizeChange(int, int, int)), this, SLOT(slotHeaderResized(int)));
+
+ // Set column width
+ setColumnWidthMode(NameColumn, QListView::Manual);
+ setColumnWidthMode(SizeColumn, QListView::Manual);
+ setColumnWidthMode(DateColumn, QListView::Manual);
+ setColumnWidthMode(PermissionsColumn, QListView::Manual);
+
+ // Set column alignments
+ setColumnAlignment(SizeColumn, Qt::AlignRight);
+ setColumnAlignment(DateColumn, Qt::AlignHCenter);
+ setColumnAlignment(PermissionsColumn, Qt::AlignHCenter);
+
+ if (KFTPCore::Config::showOwnerGroup()) {
+ setColumnAlignment(OwnerColumn, Qt::AlignHCenter);
+ setColumnAlignment(GroupColumn, Qt::AlignHCenter);
+ } else {
+ // Only show owner/group if set in the config
+ removeColumn(4);
+ removeColumn(4);
+ }
+
+ setColumnWidth(NameColumn, 140);
+ setColumnWidth(DateColumn, 100);
+
+ setAcceptDrops(true);
+ setSelectionMode(KFile::Extended);
+ setHScrollBarMode(QScrollView::AlwaysOff);
+
+ // Set the defaults
+ setHomeUrl(KURL(KFTPCore::Config::defLocalDir()));
+ setShowHidden(KFTPCore::Config::showHiddenFiles());
+}
+
+DetailsView::~DetailsView()
+{
+}
+
+const KURL &DetailsView::url() const
+{
+ return m_navigator->url();
+}
+
+const QValueList<LocationNavigator::Element> DetailsView::history(int &index) const
+{
+ return m_navigator->history(index);
+}
+
+bool DetailsView::isSelected(const KFileItem *i) const
+{
+ if (!i)
+ return false;
+
+ const KFileListViewItem *item = static_cast<const KFileListViewItem*>(i->extraData(this));
+ return (item && item->isSelected() && item->isVisible());
+}
+
+void DetailsView::setTreeView(TreeView *tree)
+{
+ m_treeView = tree;
+
+ connect(m_treeView, SIGNAL(pathChanged(const KURL&)), this, SLOT(openUrl(const KURL&)));
+}
+
+void DetailsView::setHomeUrl(const KURL &url)
+{
+ m_navigator->setHomeUrl(url);
+}
+
+void DetailsView::goBack()
+{
+ m_navigator->goBack();
+}
+
+void DetailsView::goForward()
+{
+ m_navigator->goForward();
+}
+
+void DetailsView::goUp()
+{
+ m_navigator->goUp();
+}
+
+void DetailsView::goHome()
+{
+ m_navigator->goHome();
+}
+
+void DetailsView::endItemUpdates()
+{
+ const KFileListViewItem *item = static_cast<const KFileListViewItem*>(firstChild());
+ if (item)
+ setCurrentItem(item->fileInfo());
+
+ int index = 0;
+ const QValueList<LocationNavigator::Element> history = m_navigator->history(index);
+ if (!history.isEmpty()) {
+ KFileView::setCurrentItem(history[index].currentFilename());
+ KFileDetailView::setSelected(currentFileItem(), true);
+
+ // Scroll the contents to last known coordinates
+ setContentsPos(history[index].contentsX(), history[index].contentsY());
+ }
+
+ m_treeView->openUrl(m_navigator->url());
+ m_treeView->endUpdate(m_navigator->url());
+ setFocus();
+}
+
+void DetailsView::openUrl(const KURL &url)
+{
+ m_navigator->setUrl(url);
+}
+
+void DetailsView::slotClear()
+{
+ clearView();
+}
+
+void DetailsView::slotDeleteItem(KFileItem *item)
+{
+ removeItem(item);
+
+ if (item->isDir())
+ m_treeView->removeFolder(item->url());
+}
+
+void DetailsView::slotCompleted()
+{
+ m_refreshing = true;
+
+ clearView();
+
+ KFileItemList items(m_dirLister->items());
+ KFileItemListIterator i(items);
+
+ KFileItem *item = 0;
+ while ((item = i.current()) != 0) {
+ insertItem(item);
+
+ if (item->isDir())
+ m_treeView->createFolder(item->url(), item->pixmap(16));
+
+ ++i;
+ }
+
+ endItemUpdates();
+ m_refreshing = false;
+
+ m_view->updateActions();
+}
+
+void DetailsView::slotRefreshItems()
+{
+ QTimer::singleShot(0, this, SLOT(reload()));
+}
+
+void DetailsView::reload()
+{
+ fetchLocation(m_navigator->url(), true);
+}
+
+void DetailsView::slotUrlChanged(const KURL &url)
+{
+ fetchLocation(url);
+}
+
+void DetailsView::slotSiteChanged(const KURL &url)
+{
+ m_navigator->clear();
+ m_treeView->resetView(url);
+}
+
+void DetailsView::fetchLocation(const KURL &url, bool reload)
+{
+ m_dirLister->setShowingDotFiles(m_showHidden);
+ m_dirLister->fetchLocation(url, reload);
+}
+
+void DetailsView::slotContentsMoving(int x, int y)
+{
+ if (!m_refreshing)
+ emit contentsMoved(x, y);
+}
+
+void DetailsView::slotItemExecuted()
+{
+ KFileItem *item = currentFileItem();
+
+ if (item) {
+ if (item->isDir())
+ openUrl(item->url());
+ }
+}
+
+void DetailsView::slotHeaderResized(int section)
+{
+ if (m_autoResizeEnabled && m_shouldDisableResize && section == 0) {
+ setHScrollBarMode(QScrollView::Auto);
+ m_autoResizeEnabled = false;
+ }
+}
+
+void DetailsView::resizeContents(int width, int height)
+{
+ m_shouldDisableResize = false;
+
+ KFileDetailView::resizeContents(width, height);
+
+ // Update the column widths
+ if (m_autoResizeEnabled) {
+ m_resizeTimer->stop();
+ m_resizeTimer->start(50, true);
+ }
+}
+
+void DetailsView::resizeEvent(QResizeEvent *event)
+{
+ m_shouldDisableResize = false;
+
+ KFileDetailView::resizeEvent(event);
+
+ // Update the column widths
+ if (m_autoResizeEnabled) {
+ m_resizeTimer->stop();
+ m_resizeTimer->start(50, true);
+ }
+}
+
+void DetailsView::updateColumnWidths()
+{
+ // The code below is based on Dolphin, Copyright (C) 2006 by Peter Penz
+ const int columnCount = columns();
+ int requiredWidth = 0;
+
+ for (int i = 1; i < columnCount; ++i) {
+ // When a directory contains no items, a minimum width for
+ // the column must be available, so that the header is readable.
+ int columnWidth = 64;
+ QFontMetrics fontMetrics(font());
+
+ for (QListViewItem* item = firstChild(); item != 0; item = item->nextSibling()) {
+ const int width = item->width(fontMetrics, this, i);
+
+ if (width > columnWidth) {
+ columnWidth = width;
+ }
+ }
+
+ // Add custom margin
+ columnWidth += 16;
+ setColumnWidth(i, columnWidth);
+ requiredWidth += columnWidth;
+ }
+
+ // Resize the first column in a way that the whole available width is used
+ int firstColumnWidth = visibleWidth() - requiredWidth;
+ if (firstColumnWidth < 128) {
+ firstColumnWidth = 128;
+ }
+
+ setColumnWidth(0, firstColumnWidth);
+ m_shouldDisableResize = true;
+}
+
+void DetailsView::insertItem(KFileItem *fileItem)
+{
+ const ActionChain *actionChain = Filters::self()->process(fileItem->url(), fileItem->size(), fileItem->isDir());
+ const Action *action;
+
+ if ((actionChain && actionChain->getAction(Action::Hide)))
+ return;
+
+ KFileView::insertItem(fileItem);
+
+ ListViewItem *item = new ListViewItem(this, fileItem);
+
+ if (actionChain && (action = actionChain->getAction(Action::Colorize)))
+ item->setColor(action->value().toColor());
+
+ QDir::SortSpec spec = KFileView::sorting();
+ if (spec & QDir::Time) {
+ item->setKey(sortingKey(fileItem->time(KIO::UDS_MODIFICATION_TIME), fileItem->isDir(), spec));
+ } else if (spec & QDir::Size) {
+ item->setKey(sortingKey(fileItem->size(), fileItem->isDir(), spec));
+ } else {
+ item->setKey(sortingKey(fileItem->text(), fileItem->isDir(), spec));
+ }
+
+ fileItem->setExtraData(this, item);
+}
+
+void DetailsView::slotContextMenu(KListView*, QListViewItem *i, const QPoint &p)
+{
+ m_view->updateActions();
+
+ // Create the popup menu
+ KPopupMenu *menu = new KPopupMenu(this);
+
+ Actions *actions = m_view->m_actions;
+
+ // Always show create directory
+ actions->m_createDirAction->plug(menu);
+ menu->insertSeparator();
+
+ // If nothing is selected, show the navigation menus
+ if (!i) {
+ actions->m_goUpAction->plug(menu);
+ actions->m_goBackAction->plug(menu);
+ actions->m_goForwardAction->plug(menu);
+ actions->m_reloadAction->plug(menu);
+ } else {
+ actions->m_transferAction->plug(menu);
+ actions->m_queueTransferAction->plug(menu);
+ actions->m_renameAction->plug(menu);
+ actions->m_deleteAction->plug(menu);
+ actions->m_shredAction->plug(menu);
+ actions->m_fileEditAction->plug(menu);
+ actions->m_verifyAction->plug(menu);
+ menu->insertSeparator();
+ actions->m_copyAction->plug(menu);
+ actions->m_pasteAction->plug(menu);
+ menu->insertSeparator();
+ actions->m_filterActions->plug(menu);
+ }
+
+ // Always show properties
+ menu->insertSeparator();
+ actions->m_propsAction->plug(menu);
+
+ menu->exec(p);
+}
+
+void DetailsView::slotItemRenamed(QListViewItem *item, const QString &name)
+{
+ KFileItem *fileItem = static_cast<KFileListViewItem*>(item)->fileInfo();
+ m_view->rename(fileItem->url(), name);
+}
+
+QDragObject *DetailsView::dragObject()
+{
+ KURLDrag *object = static_cast<KURLDrag*>(KFileDetailView::dragObject());
+
+ // Add some metadata
+ const KFileItemList *list = KFileView::selectedItems();
+
+ if (list) {
+ KFileItemListIterator i(*list);
+ KFileItem *item;
+
+ while ((item = i.current()) != 0) {
+ QString type = item->isDir() ? "D" : "F";
+ object->metaData().insert(item->url().htmlURL().local8Bit(), type + ":" + KIO::number(item->size()));
+ ++i;
+ }
+ }
+
+ return object;
+}
+
+bool DetailsView::acceptDrag(QDropEvent *event) const
+{
+ return KURLDrag::canDecode(event) &&
+ (event->action() == QDropEvent::Copy ||
+ event->action() == QDropEvent::Move ||
+ event->action() == QDropEvent::Link) &&
+ event->source() != this;
+}
+
+void DetailsView::contentsDropEvent(QDropEvent *event)
+{
+ if (!acceptDrag(event))
+ return;
+
+ KIO::MetaData meta;
+ KURL::List urls;
+ KURLDrag::decode(event, urls, meta);
+
+ meta.insert("DestURL", url().url());
+ KFTPQueue::Manager::self()->insertTransfer(new KURLDrag(urls, meta, this, name()));
+}
+
+KFileItem *DetailsView::fileItem(const QString &filename)
+{
+ if (!filename.isNull()) {
+ KFileItem *item;
+
+ for (item = firstFileItem(); item; item = nextItem(item)) {
+ if (item->name() == filename)
+ return item;
+ }
+ }
+
+ return 0;
+}
+
+void DetailsView::setItemVisibility(KFileItem *item, int visibility)
+{
+ ListViewItem *i = static_cast<ListViewItem*>(item->extraData(this));
+
+ if (i) {
+ if (visibility != 0 && visibility != 1)
+ visibility = !i->isVisible();
+
+ i->setVisible(visibility);
+ }
+}
+
+void DetailsView::setItemColor(KFileItem *item, const QColor &text, const QColor &background)
+{
+ ListViewItem *i = static_cast<ListViewItem*>(item->extraData(this));
+
+ if (i) {
+ i->setColor(text);
+ i->setBackground(background);
+ i->repaint();
+ }
+}
+
+void DetailsView::markItem(KFileItem *item)
+{
+ ListViewItem *i = static_cast<ListViewItem*>(item->extraData(this));
+
+ if (i) {
+ i->markItem(!i->marked());
+ }
+}
+
+void DetailsView::markItem(const QString &filename)
+{
+ if (KFileItem *item = fileItem(filename))
+ markItem(item);
+}
+
+void DetailsView::unmarkItems()
+{
+ KFileItem *item;
+
+ for (item = firstFileItem(); item; item = nextItem(item)) {
+ static_cast<ListViewItem*>(item->extraData(this))->markItem(false);
+ }
+}
+
+DetailsView::ListViewItem::ListViewItem(QListView *parent, KFileItem *fileItem)
+ : KFileListViewItem(parent, fileItem),
+ m_marked(false)
+{
+ if (fileItem->isDir() && !KFTPCore::Config::showDirectorySize()) {
+ setText(SizeColumn, " - ");
+ } else {
+ QString sizeText;
+ sizeText = KFTPCore::Config::showSizeInBytes() ? KIO::number(fileItem->size()) : KIO::convertSize(fileItem->size());
+ sizeText.append(" ");
+
+ setText(SizeColumn, sizeText);
+ }
+}
+
+void DetailsView::ListViewItem::paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int alignment)
+{
+ QColorGroup colorGroup(cg);
+ QColor textColor = colorGroup.text();
+
+ // Set custom file item color if set
+ if (m_textColor.isValid())
+ colorGroup.setColor(QColorGroup::Text, m_textColor);
+
+ // Set custom file item font
+ QFont font = p->font();
+ font.setBold(m_marked);
+ p->setFont(font);
+
+ if (m_backgroundColor.isValid()) {
+ colorGroup.setColor(QColorGroup::Base, m_backgroundColor);
+
+ // Override the KListViewItem since it resets the background color
+ QListViewItem::paintCell(p, colorGroup, column, width, alignment);
+ } else {
+ KFileListViewItem::paintCell(p, colorGroup, column, width, alignment);
+ }
+
+ if (column < listView()->columns() - 1) {
+ // Draw a separator between columns
+ p->setPen(KGlobalSettings::buttonBackground());
+ p->drawLine(width - 1, 0, width - 1, height() - 1);
+ }
+}
+
+void DetailsView::ListViewItem::markItem(bool marked)
+{
+ if (m_marked != marked) {
+ m_marked = marked;
+ repaint();
+ }
+}
+
+}
+
+}
+
+#include "detailsview.moc"