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.
550 lines
14 KiB
550 lines
14 KiB
/***************************************************************************
|
|
sq_fileiconview.cpp - description
|
|
-------------------
|
|
begin : Mon Mar 15 2004
|
|
copyright : (C) 2004 by Baryshev Dmitry
|
|
email : ksquirrel.iv@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 *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include <tqpainter.h>
|
|
#include <tqhbox.h>
|
|
#include <tqtoolbar.h>
|
|
#include <tqtoolbutton.h>
|
|
#include <tqlabel.h>
|
|
#include <tqtimer.h>
|
|
#include <tqapplication.h>
|
|
|
|
#include <kstandarddirs.h>
|
|
#include <kstringhandler.h>
|
|
#include <kglobalsettings.h>
|
|
#include <klocale.h>
|
|
#include <kapplication.h>
|
|
#include <kglobal.h>
|
|
|
|
#include "ksquirrel.h"
|
|
#include "sq_iconloader.h"
|
|
#include "sq_config.h"
|
|
#include "sq_dir.h"
|
|
#include "sq_filethumbview.h"
|
|
#include "sq_libraryhandler.h"
|
|
#include "sq_thumbnailloadjob.h"
|
|
#include "sq_thumbnailsize.h"
|
|
#include "sq_widgetstack.h"
|
|
#include "sq_diroperator.h"
|
|
#include "sq_progress.h"
|
|
#include "sq_progressbox.h"
|
|
#include "sq_filethumbviewitem.h"
|
|
#include "sq_dragprovider.h"
|
|
|
|
SQ_FileThumbView::SQ_FileThumbView(TQWidget *parent, const char *name) : SQ_FileIconViewBase(parent, name), isPending(false)
|
|
{
|
|
// create progress bar
|
|
m_progressBox = new SQ_ProgressBox(this);
|
|
|
|
timerScroll = new TQTimer(this);
|
|
connect(timerScroll, TQT_SIGNAL(timeout()), this, TQT_SLOT(slotDelayedContentsMoving()));
|
|
|
|
timerAdd = new TQTimer(this);
|
|
connect(timerAdd, TQT_SIGNAL(timeout()), this, TQT_SLOT(slotDelayedAddItems()));
|
|
|
|
// setup cache limit
|
|
SQ_Config::instance()->setGroup("Thumbnails");
|
|
m_lazy = SQ_Config::instance()->readBoolEntry("lazy", true);
|
|
lazyDelay = SQ_Config::instance()->readNumEntry("lazy_delay", 500);
|
|
if(lazyDelay <= 0) lazyDelay = 500;
|
|
m_rows = SQ_Config::instance()->readNumEntry("rows", 2);
|
|
if(m_rows <= 0 || m_rows > 5) m_rows = 2;
|
|
|
|
setResizeMode(TQIconView::Adjust);
|
|
|
|
// load "pending" pixmaps
|
|
pending = SQ_IconLoader::instance()->loadIcon("clock", KIcon::Desktop, 32);
|
|
|
|
connect(this, TQT_SIGNAL(contentsMoving(int, int)), this, TQT_SLOT(slotContentsMoving(int, int)));
|
|
|
|
rebuildCachedPixmaps();
|
|
}
|
|
|
|
SQ_FileThumbView::~SQ_FileThumbView()
|
|
{}
|
|
|
|
/*
|
|
* Reimplement insertItem() to enable/disable inserting
|
|
* directories (depends on current settings) and inserting thumbnails.
|
|
*/
|
|
void SQ_FileThumbView::insertItem(KFileItem *i)
|
|
{
|
|
SQ_Config::instance()->setGroup("Fileview");
|
|
|
|
// directores disabled ?
|
|
if(i->isDir() && SQ_Config::instance()->readBoolEntry("disable_dirs", false))
|
|
return;
|
|
|
|
SQ_Config::instance()->setGroup("Thumbnails");
|
|
|
|
SQ_FileThumbViewItem *item;
|
|
|
|
setUpdatesEnabled(false);
|
|
if(SQ_Config::instance()->readBoolEntry("mark", false) && SQ_LibraryHandler::instance()->libraryForFile(i->url().path()))
|
|
{
|
|
item = new SQ_FileThumbViewItem(this, i->text(), pendingCache, i);
|
|
}
|
|
else
|
|
{
|
|
TQPixmap mimeall = i->pixmap(SQ_ThumbnailSize::smallest());
|
|
TQPixmap thumbnail(pixelSize.width(), pixelSize.height());
|
|
TQPainter painter(&thumbnail);
|
|
painter.setBrush(colorGroup().base());
|
|
painter.setPen(colorGroup().highlight());
|
|
painter.drawRect(0, 0, pixelSize.width(), pixelSize.height());
|
|
painter.drawPixmap((pixelSize.width()-mimeall.width())/2, (pixelSize.height()-mimeall.height())/2, mimeall);
|
|
item = new SQ_FileThumbViewItem(this, i->text(), thumbnail, i);
|
|
}
|
|
|
|
initItemMy(item, i);
|
|
|
|
i->setExtraData(this, item);
|
|
setUpdatesEnabled(true);
|
|
}
|
|
|
|
/*
|
|
* One thumbnail is loaded. Let's update KFileItem's pixmap.
|
|
*/
|
|
void SQ_FileThumbView::setThumbnailPixmap(const KFileItem* fileItem, const SQ_Thumbnail &t)
|
|
{
|
|
KFileIconViewItem *iconItem = viewItem(fileItem);
|
|
|
|
if(!iconItem) return;
|
|
|
|
SQ_FileThumbViewItem *item = static_cast<SQ_FileThumbViewItem*>(iconItem);
|
|
|
|
if(!item) return;
|
|
|
|
TQPixmap newpix;
|
|
|
|
// Extended thumbnail also have mime icon and dimensions
|
|
if(SQ_ThumbnailSize::instance()->extended())
|
|
{
|
|
TQSize sz = pixelSize;//SQ_ThumbnailSize::instance()->extendedSize();
|
|
int W = sz.width(), H = sz.height();
|
|
|
|
// erase original pixmap
|
|
newpix.resize(W, H);
|
|
|
|
TQPainter painter;
|
|
painter.begin(&newpix);
|
|
|
|
painter.setPen(colorGroup().highlight());
|
|
painter.setBrush(colorGroup().base());
|
|
|
|
// draw bounding rect
|
|
painter.drawRect(0, 0, W, H);
|
|
|
|
painter.drawImage((W - t.thumbnail.width())/2, (W - t.thumbnail.height())/2, t.thumbnail);
|
|
painter.drawPixmap(W-t.mime.width()-5, H-t.mime.height()-4, t.mime);
|
|
painter.drawLine(3, W-1, W-4, W-1);
|
|
|
|
TQFont f = painter.font();
|
|
f.setPixelSize(10);
|
|
painter.setFont(f);
|
|
|
|
int rest = H-W-2;
|
|
|
|
painter.setPen(colorGroup().text());
|
|
|
|
if(t.w && t.h) painter.drawText(4, W+rest/2-12, 100, 12, 0, TQString::fromLatin1("%1x%2").arg(t.w).arg(t.h));
|
|
|
|
painter.drawText(4, W+rest/2+1, 100, 12, 0, KIO::convertSize(fileItem->size()));
|
|
painter.end();
|
|
}
|
|
else
|
|
{
|
|
newpix.resize(pixelSize.width(), pixelSize.height());
|
|
|
|
TQPainter painter;
|
|
painter.begin(&newpix);
|
|
|
|
painter.setPen(colorGroup().highlight());
|
|
painter.setBrush(colorGroup().base());
|
|
|
|
// draw bounding rect
|
|
painter.drawRect(0, 0, pixelSize.width(), pixelSize.height());
|
|
|
|
// draw pixmap
|
|
painter.drawImage((pixelSize.width() - t.thumbnail.width())/2, (pixelSize.height() - t.thumbnail.height())/2, t.thumbnail);
|
|
painter.end();
|
|
}
|
|
|
|
item->setPixmap(newpix);
|
|
item->setListed(true);
|
|
|
|
// update item
|
|
item->repaint();
|
|
}
|
|
|
|
void SQ_FileThumbView::startThumbnailUpdate()
|
|
{
|
|
stopThumbnailUpdate();
|
|
doStartThumbnailUpdate(itemsToUpdate());
|
|
}
|
|
|
|
KFileItemList SQ_FileThumbView::itemsToUpdate(bool fromAll)
|
|
{
|
|
// non-lazy mode - simply return all items
|
|
if(!m_lazy)
|
|
return *items();
|
|
|
|
// hehe, lazy mode
|
|
KFileItemList list;
|
|
|
|
TQRect rect(contentsX(), contentsY(), viewport()->width(), viewport()->height());
|
|
TQIconViewItem *first = fromAll ? firstItem() : findFirstVisibleItem(rect);
|
|
TQIconViewItem *last = fromAll ? lastItem() : findLastVisibleItem(rect);
|
|
|
|
if(first && last)
|
|
{
|
|
SQ_FileThumbViewItem *tfi;
|
|
|
|
TQIconViewItem *f = first;
|
|
int yy;
|
|
|
|
if(m_rows)
|
|
{
|
|
// one row more up and down
|
|
for(int i = 0;i < m_rows;++i)
|
|
{
|
|
if(!last) break;
|
|
|
|
last = last->nextItem();
|
|
|
|
if(last)
|
|
{
|
|
yy = last->y();
|
|
|
|
while((last = last->nextItem()) && last->y() == yy)
|
|
{}
|
|
}
|
|
}
|
|
|
|
for(int i = 0;i < m_rows;++i)
|
|
{
|
|
f = first->prevItem();
|
|
|
|
if(f)
|
|
{
|
|
yy = f->y();
|
|
|
|
while((f = first->prevItem()) && f->y() == yy)
|
|
first = f;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
last = last->nextItem();
|
|
|
|
for(TQIconViewItem *item = first;(item && item != last);item = item->nextItem())
|
|
{
|
|
tfi = dynamic_cast<SQ_FileThumbViewItem *>(item);
|
|
|
|
if(tfi && !tfi->listed())
|
|
list.append(tfi->fileInfo());
|
|
}
|
|
}
|
|
|
|
return list;
|
|
}
|
|
|
|
void SQ_FileThumbView::slotContentsMoving(int, int)
|
|
{
|
|
if(isVisible())
|
|
timerScroll->start(lazyDelay, true);
|
|
else
|
|
waitForShowEvent();
|
|
}
|
|
|
|
void SQ_FileThumbView::slotDelayedContentsMoving()
|
|
{
|
|
// restart generator in lazy mode
|
|
if(m_lazy)
|
|
{
|
|
stopThumbnailUpdate();
|
|
doStartThumbnailUpdate(itemsToUpdate());
|
|
}
|
|
// make visible items first items in the job
|
|
else
|
|
{
|
|
// force itemsToUpdate() return only visible items
|
|
// that need update
|
|
m_lazy = true;
|
|
KFileItemList visibleItems = itemsToUpdate();
|
|
|
|
if(updateRunning())
|
|
thumbJob->pop(visibleItems);
|
|
|
|
// restore lazy mode
|
|
m_lazy = false;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Create job, connect signals and start updating
|
|
*/
|
|
void SQ_FileThumbView::doStartThumbnailUpdate(const KFileItemList &list)
|
|
{
|
|
if(list.isEmpty())
|
|
return;
|
|
|
|
// update progress bar
|
|
SQ_WidgetStack::instance()->thumbnailUpdateStart(list.count());
|
|
|
|
// create new job
|
|
thumbJob = new SQ_ThumbnailLoadJob(list, this);
|
|
|
|
connect(thumbJob, TQT_SIGNAL(thumbnailLoaded(const KFileItem*, const SQ_Thumbnail &)),
|
|
this, TQT_SLOT(setThumbnailPixmap(const KFileItem*, const SQ_Thumbnail&)));
|
|
|
|
connect(thumbJob, TQT_SIGNAL(done()), SQ_WidgetStack::instance(), TQT_SLOT(thumbnailsUpdateEnded()));
|
|
|
|
// start!
|
|
thumbJob->start();
|
|
}
|
|
|
|
// Stop thumbnail update: delete job, reset progress bar
|
|
void SQ_FileThumbView::stopThumbnailUpdate()
|
|
{
|
|
timerScroll->stop();
|
|
timerAdd->stop();
|
|
newItems.clear();
|
|
|
|
if(!thumbJob.isNull())
|
|
{
|
|
thumbJob->kill();
|
|
SQ_WidgetStack::instance()->thumbnailsUpdateEnded();
|
|
}
|
|
}
|
|
|
|
// Start/stop thumbnail job
|
|
void SQ_FileThumbView::slotThumbnailUpdateToggle()
|
|
{
|
|
if(!thumbJob.isNull())
|
|
stopThumbnailUpdate();
|
|
else
|
|
startThumbnailUpdate();
|
|
}
|
|
|
|
/*
|
|
* Append new items to thumbnail generating job.
|
|
*/
|
|
void SQ_FileThumbView::addItemsToJob(const KFileItemList &items, bool append)
|
|
{
|
|
newItemsAppend = append;
|
|
|
|
KFileItemListIterator it(items);
|
|
KFileItem *fi;
|
|
|
|
while((fi = it.current()))
|
|
{
|
|
newItems.append(fi);
|
|
++it;
|
|
}
|
|
|
|
// don't confuse user with multiple updates
|
|
timerAdd->start(500, true);
|
|
}
|
|
|
|
void SQ_FileThumbView::slotDelayedAddItems()
|
|
{
|
|
KFileItemList _newItems = newItems;
|
|
newItems.clear();
|
|
|
|
if(m_lazy)
|
|
{
|
|
KFileItemList visItems = itemsToUpdate();
|
|
KFileItemListIterator it(_newItems);
|
|
KFileItem *fi;
|
|
|
|
while((fi = it.current()))
|
|
{
|
|
if(visItems.findRef(fi) == -1)
|
|
_newItems.removeRef(fi); // also does ++it
|
|
else
|
|
++it;
|
|
}
|
|
}
|
|
|
|
// job is not running
|
|
if(thumbJob.isNull())
|
|
doStartThumbnailUpdate(_newItems);
|
|
// add new items to running job
|
|
else
|
|
{
|
|
m_progressBox->addSteps(_newItems.count());
|
|
|
|
if(newItemsAppend)
|
|
thumbJob->appendItems(_newItems);
|
|
else
|
|
thumbJob->prependItems(_newItems);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Clear current view and insert "..".
|
|
*/
|
|
void SQ_FileThumbView::clearView()
|
|
{
|
|
// stop job
|
|
stopThumbnailUpdate();
|
|
slotRemoveToolTip();
|
|
|
|
pixelSize = SQ_ThumbnailSize::instance()->extended() ?
|
|
SQ_ThumbnailSize::instance()->extendedSize() : TQSize(SQ_ThumbnailSize::instance()->pixelSize()+2,SQ_ThumbnailSize::instance()->pixelSize()+2);
|
|
|
|
// clear
|
|
KFileIconView::clearView();
|
|
|
|
// insert ".."
|
|
insertCdUpItem(SQ_WidgetStack::instance()->url());
|
|
}
|
|
|
|
/*
|
|
* Is thumbnail job running ?
|
|
*/
|
|
bool SQ_FileThumbView::updateRunning() const
|
|
{
|
|
return !thumbJob.isNull();
|
|
}
|
|
|
|
/*
|
|
* Insert ".." item.
|
|
*/
|
|
void SQ_FileThumbView::insertCdUpItem(const KURL &base)
|
|
{
|
|
static const TQString &dirup = KGlobal::staticQString("..");
|
|
|
|
KFileItem *fi = new KFileItem(base.upURL(), "inode/directory", S_IFDIR);
|
|
|
|
// insert new item
|
|
SQ_FileThumbViewItem *item = new SQ_FileThumbViewItem(this, dirup, directoryCache, fi);
|
|
|
|
// item ".." won't be selectable
|
|
item->setSelectable(false);
|
|
|
|
fi->setExtraData(this, item);
|
|
}
|
|
|
|
/*
|
|
* All files are listed. Do something important.
|
|
*/
|
|
void SQ_FileThumbView::listingCompleted()
|
|
{
|
|
arrangeItemsInGrid();
|
|
}
|
|
|
|
void SQ_FileThumbView::rebuildPendingPixmap(bool dir)
|
|
{
|
|
TQPixmap pixmapDir;
|
|
|
|
if(dir)
|
|
pixmapDir = SQ_IconLoader::instance()->loadIcon("folder", KIcon::Desktop, 48);
|
|
|
|
TQPixmap *p = dir ? &directoryCache : &pendingCache;
|
|
TQPixmap *w = dir ? &pixmapDir : &pending;
|
|
|
|
p->resize(pixelSize.width(), pixelSize.height());
|
|
|
|
TQPainter painter(p);
|
|
painter.setBrush(colorGroup().base());
|
|
painter.setPen(colorGroup().highlight());
|
|
painter.drawRect(0, 0, pixelSize.width(), pixelSize.height());
|
|
painter.drawPixmap((pixelSize.width() - w->width())/2, (pixelSize.height() - w->height())/2, *w);
|
|
}
|
|
|
|
void SQ_FileThumbView::rebuildCachedPixmaps()
|
|
{
|
|
pixelSize = SQ_ThumbnailSize::instance()->extended() ?
|
|
SQ_ThumbnailSize::instance()->extendedSize() : TQSize(SQ_ThumbnailSize::instance()->pixelSize()+2,SQ_ThumbnailSize::instance()->pixelSize()+2);
|
|
|
|
// rebuild "pending" thumbnail
|
|
rebuildPendingPixmap();
|
|
|
|
// rebuild directory pixmap
|
|
rebuildPendingPixmap(true);
|
|
}
|
|
|
|
void SQ_FileThumbView::itemRemoved(KFileItem *i)
|
|
{
|
|
thumbJob->itemRemoved(i);
|
|
}
|
|
|
|
void SQ_FileThumbView::itemsRemoved(const KFileItemList &l)
|
|
{
|
|
thumbJob->itemsRemoved(l);
|
|
}
|
|
|
|
void SQ_FileThumbView::showEvent(TQShowEvent *e)
|
|
{
|
|
KFileIconView::showEvent(e);
|
|
|
|
if(isPending)
|
|
{
|
|
isPending = false;
|
|
startThumbnailUpdate();
|
|
}
|
|
}
|
|
|
|
void SQ_FileThumbView::startDrag()
|
|
{
|
|
SQ_Config::instance()->setGroup("Fileview");
|
|
|
|
if(SQ_Config::instance()->readBoolEntry("drag", true))
|
|
{
|
|
SQ_DragProvider::instance()->setParams(this, *KFileView::selectedItems(), SQ_DragProvider::Thumbnails);
|
|
SQ_DragProvider::instance()->start();
|
|
}
|
|
else
|
|
KFileIconView::startDrag();
|
|
}
|
|
|
|
void SQ_FileThumbView::setLazy(bool l, int delay)
|
|
{
|
|
m_lazy = l;
|
|
lazyDelay = delay <= 0 ? 500 : delay;
|
|
|
|
// non-lazy mode requires to update all thumbnails
|
|
if(!m_lazy)
|
|
{
|
|
m_lazy = true;
|
|
|
|
stopThumbnailUpdate();
|
|
doStartThumbnailUpdate(itemsToUpdate(true));
|
|
|
|
// restore lazy mode
|
|
m_lazy = false;
|
|
}
|
|
}
|
|
|
|
void SQ_FileThumbView::resizeEvent(TQResizeEvent *e)
|
|
{
|
|
KFileIconView::resizeEvent(e);
|
|
|
|
if(isVisible())
|
|
timerScroll->start(lazyDelay, true);
|
|
else
|
|
waitForShowEvent();
|
|
}
|
|
|
|
#include "sq_filethumbview.moc"
|