diff options
Diffstat (limited to 'src/dolphiniconsview.cpp')
-rw-r--r-- | src/dolphiniconsview.cpp | 500 |
1 files changed, 500 insertions, 0 deletions
diff --git a/src/dolphiniconsview.cpp b/src/dolphiniconsview.cpp new file mode 100644 index 0000000..7a2489b --- /dev/null +++ b/src/dolphiniconsview.cpp @@ -0,0 +1,500 @@ +/*************************************************************************** + * Copyright (C) 2006 by Peter Penz * + * peter.penz@gmx.at * + * * + * 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 "dolphiniconsview.h" +#include <qpainter.h> +#include <kiconeffect.h> +#include <kapplication.h> +#include <qobjectlist.h> +#include <kglobalsettings.h> +#include <kurldrag.h> +#include <qclipboard.h> +#include <assert.h> +#include <kaction.h> +#include <kstdaction.h> +#include <kfileitem.h> + +#include "dolphinview.h" +#include "viewproperties.h" +#include "dolphin.h" +#include "dolphinstatusbar.h" +#include "dolphinsettings.h" +#include "dolphiniconsviewsettings.h" + +DolphinIconsView::DolphinIconsView(DolphinView* parent, LayoutMode layoutMode) : + KFileIconView(parent, 0), + m_previewIconSize(-1), + m_layoutMode(layoutMode), + m_dolphinView(parent) +{ + setAcceptDrops(true); + setMode(KIconView::Execute); + setSelectionMode(KFile::Extended); + Dolphin& dolphin = Dolphin::mainWin(); + + connect(this, SIGNAL(onItem(QIconViewItem*)), + this, SLOT(slotOnItem(QIconViewItem*))); + connect(this, SIGNAL(onViewport()), + this, SLOT(slotOnViewport())); + connect(this, SIGNAL(contextMenuRequested(QIconViewItem*, const QPoint&)), + this, SLOT(slotContextMenuRequested(QIconViewItem*, const QPoint&))); + connect(this, SIGNAL(selectionChanged()), + &dolphin, SLOT(slotSelectionChanged())); + connect(&dolphin, SIGNAL(activeViewChanged()), + this, SLOT(slotActivationUpdate())); + connect(this, SIGNAL(itemRenamed(QIconViewItem*, const QString&)), + this, SLOT(slotItemRenamed(QIconViewItem*, const QString&))); + connect(this, SIGNAL(dropped(QDropEvent*, const KURL::List&, const KURL&)), + parent, SLOT(slotURLListDropped(QDropEvent*, const KURL::List&, const KURL&))); + + QClipboard* clipboard = QApplication::clipboard(); + connect(clipboard, SIGNAL(dataChanged()), + this, SLOT(slotUpdateDisabledItems())); + + // KFileIconView creates two actions for zooming, which are directly connected to the + // slots KFileIconView::zoomIn() and KFileIconView::zoomOut(). As this behavior is not + // wanted and the slots are not virtual, the actions are disabled here. + KAction* zoomInAction = actionCollection()->action("zoomIn"); + assert(zoomInAction != 0); + zoomInAction->setEnabled(false); + + KAction* zoomOutAction = actionCollection()->action("zoomOut"); + assert(zoomOutAction != 0); + zoomOutAction->setEnabled(false); + + setItemsMovable(true); + setWordWrapIconText(true); + if (m_layoutMode == Previews) { + showPreviews(); + } + refreshSettings(); +} + +DolphinIconsView::~DolphinIconsView() +{ +} + +void DolphinIconsView::setLayoutMode(LayoutMode mode) +{ + if (m_layoutMode != mode) { + m_layoutMode = mode; + refreshSettings(); + } +} + +void DolphinIconsView::beginItemUpdates() +{ +} + +void DolphinIconsView::endItemUpdates() +{ + arrangeItemsInGrid(); + + // TODO: KFileIconView does not emit any signal when the preview + // has been finished. Using a delay of 300 ms is a temporary workaround + // until the DolphinIconsView will implement the previews by it's own in + // future releases. + QTimer::singleShot(300, this, SLOT(slotUpdateDisabledItems())); + + const KFileIconViewItem* item = static_cast<const KFileIconViewItem*>(firstItem()); + if (item != 0) { + setCurrentItem(item->fileInfo()); + } + + int index = 0; + const QValueList<URLNavigator::HistoryElem> history = m_dolphinView->urlHistory(index); + if (!history.isEmpty()) { + KFileView* fileView = static_cast<KFileView*>(this); + fileView->setCurrentItem(history[index].currentFileName()); + setContentsPos(history[index].contentsX(), history[index].contentsY()); + } +} + +void DolphinIconsView::refreshSettings() +{ + const DolphinIconsViewSettings* settings = DolphinSettings::instance().iconsView(m_layoutMode); + assert(settings != 0); + + setIconSize(settings->iconSize()); + + const QIconView::Arrangement arrangement = settings->arrangement(); + const QIconView::ItemTextPos textPos = (arrangement == QIconView::LeftToRight) ? + QIconView::Bottom : + QIconView::Right; + setArrangement(arrangement); + setItemTextPos(textPos); + + setGridX(settings->gridWidth()); + setGridY(settings->gridHeight()); + setSpacing(settings->gridSpacing()); + + QFont adjustedFont(font()); + adjustedFont.setFamily(settings->fontFamily()); + adjustedFont.setPointSize(settings->fontSize()); + setFont(adjustedFont); + setIconTextHeight(settings->textlinesCount()); + + if (m_layoutMode == Previews) { + // There is no getter method for the current size in KFileIconView. To + // prevent a flickering the current size is stored in m_previewIconSize and + // setPreviewSize is only invoked if the size really has changed. + showPreviews(); + + const int size = settings->previewSize(); + if (size != m_previewIconSize) { + m_previewIconSize = size; + setPreviewSize(size); + } + } +} + +void DolphinIconsView::zoomIn() +{ + if (isZoomInPossible()) { + DolphinIconsViewSettings* settings = DolphinSettings::instance().iconsView(m_layoutMode); + const int textWidthHint = settings->textWidthHint(); + + const int iconSize = increasedIconSize(settings->iconSize()); + settings->setIconSize(iconSize); + + if (m_layoutMode == Previews) { + const int previewSize = increasedIconSize(settings->previewSize()); + settings->setPreviewSize(previewSize); + } + + settings->calculateGridSize(textWidthHint); + ItemEffectsManager::zoomIn(); + } +} + +void DolphinIconsView::zoomOut() +{ + if (isZoomOutPossible()) { + DolphinIconsViewSettings* settings = DolphinSettings::instance().iconsView(m_layoutMode); + const int textWidthHint = settings->textWidthHint(); + + const int iconSize = decreasedIconSize(settings->iconSize()); + settings->setIconSize(iconSize); + + if (m_layoutMode == Previews) { + const int previewSize = decreasedIconSize(settings->previewSize()); + settings->setPreviewSize(previewSize); + } + + settings->calculateGridSize(textWidthHint); + ItemEffectsManager::zoomOut(); + } +} + +bool DolphinIconsView::isZoomInPossible() const +{ + DolphinIconsViewSettings* settings = DolphinSettings::instance().iconsView(m_layoutMode); + const int size = (m_layoutMode == Icons) ? settings->iconSize() : settings->previewSize(); + return size < KIcon::SizeEnormous; +} + +bool DolphinIconsView::isZoomOutPossible() const +{ + DolphinIconsViewSettings* settings = DolphinSettings::instance().iconsView(m_layoutMode); + return settings->iconSize() > KIcon::SizeSmall; +} + +void DolphinIconsView::arrangeItemsInGrid( bool updated ) +{ + + KFileIconView::arrangeItemsInGrid(updated); + + if (m_layoutMode == Previews) { + // The class KFileIconView has a bug when the size of the previews differs from the size + // of the icons: For specific MIME types the y-position and the height is calculated in + // a wrong manner. The following code bypasses this issue. No bugreport has been submitted + // as this functionality is not used by any KDE3 application and the core developers are + // busy enough for KDE4 now :-) + + KFileIconViewItem* item = static_cast<KFileIconViewItem*>(QIconView::firstItem()); + QString mimetype; + while (item != 0) { + mimetype = item->fileInfo()->mimetype(); + const bool fixSize = mimetype.contains("text") || + mimetype.contains("application/x-"); + if (fixSize) { + item->setPixmapSize(QSize(m_previewIconSize, m_previewIconSize)); + } + item = static_cast<KFileIconViewItem *>(item->nextItem()); + } + } +} + +void DolphinIconsView::setContextPixmap(void* context, + const QPixmap& pixmap) +{ + reinterpret_cast<KFileIconViewItem*>(context)->setPixmap(pixmap); +} + +const QPixmap* DolphinIconsView::contextPixmap(void* context) +{ + return reinterpret_cast<KFileIconViewItem*>(context)->pixmap(); +} + +void* DolphinIconsView::firstContext() +{ + return reinterpret_cast<void*>(firstItem()); +} + +void* DolphinIconsView::nextContext(void* context) +{ + KFileIconViewItem* iconViewItem = reinterpret_cast<KFileIconViewItem*>(context); + return reinterpret_cast<void*>(iconViewItem->nextItem()); +} + +KFileItem* DolphinIconsView::contextFileInfo(void* context) +{ + return reinterpret_cast<KFileIconViewItem*>(context)->fileInfo(); +} + +void DolphinIconsView::contentsMousePressEvent(QMouseEvent* event) +{ + KFileIconView::contentsMousePressEvent(event); + resetActivatedItem(); + emit signalRequestActivation(); + m_dolphinView->statusBar()->clear(); +} + +void DolphinIconsView::contentsMouseReleaseEvent(QMouseEvent* event) +{ + KFileIconView::contentsMouseReleaseEvent(event); + + // The KFileIconView does not send any selectionChanged signal if + // a selection is done by using the "select-during-button-pressed" feature. + // Hence inform Dolphin about the selection change manually: + Dolphin::mainWin().slotSelectionChanged(); +} + +void DolphinIconsView::drawBackground(QPainter* painter, const QRect& rect) +{ + if (m_dolphinView->isActive()) { + KFileIconView::drawBackground(painter, rect); + } + else { + const QBrush brush(colorGroup().background()); + painter->fillRect(0, 0, width(), height(), brush); + } +} + +QDragObject* DolphinIconsView::dragObject() +{ + KURL::List urls; + KFileItemListIterator it(*KFileView::selectedItems()); + while (it.current() != 0) { + urls.append((*it)->url()); + ++it; + } + + QPixmap pixmap; + if(urls.count() > 1) { + pixmap = DesktopIcon("kmultiple", iconSize()); + } + else { + KFileIconViewItem* item = static_cast<KFileIconViewItem*>(currentItem()); + if ((item != 0) && (item->pixmap() != 0)) { + pixmap = *(item->pixmap()); + } + } + + if (pixmap.isNull()) { + pixmap = currentFileItem()->pixmap(iconSize()); + } + + QDragObject* dragObj = new KURLDrag(urls, widget()); + dragObj->setPixmap(pixmap); + return dragObj; +} + +void DolphinIconsView::contentsDragEnterEvent(QDragEnterEvent* event) +{ + // TODO: The method KFileIconView::contentsDragEnterEvent() does + // not allow drag and drop inside itself, which prevents the possability + // to move a file into a directory. As the method KFileIconView::acceptDrag() + // is not virtual, we must overwrite the method + // KFileIconView::contentsDragEnterEvent() and do some cut/copy/paste for this + // usecase. Corresponding to the documentation the method KFileIconView::acceptDrag() + // will get virtual in KDE 4, which will simplify the code. + + if (event->source() != this) { + KFileIconView::contentsDragEnterEvent(event); + return; + } + + const bool accept = KURLDrag::canDecode(event) && + (event->action() == QDropEvent::Copy || + event->action() == QDropEvent::Move || + event->action() == QDropEvent::Link ); + if (accept) { + event->acceptAction(); + } + else { + event->ignore(); + } +} + +void DolphinIconsView::contentsDragMoveEvent(QDragMoveEvent* event) +{ + KFileIconView::contentsDragMoveEvent(event); + + // If a dragging is done above a directory, show the icon as 'active' for + // a visual feedback + KFileIconViewItem* item = static_cast<KFileIconViewItem*>(findItem(contentsToViewport(event->pos()))); + + bool showActive = false; + if (item != 0) { + const KFileItem* fileInfo = item->fileInfo(); + showActive = (fileInfo != 0) && fileInfo->isDir(); + } + + if (showActive) { + slotOnItem(item); + } + else { + slotOnViewport(); + } +} + +void DolphinIconsView::contentsDropEvent(QDropEvent* event) +{ + // TODO: Most of the following code is a copy of + // KFileIconView::contentsDropEvent. See comment in + // DolphinIconsView::contentsDragEnterEvent for details. + + if (event->source() != this) { + KFileIconView::contentsDropEvent(event); + return; + } + + KFileIconViewItem* item = static_cast<KFileIconViewItem*>(findItem(contentsToViewport(event->pos()))); + const bool accept = KURLDrag::canDecode(event) && + (event->action() == QDropEvent::Copy || + event->action() == QDropEvent::Move || + event->action() == QDropEvent::Link ) && + (item != 0); + if (!accept) { + return; + } + + KFileItem* fileItem = item->fileInfo(); + if (!fileItem->isDir()) { + // the file is not a directory, hence don't accept any drop + return; + } + emit dropped(event, fileItem); + KURL::List urls; + if (KURLDrag::decode(event, urls) && !urls.isEmpty()) { + emit dropped(event, urls, fileItem != 0 ? fileItem->url() : KURL()); + sig->dropURLs(fileItem, event, urls); + } +} + +void DolphinIconsView::slotOnItem(QIconViewItem* item) +{ + assert(item != 0); + activateItem(reinterpret_cast<void*>(item)); + + KFileItem* fileItem = static_cast<KFileIconViewItem*>(item)->fileInfo(); + m_dolphinView->requestItemInfo(fileItem->url()); +} + +void DolphinIconsView::slotOnViewport() +{ + resetActivatedItem(); + m_dolphinView->requestItemInfo(KURL()); +} + +void DolphinIconsView::slotContextMenuRequested(QIconViewItem* item, + const QPoint& pos) +{ + KFileItem* fileInfo = 0; + if (item != 0) { + fileInfo = static_cast<KFileIconViewItem*>(item)->fileInfo(); + } + m_dolphinView->openContextMenu(fileInfo, pos); +} + +void DolphinIconsView::slotItemRenamed(QIconViewItem* item, + const QString& name) +{ + KFileItem* fileInfo = static_cast<KFileIconViewItem*>(item)->fileInfo(); + m_dolphinView->rename(KURL(fileInfo->url()), name); +} + +void DolphinIconsView::slotActivationUpdate() +{ + update(); + + // TODO: there must be a simpler way to say + // "update all children" + const QObjectList* list = children(); + if (list == 0) { + return; + } + + QObjectListIterator it(*list); + QObject* object = 0; + while ((object = it.current()) != 0) { + if (object->inherits("QWidget")) { + QWidget* widget = static_cast<QWidget*>(object); + widget->update(); + } + ++it; + } +} + +void DolphinIconsView::slotUpdateDisabledItems() +{ + updateDisabledItems(); +} + +int DolphinIconsView::increasedIconSize(int size) const +{ + int incSize = 0; + switch (size) { + case KIcon::SizeSmall: incSize = KIcon::SizeSmallMedium; break; + case KIcon::SizeSmallMedium: incSize = KIcon::SizeMedium; break; + case KIcon::SizeMedium: incSize = KIcon::SizeLarge; break; + case KIcon::SizeLarge: incSize = KIcon::SizeHuge; break; + case KIcon::SizeHuge: incSize = KIcon::SizeEnormous; break; + default: assert(false); break; + } + return incSize; +} + +int DolphinIconsView::decreasedIconSize(int size) const +{ + int decSize = 0; + switch (size) { + case KIcon::SizeSmallMedium: decSize = KIcon::SizeSmall; break; + case KIcon::SizeMedium: decSize = KIcon::SizeSmallMedium; break; + case KIcon::SizeLarge: decSize = KIcon::SizeMedium; break; + case KIcon::SizeHuge: decSize = KIcon::SizeLarge; break; + case KIcon::SizeEnormous: decSize = KIcon::SizeHuge; break; + default: assert(false); break; + } + return decSize; +} + +#include "dolphiniconsview.moc" |