/***************************************************************************
- * Copyright (C) 2006 by Peter Penz <peter.penz@gmx.at> *
+ * Copyright (C) 2006-2010 by Peter Penz <peter.penz19@gmail.com> *
* *
* 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 *
#include "folderspanel.h"
-#include "settings/dolphinsettings.h"
#include "dolphin_folderspanelsettings.h"
#include "dolphin_generalsettings.h"
-#include "paneltreeview.h"
#include "treeviewcontextmenu.h"
-#include <kfileplacesmodel.h>
-#include <kdirlister.h>
-#include <kfileitem.h>
+#include <kitemviews/kitemlistselectionmanager.h>
+#include <kitemviews/kfileitemlistview.h>
+#include <kitemviews/kfileitemlistwidget.h>
+#include <kitemviews/kitemlistcontainer.h>
+#include <kitemviews/kitemlistcontroller.h>
+#include <kitemviews/kfileitemmodel.h>
+
+#include <KDirLister>
+#include <KFileItem>
#include <konq_operations.h>
#include <QApplication>
-#include <QItemSelection>
-#include <QTreeView>
#include <QBoxLayout>
-#include <QModelIndex>
-#include <QScrollBar>
+#include <QDropEvent>
+#include <QGraphicsSceneDragDropEvent>
+#include <QGraphicsView>
+#include <QPropertyAnimation>
#include <QTimer>
#include <views/draganddrophelper.h>
-#include <views/dolphinmodel.h>
-#include <views/dolphinsortfilterproxymodel.h>
-#include <views/dolphinview.h>
-#include <views/folderexpander.h>
#include <views/renamedialog.h>
+#include <KDebug>
+
FoldersPanel::FoldersPanel(QWidget* parent) :
Panel(parent),
- m_setLeafVisible(false),
- m_mouseButtons(Qt::NoButton),
+ m_updateCurrentItem(false),
m_dirLister(0),
- m_dolphinModel(0),
- m_proxyModel(0),
- m_treeView(0),
- m_leafDir()
+ m_controller(0)
{
setLayoutDirection(Qt::LeftToRight);
}
{
FoldersPanelSettings::self()->writeConfig();
- delete m_proxyModel;
- m_proxyModel = 0;
- delete m_dolphinModel;
- m_dolphinModel = 0;
- m_dirLister = 0; // deleted by m_dolphinModel
+ if (m_controller) {
+ KItemListView* view = m_controller->view();
+ m_controller->setView(0);
+ delete view;
+ }
+
+ delete m_dirLister;
+ m_dirLister = 0;
}
-QSize FoldersPanel::sizeHint() const
+void FoldersPanel::setHiddenFilesShown(bool show)
{
- return QSize(200, 400);
+ FoldersPanelSettings::setHiddenFilesShown(show);
+ if (m_dirLister) {
+ KFileItemModel* model = fileItemModel();
+ const QSet<KUrl> expandedUrls = model->expandedUrls();
+ model->setShowHiddenFiles(show);
+ model->setExpanded(expandedUrls);
+ }
}
-void FoldersPanel::setShowHiddenFiles(bool show)
+bool FoldersPanel::hiddenFilesShown() const
{
- FoldersPanelSettings::setShowHiddenFiles(show);
- if (m_dirLister != 0) {
- m_dirLister->setShowingDotFiles(show);
- m_dirLister->openUrl(m_dirLister->url(), KDirLister::Reload);
- }
+ return FoldersPanelSettings::hiddenFilesShown();
}
-bool FoldersPanel::showHiddenFiles() const
+void FoldersPanel::setAutoScrolling(bool enable)
{
- return FoldersPanelSettings::showHiddenFiles();
+ // TODO: Not supported yet in Dolphin 2.0
+ FoldersPanelSettings::setAutoScrolling(enable);
+}
+
+bool FoldersPanel::autoScrolling() const
+{
+ return FoldersPanelSettings::autoScrolling();
}
void FoldersPanel::rename(const KFileItem& item)
{
- if (DolphinSettings::instance().generalSettings()->renameInline()) {
- const QModelIndex dirIndex = m_dolphinModel->indexForItem(item);
- const QModelIndex proxyIndex = m_proxyModel->mapFromSource(dirIndex);
- m_treeView->edit(proxyIndex);
+ // TODO: Inline renaming is not supported anymore in Dolphin 2.0
+ if (false /* GeneralSettings::renameInline() */) {
+ //const QModelIndex dirIndex = m_dolphinModel->indexForItem(item);
+ //const QModelIndex proxyIndex = m_proxyModel->mapFromSource(dirIndex);
+ //m_treeView->edit(proxyIndex);
} else {
- KFileItemList items;
- items.append(item);
- QPointer<RenameDialog> dialog = new RenameDialog(this, items);
- if (dialog->exec() == QDialog::Accepted) {
- const QString newName = dialog->newName();
- if (!newName.isEmpty()) {
- KUrl newUrl = item.url();
- newUrl.setFileName(newName);
- KonqOperations::rename(this, item.url(), newUrl);
- }
- }
- delete dialog;
+ RenameDialog* dialog = new RenameDialog(this, KFileItemList() << item);
+ dialog->setAttribute(Qt::WA_DeleteOnClose);
+ dialog->show();
+ dialog->raise();
+ dialog->activateWindow();
}
}
-void FoldersPanel::setUrl(const KUrl& url)
+bool FoldersPanel::urlChanged()
{
- if (!url.isValid() || (url == Panel::url())) {
- return;
+ if (!url().isValid() || url().protocol().contains("search")) {
+ // Skip results shown by a search, as possible identical
+ // directory names are useless without parent-path information.
+ return false;
}
- Panel::setUrl(url);
- if (m_dirLister != 0) {
- m_setLeafVisible = true;
- loadTree(url);
+ if (m_dirLister) {
+ loadTree(url());
}
+
+ return true;
}
void FoldersPanel::showEvent(QShowEvent* event)
return;
}
- if (m_dirLister == 0) {
+ if (!m_dirLister) {
// Postpone the creating of the dir lister to the first show event.
// This assures that no performance and memory overhead is given when the TreeView is not
// used at all (see FoldersPanel::setUrl()).
m_dirLister->setMainWindow(window());
m_dirLister->setDelayedMimeTypes(true);
m_dirLister->setAutoErrorHandlingEnabled(false, this);
- m_dirLister->setShowingDotFiles(FoldersPanelSettings::showHiddenFiles());
-
- Q_ASSERT(m_dolphinModel == 0);
- m_dolphinModel = new DolphinModel(this);
- m_dolphinModel->setDirLister(m_dirLister);
- m_dolphinModel->setDropsAllowed(DolphinModel::DropOnDirectory);
- connect(m_dolphinModel, SIGNAL(expand(const QModelIndex&)),
- this, SLOT(expandToDir(const QModelIndex&)));
-
- Q_ASSERT(m_proxyModel == 0);
- m_proxyModel = new DolphinSortFilterProxyModel(this);
- m_proxyModel->setSourceModel(m_dolphinModel);
-
- Q_ASSERT(m_treeView == 0);
- m_treeView = new PanelTreeView(this);
- m_treeView->setModel(m_proxyModel);
- m_proxyModel->setSorting(DolphinView::SortByName);
- m_proxyModel->setSortOrder(Qt::AscendingOrder);
-
- new FolderExpander(m_treeView, m_proxyModel);
-
- connect(m_treeView, SIGNAL(clicked(const QModelIndex&)),
- this, SLOT(updateActiveView(const QModelIndex&)));
- connect(m_treeView, SIGNAL(urlsDropped(const QModelIndex&, QDropEvent*)),
- this, SLOT(dropUrls(const QModelIndex&, QDropEvent*)));
- connect(m_treeView, SIGNAL(pressed(const QModelIndex&)),
- this, SLOT(updateMouseButtons()));
+
+ KFileItemListView* view = new KFileItemListView();
+ view->setWidgetCreator(new KItemListWidgetCreator<KFileItemListWidget>());
+
+ KItemListStyleOption styleOption = view->styleOption();
+ styleOption.margin = 2;
+ styleOption.iconSize = KIconLoader::SizeSmall;
+ view->setStyleOption(styleOption);
+
+ const qreal itemHeight = qMax(int(KIconLoader::SizeSmall), styleOption.fontMetrics.height());
+ view->setItemSize(QSizeF(-1, itemHeight + 2 * styleOption.margin));
+ view->setItemLayout(KFileItemListView::DetailsLayout);
+ // Set the opacity to 0 initially. The opacity will be increased after the loading of the initial tree
+ // has been finished in slotLoadingCompleted(). This prevents an unnecessary animation-mess when
+ // opening the folders panel.
+ view->setOpacity(0);
+
+ KFileItemModel* model = new KFileItemModel(m_dirLister, this);
+ model->setShowHiddenFiles(FoldersPanelSettings::hiddenFilesShown());
+ // Use a QueuedConnection to give the view the possibility to react first on the
+ // finished loading.
+ connect(model, SIGNAL(loadingCompleted()), this, SLOT(slotLoadingCompleted()), Qt::QueuedConnection);
+
+ KItemListContainer* container = new KItemListContainer(this);
+ m_controller = container->controller();
+ m_controller->setView(view);
+ m_controller->setModel(model);
+ m_controller->setSelectionBehavior(KItemListController::SingleSelection);
+ m_controller->setAutoActivationDelay(750);
+
+ connect(m_controller, SIGNAL(itemActivated(int)), this, SLOT(slotItemActivated(int)));
+ connect(m_controller, SIGNAL(itemMiddleClicked(int)), this, SLOT(slotItemMiddleClicked(int)));
+ connect(m_controller, SIGNAL(itemContextMenuRequested(int,QPointF)), this, SLOT(slotItemContextMenuRequested(int,QPointF)));
+ connect(m_controller, SIGNAL(viewContextMenuRequested(QPointF)), this, SLOT(slotViewContextMenuRequested(QPointF)));
+ connect(m_controller, SIGNAL(itemDropEvent(int,QGraphicsSceneDragDropEvent*)), this, SLOT(slotItemDropEvent(int,QGraphicsSceneDragDropEvent*)));
+
+ // TODO: Check whether it makes sense to make an explicit API for KItemListContainer
+ // to make the background transparent.
+ container->setFrameShape(QFrame::NoFrame);
+ QGraphicsView* graphicsView = qobject_cast<QGraphicsView*>(container->viewport());
+ if (graphicsView) {
+ // Make the background of the container transparent and apply the window-text color
+ // to the text color, so that enough contrast is given for all color
+ // schemes
+ QPalette p = graphicsView->palette();
+ p.setColor(QPalette::Active, QPalette::Text, p.color(QPalette::Active, QPalette::WindowText));
+ p.setColor(QPalette::Inactive, QPalette::Text, p.color(QPalette::Inactive, QPalette::WindowText));
+ p.setColor(QPalette::Disabled, QPalette::Text, p.color(QPalette::Disabled, QPalette::WindowText));
+ graphicsView->setPalette(p);
+ graphicsView->viewport()->setAutoFillBackground(false);
+ }
QVBoxLayout* layout = new QVBoxLayout(this);
layout->setMargin(0);
- layout->addWidget(m_treeView);
+ layout->addWidget(container);
}
loadTree(url());
Panel::showEvent(event);
}
-void FoldersPanel::contextMenuEvent(QContextMenuEvent* event)
-{
- Panel::contextMenuEvent(event);
-
- KFileItem item;
- const QModelIndex index = m_treeView->indexAt(event->pos());
- if (index.isValid()) {
- const QModelIndex dolphinModelIndex = m_proxyModel->mapToSource(index);
- item = m_dolphinModel->itemForIndex(dolphinModelIndex);
- }
-
- TreeViewContextMenu contextMenu(this, item);
- contextMenu.open();
-}
-
void FoldersPanel::keyPressEvent(QKeyEvent* event)
{
const int key = event->key();
if ((key == Qt::Key_Enter) || (key == Qt::Key_Return)) {
event->accept();
- updateActiveView(m_treeView->currentIndex());
} else {
Panel::keyPressEvent(event);
}
}
-void FoldersPanel::updateActiveView(const QModelIndex& index)
+void FoldersPanel::slotItemActivated(int index)
{
- const QModelIndex dirIndex = m_proxyModel->mapToSource(index);
- const KFileItem item = m_dolphinModel->itemForIndex(dirIndex);
+ const KFileItem item = fileItemModel()->fileItem(index);
if (!item.isNull()) {
- emit changeUrl(item.url(), m_mouseButtons);
+ emit changeUrl(item.url(), Qt::LeftButton);
}
}
-void FoldersPanel::dropUrls(const QModelIndex& index, QDropEvent* event)
+void FoldersPanel::slotItemMiddleClicked(int index)
{
- if (index.isValid()) {
- const QModelIndex dirIndex = m_proxyModel->mapToSource(index);
- KFileItem item = m_dolphinModel->itemForIndex(dirIndex);
- Q_ASSERT(!item.isNull());
- if (item.isDir()) {
- DragAndDropHelper::instance().dropUrls(item, item.url(), event, this);
- }
+ const KFileItem item = fileItemModel()->fileItem(index);
+ if (!item.isNull()) {
+ emit changeUrl(item.url(), Qt::MiddleButton);
+ }
+}
+
+void FoldersPanel::slotItemContextMenuRequested(int index, const QPointF& pos)
+{
+ Q_UNUSED(pos);
+
+ const KFileItem fileItem = fileItemModel()->fileItem(index);
+
+ QWeakPointer<TreeViewContextMenu> contextMenu = new TreeViewContextMenu(this, fileItem);
+ contextMenu.data()->open();
+ if (contextMenu.data()) {
+ delete contextMenu.data();
}
}
-void FoldersPanel::expandToDir(const QModelIndex& index)
+void FoldersPanel::slotViewContextMenuRequested(const QPointF& pos)
{
- m_treeView->setExpanded(index, true);
- selectLeafDirectory();
- m_treeView->resizeColumnToContents(DolphinModel::Name);
+ Q_UNUSED(pos);
+
+ QWeakPointer<TreeViewContextMenu> contextMenu = new TreeViewContextMenu(this, KFileItem());
+ contextMenu.data()->open();
+ if (contextMenu.data()) {
+ delete contextMenu.data();
+ }
+}
+
+void FoldersPanel::slotItemDropEvent(int index, QGraphicsSceneDragDropEvent* event)
+{
+ if (index >= 0) {
+ KFileItemModel* model = fileItemModel();
+ KFileItem destItem = model->fileItem(index);
+ if (destItem.isNull()) {
+ destItem = model->rootItem();
+ if (destItem.isNull()) {
+ kWarning() << "No destination item available for drop operation.";
+ return;
+ }
+ }
+
+ QDropEvent dropEvent(event->pos().toPoint(),
+ event->possibleActions(),
+ event->mimeData(),
+ event->buttons(),
+ event->modifiers());
+
+ DragAndDropHelper::dropUrls(destItem, &dropEvent);
+ }
}
-void FoldersPanel::scrollToLeaf()
+void FoldersPanel::slotLoadingCompleted()
{
- const QModelIndex dirIndex = m_dolphinModel->indexForUrl(m_leafDir);
- const QModelIndex proxyIndex = m_proxyModel->mapFromSource(dirIndex);
- if (proxyIndex.isValid()) {
- m_treeView->scrollTo(proxyIndex);
+ if (m_controller->view()->opacity() == 0) {
+ // The loading of the initial tree after opening the Folders panel
+ // has been finished. Trigger the increasing of the opacity after
+ // a short delay to give the view the chance to finish its internal
+ // animations.
+ // TODO: Check whether it makes sense to allow accessing the
+ // view-internal delay for usecases like this.
+ QTimer::singleShot(250, this, SLOT(startFadeInAnimation()));
}
+
+ if (!m_updateCurrentItem) {
+ return;
+ }
+
+ const int index = fileItemModel()->index(url());
+ updateCurrentItem(index);
+ m_updateCurrentItem = false;
}
-void FoldersPanel::updateMouseButtons()
+void FoldersPanel::startFadeInAnimation()
{
- m_mouseButtons = QApplication::mouseButtons();
+ QPropertyAnimation* anim = new QPropertyAnimation(m_controller->view(), "opacity", this);
+ anim->setStartValue(0);
+ anim->setEndValue(1);
+ anim->setEasingCurve(QEasingCurve::InOutQuad);
+ anim->start(QAbstractAnimation::DeleteWhenStopped);
+ anim->setDuration(200);
}
void FoldersPanel::loadTree(const KUrl& url)
{
- Q_ASSERT(m_dirLister != 0);
- m_leafDir = url;
+ Q_ASSERT(m_dirLister);
+
+ m_updateCurrentItem = false;
KUrl baseUrl;
if (url.isLocalFile()) {
- // use the root directory as base for local URLs (#150941)
+ // Use the root directory as base for local URLs (#150941)
baseUrl = QDir::rootPath();
} else {
- // clear the path for non-local URLs and use it as base
+ // Clear the path for non-local URLs and use it as base
baseUrl = url;
baseUrl.setPath(QString('/'));
}
if (m_dirLister->url() != baseUrl) {
+ m_updateCurrentItem = true;
m_dirLister->stop();
m_dirLister->openUrl(baseUrl, KDirLister::Reload);
}
- m_dolphinModel->expandToUrl(m_leafDir);
+
+ KFileItemModel* model = fileItemModel();
+ const int index = model->index(url);
+ if (index >= 0) {
+ updateCurrentItem(index);
+ } else {
+ m_updateCurrentItem = true;
+ model->setExpanded(QSet<KUrl>() << url);
+ // slotLoadingCompleted() will be invoked after the model has
+ // expanded the url
+ }
}
-void FoldersPanel::selectLeafDirectory()
+void FoldersPanel::updateCurrentItem(int index)
{
- const QModelIndex dirIndex = m_dolphinModel->indexForUrl(m_leafDir);
- const QModelIndex proxyIndex = m_proxyModel->mapFromSource(dirIndex);
- if (!proxyIndex.isValid()) {
- return;
- }
+ KItemListSelectionManager* selectionManager = m_controller->selectionManager();
+ selectionManager->setCurrentItem(index);
+ selectionManager->clearSelection();
+ selectionManager->setSelected(index);
- if (m_setLeafVisible) {
- // Invoke m_treeView->scrollTo(proxyIndex) asynchronously by
- // scrollToLeaf(). This assures that the scrolling is done after
- // the horizontal scrollbar gets visible (otherwise the scrollbar
- // might hide the leaf).
- QTimer::singleShot(100, this, SLOT(scrollToLeaf()));
- m_setLeafVisible = false;
- }
+ m_controller->view()->scrollToItem(index);
+}
- QItemSelectionModel* selModel = m_treeView->selectionModel();
- selModel->setCurrentIndex(proxyIndex, QItemSelectionModel::ClearAndSelect);
+KFileItemModel* FoldersPanel::fileItemModel() const
+{
+ return static_cast<KFileItemModel*>(m_controller->model());
}
#include "folderspanel.moc"