diff options
Diffstat (limited to 'src/dolphincolumnwidget.cpp')
| -rw-r--r-- | src/dolphincolumnwidget.cpp | 446 |
1 files changed, 446 insertions, 0 deletions
diff --git a/src/dolphincolumnwidget.cpp b/src/dolphincolumnwidget.cpp new file mode 100644 index 000000000..94bee2bee --- /dev/null +++ b/src/dolphincolumnwidget.cpp @@ -0,0 +1,446 @@ +/*************************************************************************** + * Copyright (C) 2007 by Peter Penz <[email protected]> * + * * + * 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 WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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 Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#include "dolphincolumnwidget.h" + +#include "dolphinmodel.h" +#include "dolphincolumnview.h" +#include "dolphincontroller.h" +#include "dolphindirlister.h" +#include "dolphinmodel.h" +#include "dolphinsortfilterproxymodel.h" +#include "dolphinsettings.h" + +#include "dolphin_columnmodesettings.h" + +#include <kcolorutils.h> +#include <kcolorscheme.h> +#include <kdirlister.h> +#include <kfileitem.h> +#include <kio/previewjob.h> +#include <kiconeffect.h> +#include <konqmimedata.h> + +#include <QAbstractProxyModel> +#include <QApplication> +#include <QClipboard> +#include <QPoint> +#include <QScrollBar> +#include <QTimer> +#include <QTimeLine> + +DolphinColumnWidget::DolphinColumnWidget(QWidget* parent, + DolphinColumnView* columnView, + const KUrl& url) : + QListView(parent), + m_active(true), + m_showPreview(false), + m_view(columnView), + m_url(url), + m_childUrl(), + m_viewOptions(), + m_dirLister(0), + m_dolphinModel(0), + m_proxyModel(0), + m_dragging(false), + m_dropRect() +{ + setMouseTracking(true); + viewport()->setAttribute(Qt::WA_Hover); + setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); + setSelectionBehavior(SelectItems); + setSelectionMode(QAbstractItemView::ExtendedSelection); + setDragDropMode(QAbstractItemView::DragDrop); + setDropIndicatorShown(false); + setFocusPolicy(Qt::NoFocus); + +// TODO: Remove this check when 4.3.2 is released and KDE requires it... this +// check avoids a division by zero happening on versions before 4.3.1. +// Right now KDE in theory can be shipped with Qt 4.3.0 and above. +// ereslibre +#if (QT_VERSION >= QT_VERSION_CHECK(4, 3, 2) || defined(QT_KDE_QT_COPY)) + setVerticalScrollMode(QListView::ScrollPerPixel); + setHorizontalScrollMode(QListView::ScrollPerPixel); +#endif + + // apply the column mode settings to the widget + const ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings(); + Q_ASSERT(settings != 0); + + m_viewOptions = QListView::viewOptions(); + + QFont font(settings->fontFamily(), settings->fontSize()); + font.setItalic(settings->italicFont()); + font.setBold(settings->boldFont()); + m_viewOptions.font = font; + + const int iconSize = settings->iconSize(); + m_viewOptions.decorationSize = QSize(iconSize, iconSize); + + m_viewOptions.showDecorationSelected = true; + + KFileItemDelegate* delegate = new KFileItemDelegate(this); + setItemDelegate(delegate); + + activate(); + + connect(this, SIGNAL(entered(const QModelIndex&)), + m_view->m_controller, SLOT(emitItemEntered(const QModelIndex&))); + connect(this, SIGNAL(viewportEntered()), + m_view->m_controller, SLOT(emitViewportEntered())); + connect(this, SIGNAL(viewportEntered()), + m_view->m_controller, SLOT(emitViewportEntered())); + + connect(this, SIGNAL(entered(const QModelIndex&)), + this, SLOT(slotEntered(const QModelIndex&))); + + //m_dirLister = new DolphinDirLister(); TODO + m_dirLister = new KDirLister(); + m_dirLister->setAutoUpdate(true); + m_dirLister->setMainWindow(this); + m_dirLister->setDelayedMimeTypes(true); + m_dirLister->setShowingDotFiles(m_view->m_controller->showHiddenFiles()); + connect(m_dirLister, SIGNAL(newItems(const KFileItemList&)), + this, SLOT(generatePreviews(const KFileItemList&))); + + m_dolphinModel = new DolphinModel(this); + m_dolphinModel->setDirLister(m_dirLister); + m_dolphinModel->setDropsAllowed(DolphinModel::DropOnDirectory); + + m_proxyModel = new DolphinSortFilterProxyModel(this); + m_proxyModel->setSourceModel(m_dolphinModel); + + setModel(m_proxyModel); + + m_dirLister->openUrl(url, KDirLister::NoFlags); +} + +DolphinColumnWidget::~DolphinColumnWidget() +{ + delete m_dirLister; + m_dirLister = 0; +} + +void DolphinColumnWidget::setDecorationSize(const QSize& size) +{ + m_viewOptions.decorationSize = size; + doItemsLayout(); +} + +void DolphinColumnWidget::setActive(bool active) +{ + if (m_active == active) { + return; + } + + m_active = active; + + if (active) { + activate(); + } else { + deactivate(); + } +} + +void DolphinColumnWidget::reload() +{ + m_dirLister->stop(); + m_dirLister->openUrl(m_url, KDirLister::Reload); +} + +void DolphinColumnWidget::setShowHiddenFiles(bool show) +{ + if (show != m_dirLister->showingDotFiles()) { + m_dirLister->setShowingDotFiles(show); + m_dirLister->stop(); + m_dirLister->openUrl(m_url, KDirLister::Reload); + } +} + +void DolphinColumnWidget::setShowPreview(bool show) +{ + if (show != m_showPreview) { + m_dirLister->stop(); + m_dirLister->openUrl(m_url, KDirLister::Reload); + } +} + +void DolphinColumnWidget::dragEnterEvent(QDragEnterEvent* event) +{ + if (event->mimeData()->hasUrls()) { + event->acceptProposedAction(); + } + + m_dragging = true; +} + +void DolphinColumnWidget::dragLeaveEvent(QDragLeaveEvent* event) +{ + QListView::dragLeaveEvent(event); + + // TODO: remove this code when the issue #160611 is solved in Qt 4.4 + m_dragging = false; + setDirtyRegion(m_dropRect); +} + +void DolphinColumnWidget::dragMoveEvent(QDragMoveEvent* event) +{ + QListView::dragMoveEvent(event); + + // TODO: remove this code when the issue #160611 is solved in Qt 4.4 + const QModelIndex index = indexAt(event->pos()); + setDirtyRegion(m_dropRect); + m_dropRect = visualRect(index); + setDirtyRegion(m_dropRect); +} + +void DolphinColumnWidget::dropEvent(QDropEvent* event) +{ + const KUrl::List urls = KUrl::List::fromMimeData(event->mimeData()); + if (!urls.isEmpty()) { + event->acceptProposedAction(); + m_view->m_controller->indicateDroppedUrls(urls, + url(), + indexAt(event->pos()), + event->source()); + } + QListView::dropEvent(event); + m_dragging = false; +} + +void DolphinColumnWidget::paintEvent(QPaintEvent* event) +{ + if (!m_childUrl.isEmpty()) { + // indicate the shown URL of the next column by highlighting the shown folder item + const QModelIndex dirIndex = m_dolphinModel->indexForUrl(m_childUrl); + const QModelIndex proxyIndex = m_proxyModel->mapFromSource(dirIndex); + if (proxyIndex.isValid() && !selectionModel()->isSelected(proxyIndex)) { + const QRect itemRect = visualRect(proxyIndex); + QPainter painter(viewport()); + painter.save(); + + QColor color = KColorScheme(QPalette::Active, KColorScheme::View).foreground().color(); + color.setAlpha(32); + painter.setPen(Qt::NoPen); + painter.setBrush(color); + painter.drawRect(itemRect); + + painter.restore(); + } + } + + QListView::paintEvent(event); + + // TODO: remove this code when the issue #160611 is solved in Qt 4.4 + if (m_dragging) { + const QBrush& brush = m_viewOptions.palette.brush(QPalette::Normal, QPalette::Highlight); + DolphinController::drawHoverIndication(viewport(), m_dropRect, brush); + } +} + +void DolphinColumnWidget::mousePressEvent(QMouseEvent* event) +{ + if (!m_active) { + m_view->requestActivation(this); + } + + QListView::mousePressEvent(event); +} + +void DolphinColumnWidget::keyPressEvent(QKeyEvent* event) +{ + QListView::keyPressEvent(event); + + const QItemSelectionModel* selModel = selectionModel(); + const QModelIndex currentIndex = selModel->currentIndex(); + const bool trigger = currentIndex.isValid() + && (event->key() == Qt::Key_Return) + && (selModel->selectedIndexes().count() <= 1); + if (trigger) { + triggerItem(currentIndex); + } +} + +void DolphinColumnWidget::contextMenuEvent(QContextMenuEvent* event) +{ + if (!m_active) { + m_view->requestActivation(this); + } + + QListView::contextMenuEvent(event); + + const QModelIndex index = indexAt(event->pos()); + if (index.isValid() || m_active) { + // Only open a context menu above an item or if the mouse is above + // the active column. + const QPoint pos = m_view->viewport()->mapFromGlobal(event->globalPos()); + m_view->m_controller->triggerContextMenuRequest(pos); + } +} + +void DolphinColumnWidget::selectionChanged(const QItemSelection& selected, const QItemSelection& deselected) +{ + QListView::selectionChanged(selected, deselected); + + QItemSelectionModel* selModel = m_view->selectionModel(); + selModel->select(selected, QItemSelectionModel::Select); + selModel->select(deselected, QItemSelectionModel::Deselect); +} +void DolphinColumnWidget::triggerItem(const QModelIndex& index) +{ + const Qt::KeyboardModifiers modifier = QApplication::keyboardModifiers(); + if ((modifier & Qt::ShiftModifier) || (modifier & Qt::ControlModifier)) { + // items are selected by the user, hence don't trigger the + // item specified by 'index' + return; + } + + // TODO: check ZIP support (see DolphinViewContainer::triggerItem) + KFileItem item = m_dolphinModel->itemForIndex(m_proxyModel->mapToSource(index)); + if (item.isDir()) { + bool isLocal; + const KUrl url = item.mostLocalUrl(isLocal); + m_view->showColumn(url); + m_view->m_controller->setUrl(url); + } else if (item.isFile()) { + item.run(); + } +} + +void DolphinColumnWidget::generatePreviews(const KFileItemList& items) +{ + // TODO: same implementation as in DolphinView; create helper class + // for generatePreviews(), showPreview() and isCutItem() + + if (m_view->m_controller->showPreview()) { + KIO::PreviewJob* job = KIO::filePreview(items, 128); + connect(job, SIGNAL(gotPreview(const KFileItem&, const QPixmap&)), + this, SLOT(showPreview(const KFileItem&, const QPixmap&))); + } +} + +void DolphinColumnWidget::showPreview(const KFileItem& item, const QPixmap& pixmap) +{ + // TODO: same implementation as in DolphinView; create helper class + // for generatePreviews(), showPreview() and isCutItem() + + Q_ASSERT(!item.isNull()); + if (item.url().directory() != m_dirLister->url().path()) { + // the preview job is still working on items of an older URL, hence + // the item is not part of the directory model anymore + return; + } + + const QModelIndex idx = m_dolphinModel->indexForItem(item); + if (idx.isValid() && (idx.column() == 0)) { + const QMimeData* mimeData = QApplication::clipboard()->mimeData(); + if (KonqMimeData::decodeIsCutSelection(mimeData) && isCutItem(item)) { + KIconEffect iconEffect; + const QPixmap cutPixmap = iconEffect.apply(pixmap, KIconLoader::Desktop, KIconLoader::DisabledState); + m_dolphinModel->setData(idx, QIcon(cutPixmap), Qt::DecorationRole); + } else { + m_dolphinModel->setData(idx, QIcon(pixmap), Qt::DecorationRole); + } + } +} + +void DolphinColumnWidget::slotEntered(const QModelIndex& index) +{ + const QModelIndex dirIndex = m_proxyModel->mapToSource(index); + const KFileItem item = m_dolphinModel->itemForIndex(dirIndex); + m_view->m_controller->emitItemEntered(item); +} + +void DolphinColumnWidget::activate() +{ + if (m_view->hasFocus()) { + setFocus(Qt::OtherFocusReason); + } + m_view->setFocusProxy(this); + + // TODO: Connecting to the signal 'activated()' is not possible, as kstyle + // does not forward the single vs. doubleclick to it yet (KDE 4.1?). Hence it is + // necessary connecting the signal 'singleClick()' or 'doubleClick'. + if (KGlobalSettings::singleClick()) { + connect(this, SIGNAL(clicked(const QModelIndex&)), + this, SLOT(triggerItem(const QModelIndex&))); + } else { + connect(this, SIGNAL(doubleClicked(const QModelIndex&)), + this, SLOT(triggerItem(const QModelIndex&))); + } + + const QColor bgColor = KColorScheme(QPalette::Active, KColorScheme::View).background().color(); + QPalette palette = viewport()->palette(); + palette.setColor(viewport()->backgroundRole(), bgColor); + viewport()->setPalette(palette); + + if (!m_childUrl.isEmpty()) { + // assure that the current index is set on the index that represents + // the child URL + const QModelIndex dirIndex = m_dolphinModel->indexForUrl(m_childUrl); + const QModelIndex proxyIndex = m_proxyModel->mapFromSource(dirIndex); + selectionModel()->setCurrentIndex(proxyIndex, QItemSelectionModel::Current); + } + + update(); +} + +void DolphinColumnWidget::deactivate() +{ + // TODO: Connecting to the signal 'activated()' is not possible, as kstyle + // does not forward the single vs. doubleclick to it yet (KDE 4.1?). Hence it is + // necessary connecting the signal 'singleClick()' or 'doubleClick'. + if (KGlobalSettings::singleClick()) { + disconnect(this, SIGNAL(clicked(const QModelIndex&)), + this, SLOT(triggerItem(const QModelIndex&))); + } else { + disconnect(this, SIGNAL(doubleClicked(const QModelIndex&)), + this, SLOT(triggerItem(const QModelIndex&))); + } + + const QPalette palette = m_view->viewport()->palette(); + viewport()->setPalette(palette); + + selectionModel()->clear(); + update(); +} + +bool DolphinColumnWidget::isCutItem(const KFileItem& item) const +{ + // TODO: same implementation as in DolphinView; create helper class + // for generatePreviews(), showPreview() and isCutItem() + + const QMimeData* mimeData = QApplication::clipboard()->mimeData(); + const KUrl::List cutUrls = KUrl::List::fromMimeData(mimeData); + + const KUrl& itemUrl = item.url(); + KUrl::List::const_iterator it = cutUrls.begin(); + const KUrl::List::const_iterator end = cutUrls.end(); + while (it != end) { + if (*it == itemUrl) { + return true; + } + ++it; + } + + return false; +} + +#include "dolphincolumnwidget.moc" |
