You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
dolphin/src/dolphiniconsview.cpp

501 lines
17 KiB

/***************************************************************************
* 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 <tqpainter.h>
#include <kiconeffect.h>
#include <tdeapplication.h>
#include <tqobjectlist.h>
#include <tdeglobalsettings.h>
#include <kurldrag.h>
#include <tqclipboard.h>
#include <assert.h>
#include <tdeaction.h>
#include <kstdaction.h>
#include <tdefileitem.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(TDEIconView::Execute);
setSelectionMode(KFile::Extended);
Dolphin& dolphin = Dolphin::mainWin();
connect(this, TQ_SIGNAL(onItem(TQIconViewItem*)),
this, TQ_SLOT(slotOnItem(TQIconViewItem*)));
connect(this, TQ_SIGNAL(onViewport()),
this, TQ_SLOT(slotOnViewport()));
connect(this, TQ_SIGNAL(contextMenuRequested(TQIconViewItem*, const TQPoint&)),
this, TQ_SLOT(slotContextMenuRequested(TQIconViewItem*, const TQPoint&)));
connect(this, TQ_SIGNAL(selectionChanged()),
&dolphin, TQ_SLOT(slotSelectionChanged()));
connect(&dolphin, TQ_SIGNAL(activeViewChanged()),
this, TQ_SLOT(slotActivationUpdate()));
connect(this, TQ_SIGNAL(itemRenamed(TQIconViewItem*, const TQString&)),
this, TQ_SLOT(slotItemRenamed(TQIconViewItem*, const TQString&)));
connect(this, TQ_SIGNAL(dropped(TQDropEvent*, const KURL::List&, const KURL&)),
parent, TQ_SLOT(slotURLListDropped(TQDropEvent*, const KURL::List&, const KURL&)));
TQClipboard* clipboard = TQApplication::clipboard();
connect(clipboard, TQ_SIGNAL(dataChanged()),
this, TQ_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.
TDEAction* zoomInAction = actionCollection()->action("zoomIn");
assert(zoomInAction != 0);
zoomInAction->setEnabled(false);
TDEAction* 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.
TQTimer::singleShot(300, this, TQ_SLOT(slotUpdateDisabledItems()));
const KFileIconViewItem* item = static_cast<const KFileIconViewItem*>(firstItem());
if (item != 0) {
setCurrentItem(item->fileInfo());
}
int index = 0;
const TQValueList<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 TQIconView::Arrangement arrangement = settings->arrangement();
const TQIconView::ItemTextPos textPos = (arrangement == TQIconView::LeftToRight) ?
TQIconView::Bottom :
TQIconView::Right;
setArrangement(arrangement);
setItemTextPos(textPos);
setGridX(settings->gridWidth());
setGridY(settings->gridHeight());
setSpacing(settings->gridSpacing());
TQFont 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 < TDEIcon::SizeEnormous;
}
bool DolphinIconsView::isZoomOutPossible() const
{
DolphinIconsViewSettings* settings = DolphinSettings::instance().iconsView(m_layoutMode);
return settings->iconSize() > TDEIcon::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*>(TQIconView::firstItem());
TQString mimetype;
while (item != 0) {
mimetype = item->fileInfo()->mimetype();
const bool fixSize = mimetype.contains("text") ||
mimetype.contains("application/x-");
if (fixSize) {
item->setPixmapSize(TQSize(m_previewIconSize, m_previewIconSize));
}
item = static_cast<KFileIconViewItem *>(item->nextItem());
}
}
}
void DolphinIconsView::setContextPixmap(void* context,
const TQPixmap& pixmap)
{
reinterpret_cast<KFileIconViewItem*>(context)->setPixmap(pixmap);
}
const TQPixmap* 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(TQMouseEvent* event)
{
KFileIconView::contentsMousePressEvent(event);
resetActivatedItem();
emit signalRequestActivation();
m_dolphinView->statusBar()->clear();
}
void DolphinIconsView::contentsMouseReleaseEvent(TQMouseEvent* 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(TQPainter* painter, const TQRect& rect)
{
if (m_dolphinView->isActive()) {
KFileIconView::drawBackground(painter, rect);
}
else {
const TQBrush brush(colorGroup().background());
painter->fillRect(0, 0, width(), height(), brush);
}
}
TQDragObject* DolphinIconsView::dragObject()
{
KURL::List urls;
KFileItemListIterator it(*KFileView::selectedItems());
while (it.current() != 0) {
urls.append((*it)->url());
++it;
}
TQPixmap pixmap;
if(urls.count() > 1) {
pixmap = DesktopIcon("application-vnd.tde.tdemultiple", iconSize());
}
else {
KFileIconViewItem* item = static_cast<KFileIconViewItem*>(currentItem());
if ((item != 0) && (item->pixmap() != 0)) {
pixmap = *(item->pixmap());
}
}
if (pixmap.isNull()) {
pixmap = currentFileItem()->pixmap(iconSize());
}
TQDragObject* dragObj = new KURLDrag(urls, widget());
dragObj->setPixmap(pixmap);
return dragObj;
}
void DolphinIconsView::contentsDragEnterEvent(TQDragEnterEvent* 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() == TQDropEvent::Copy ||
event->action() == TQDropEvent::Move ||
event->action() == TQDropEvent::Link );
if (accept) {
event->acceptAction();
}
else {
event->ignore();
}
}
void DolphinIconsView::contentsDragMoveEvent(TQDragMoveEvent* 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(TQDropEvent* 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() == TQDropEvent::Copy ||
event->action() == TQDropEvent::Move ||
event->action() == TQDropEvent::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(TQIconViewItem* 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(TQIconViewItem* item,
const TQPoint& pos)
{
KFileItem* fileInfo = 0;
if (item != 0) {
fileInfo = static_cast<KFileIconViewItem*>(item)->fileInfo();
}
m_dolphinView->openContextMenu(fileInfo, pos);
}
void DolphinIconsView::slotItemRenamed(TQIconViewItem* item,
const TQString& 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 TQObjectList list = childrenListObject();
if (list.isEmpty()) {
return;
}
TQObjectListIterator it(list);
TQObject* object = 0;
while ((object = it.current()) != 0) {
if (object->inherits("TQWidget")) {
TQWidget* widget = static_cast<TQWidget*>(object);
widget->update();
}
++it;
}
}
void DolphinIconsView::slotUpdateDisabledItems()
{
updateDisabledItems();
}
int DolphinIconsView::increasedIconSize(int size) const
{
int incSize = 0;
switch (size) {
case TDEIcon::SizeSmall: incSize = TDEIcon::SizeSmallMedium; break;
case TDEIcon::SizeSmallMedium: incSize = TDEIcon::SizeMedium; break;
case TDEIcon::SizeMedium: incSize = TDEIcon::SizeLarge; break;
case TDEIcon::SizeLarge: incSize = TDEIcon::SizeHuge; break;
case TDEIcon::SizeHuge: incSize = TDEIcon::SizeEnormous; break;
default: assert(false); break;
}
return incSize;
}
int DolphinIconsView::decreasedIconSize(int size) const
{
int decSize = 0;
switch (size) {
case TDEIcon::SizeSmallMedium: decSize = TDEIcon::SizeSmall; break;
case TDEIcon::SizeMedium: decSize = TDEIcon::SizeSmallMedium; break;
case TDEIcon::SizeLarge: decSize = TDEIcon::SizeMedium; break;
case TDEIcon::SizeHuge: decSize = TDEIcon::SizeLarge; break;
case TDEIcon::SizeEnormous: decSize = TDEIcon::SizeHuge; break;
default: assert(false); break;
}
return decSize;
}
#include "dolphiniconsview.moc"