summaryrefslogtreecommitdiffstats
path: root/src/dolphiniconsview.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/dolphiniconsview.cpp')
-rw-r--r--src/dolphiniconsview.cpp500
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 *
+ * *
+ * 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"