#include <QPainter>
#include <QPixmapCache>
#include <QTimerEvent>
#include <QKeyEvent>
#include <QImageReader>
#include <QDir>
#include <QTimer>
#include <QLabel>
#include "iconview.h"
IconView::IconView(QWidget *parent) : QWidget(parent)
{
paintTimerId = 0;
thumbTimerId = 0;
index = 0;
changeDirectory("Internal");
QPixmapCache::setCacheLimit(64000);
QPixmapCache::insert("folder", QPixmap("icons/b/folder.png"));
QPixmapCache::insert("thumb", QPixmap("icons/b/thumb.png"));
curItemX = 0;
curItemY = 0;
offset = 0;
}
IconView::~IconView()
{
}
void IconView::changeDirectory(QString dirStr)
{
if (paintTimerId)
killTimer(paintTimerId);
if (thumbTimerId)
killTimer(thumbTimerId);
paintTimerId = 0;
thumbTimerId = 0;
QDir d1("photos/" + dirStr);
dirStr = d1.absolutePath();
QDir d2("photos");
directory = d2.relativeFilePath(dirStr);
index = 0;
curItemX = -1;
curItemY = -1;
offset = 0;
repaint();
if ( !QFile::exists("photos/" + directory) )
return;
emit directoryChanged(directory);
dir = QDir("photos/" + directory);
dir.setSorting(QDir::Name | QDir::DirsFirst);
entryList = dir.entryList();
entryInfoList = dir.entryInfoList();
QPixmap folder = QPixmap("icons/b/folder.png");
QPixmap thumb = QPixmap("icons/b/thumb.png");
QPixmap back = QPixmap("icons/b/back.png");
QFont font("Arial",11);
for (int i = 0; i < (int)dir.count(); i++) {
QFileInfo fi = entryInfoList[i];
QString filename = "photos/" + directory + "/" + fi.fileName();
QPixmap dummy(88,68);
if (!QPixmapCache::find(filename, dummy)) {
dummy.fill(QColor(0,0,0,0));
QPainter p(&dummy);
p.setPen(Qt::NoPen);
p.setBrush(QColor(178,178,178,64));
p.drawRect(0, 0, 88, 68);
QString label = fi.fileName();
if ( fi.isFile() ) {
p.drawPixmap(20, 3, thumb);
} else if ( fi.isDir() ) {
if (label == "..") {
label = "Up";
p.drawPixmap(20, 3, back);
} else {
p.drawPixmap(20, 3, folder);
}
}
QFontMetrics fm(font);
p.setFont(font);
QString str = fm.elidedText(label, Qt::ElideRight, 88);
int w = fm.width(str);
p.setPen(QColor(64,64,64));
p.drawText((88-w)/2+1, 66, str);
p.setPen(Qt::white);
p.drawText((88-w)/2, 65, str);
p.end();
QPixmapCache::insert(filename, dummy);
}
}
thumbTimerId = startTimer(5);
paintTimerId = startTimer(30);
}
static QPixmap loadThumbnail(QString filename, QSize size)
{
QPixmap thumb;
ExifLoader *loader = exif_loader_new();
if ( !loader )
return thumb;
exif_loader_write_file(loader, filename.toLatin1().data());
ExifData *ed = exif_loader_get_data(loader);
if (ed && ed->data && ed->size) {
thumb.loadFromData(ed->data, ed->size);
thumb = thumb.scaled(size.width(), size.height());
} else {
QImageReader iio(filename);
iio.setScaledSize(size);
iio.setQuality(0);
QImage img = iio.read();
if ( img.isNull() )
return thumb;
thumb = thumb.fromImage(img);
}
exif_data_unref(ed);
exif_loader_unref(loader);
return thumb;
}
void IconView::timerEvent(QTimerEvent *te)
{
if (te->timerId() == thumbTimerId) {
for (int i = 0; i < 4; i++) {
QFileInfo fi = entryInfoList[index];
QString filename = "photos/" + directory + "/" + fi.fileName();
if ( fi.isFile() ) {
QPixmap thumb = loadThumbnail(filename, QSize(88,68));
if (!thumb.isNull())
QPixmapCache::insert(filename, thumb);
}
index++;
if (index >= dir.count()) {
killTimer(thumbTimerId);
thumbTimerId = 0;
return;
}
/*
else if (index >= 21 ) {
killTimer(thumbTimerId);
thumbTimerId = startTimer(200);
}
*/
}
} else if (te->timerId() == paintTimerId) {
update();
if (index >= offset + 30 || index >= dir.count()) {
// deliberately seperate to the killTimer for thumbTimerId
// because doing it here will allow the last update() to happpen
killTimer(paintTimerId);
paintTimerId = 0;
}
}
}
void IconView::setFocusItem(int x, int y)
{
curItemX = x;
curItemY = y;
offset = 1;
repaint();
}
class FadeInOutPreview : public QWidget
{
public:
int speed;
bool autoOut;
FadeInOutPreview(QWidget *parent, QString file, int _x, int _y, int exp, int s, bool ao = false) : QWidget(parent) {
expandFactor = exp;
autoOut = ao;
speed = s;
tick = 0;
x = _x;
y = _y;
pix = QPixmap(file);
QSize size = pix.size();
size.scale(600,350,Qt::KeepAspectRatio);
pix = pix.scaled(size);
setGeometry(0, 0, 800, 480);
//QTimer::singleShot(2000, this, SLOT(deleteLater()));
fadeInId = 0;
fadeOutId = 0;
tmp = 0;
}
~FadeInOutPreview() { }
void fadeIn() {
show();
fadeInId = startTimer(speed);
}
void fadeOut() {
fadeOutId = startTimer(speed);
}
int fadeInId;
int fadeOutId;
int tmp;
void timerEvent(QTimerEvent *te) {
if (te->timerId() == fadeInId) {
tick++;
if (tick > 30) {
tick = 30;
tmp++;
if (tmp > 40) {
killTimer(fadeInId);
fadeInId = 0;
if (autoOut)
fadeOut();
}
}
}
if (te->timerId() == fadeOutId) {
tick++;
if ( tick > 60 ) {
hide();
killTimer(fadeOutId);
fadeOutId = 0;
}
}
update();
}
void paintEvent(QPaintEvent *pe) {
QPainter p(this);
QPixmap p2;
QSize size = pix.size();
float ratio = 1.0;
float fadeRatio = 1.0;
if ( tick < 20 - expandFactor ) {
ratio = tick / 20.0;
} else if ( tick < 40 + expandFactor ) {
ratio = (60.0 - 40 - expandFactor) / 20.0;
} else {
ratio = (60.0 - tick) / 20.0;
}
if ( tick < 20 ) {
fadeRatio = tick / 20.0;
} else if ( tick < 40 ) {
fadeRatio = 1.0;
} else {
fadeRatio = (60.0 - tick) / 20.0;
}
size.scale(ratio*(800-90)+90, ratio*(480-70)+70, Qt::KeepAspectRatio);
p2 = pix.scaled(size);
int _x = -15+(1.0-ratio)*x+((ratio*(800-90)+90)/2)-size.width()/2;
int _y = -15+(1.0-ratio)*y+((ratio*(480-70)+70)/2)-size.height()/2;
p.setPen(Qt::NoPen);
p.setBrush(QColor(32,32,32,128));
p.drawRect(12 + _x, 12 + _y, size.width(), size.height());
p.setOpacity(fadeRatio);
p.drawPixmap(_x, _y, p2);
}
QPixmap pix;
int tick;
int x, y;
int expandFactor;
};
void IconView::keyPressEvent(QKeyEvent *ke)
{
/*
static FadeInOutPreview *oldI = 0;
static FadeInOutPreview *newI = 0;
static int oldCurItemX = 0;
static int oldCurItemY = 0;
QString filename = "photos/" + directory + "/" + entryList[curItemX+curItemY*5+offset];
if (oldI)
oldI->deleteLater();
oldI = new FadeInOutPreview(parentWidget(), filename, curItemX*100+320, curItemY*80+180, 17, 1);
oldI->fadeIn();
oldCurItemX = curItemX;
oldCurItemY = curItemY;
*/
if (ke->key() == Qt::Key_Down) {
if ( dir.count() > (offset + curItemX + curItemY * 5 + 5) )
curItemY++;
if (curItemY > 3) {
curItemY = 3;
if ( dir.count() - offset >= 21 + curItemX ) {
offset += 5;
}
}
}
if (ke->key() == Qt::Key_Right) {
if ( dir.count() > (offset + curItemX + curItemY * 5 + 1) )
curItemX++;
if (curItemX > 4) {
if (curItemY > 2) {
if ( dir.count() - offset <= 20 ) {
curItemX = 4;
curItemY = 3;
} else {
curItemX = 0;
curItemY = 3;
offset += 5;
}
} else {
curItemX = 0;
curItemY++;
}
}
}
if (ke->key() == Qt::Key_Up) {
curItemY--;
if (curItemY < 0) {
curItemY = 0;
if ( offset > 5 ) {
offset -= 5;
}
}
}
if (ke->key() == Qt::Key_Left) {
curItemX--;
if (curItemX < -1) {
curItemX = -1;
}
if (curItemX == -1) {
if (curItemY == 0) {
if ( offset > 5 ) {
curItemX = 4;
offset -= 5;
} else {
emit switchFocus();
}
} else {
curItemY--;
curItemX = 4;
}
}
}
/*
if ( curItemX != oldCurItemX || curItemY != oldCurItemY ) {
oldI->fadeOut();
if (newI)
newI->deleteLater();
QString filename = "photos/" + directory + "/" + entryList[curItemX+curItemY*5+offset];
newI = new FadeInOutPreview(parentWidget(), filename, curItemX*100+320, curItemY*80+180, 17, 1);
newI->fadeIn();
oldCurItemX = curItemX;
oldCurItemY = curItemY;
FadeInOutPreview *oldITmp = oldI;
oldI = newI;
newI = oldITmp;
}
*/
if (ke->key() == Qt::Key_Return) {
QString filename = "photos/" + directory + "/" + entryList[curItemX+curItemY*5+offset];
if (QFileInfo(filename).isDir()) {
changeDirectory(directory + "/" + entryList[curItemX+curItemY*5+offset]);
setFocusItem(0,0);
} else {
// QPoint topLeft = mapToGlobal(QPoint(0,0));
int _x = 280;//topLeft.x();
int _y = 140;//topLeft.y();
FadeInOutPreview *tmp = new FadeInOutPreview(parentWidget(), filename, curItemX*100+_x, curItemY*80+_y, 3, 3, true);
// FadeInOutPreview *tmp = new FadeInOutPreview(parentWidget(), filename, curItemX*100+320, curItemY*80+180, 13, 5, true);
tmp->fadeIn();
/*
static QLabel *lab = 0;
if (lab) {
lab->hide();
delete lab;
}
lab = new QLabel(parentWidget());
QPixmap pix = QPixmap(filename);
QSize size = pix.size();
size.scale(700,380,Qt::KeepAspectRatio);
pix.fill(QColor(0,0,0,0));
QPainter p(&pix);
p.setOpacity(0.8);
p.drawPixmap(0, 0, QPixmap(filename));
p.end();
lab->setPixmap(pix.scaled(size));
lab->setGeometry((800 - size.width()) / 2, (480 - size.height()) / 2, size.width(), size.height());
lab->show();
QTimer::singleShot(2000, lab, SLOT(hide()));
*/
}
}
repaint();
}
void IconView::paintEvent(QPaintEvent *pe)
{
QPainter p(this);
p.setPen(QColor(32,32,64));
for (int y = 0; y < 320; y+=80)
for (int x = 0; x < 500; x+=100)
p.drawRect(x, y, 90, 70);
p.setPen(QColor(178,178,255));
for (int y = 1; y < 321; y+=80)
for (int x = 1; x < 501; x+=100)
p.drawRect(x, y, 90, 70);
p.setPen(Qt::NoPen);
p.setBrush(QColor(178,178,178,64));
for (int y = 2; y < 322; y+=80)
for (int x = 2; x < 502; x+=100)
p.drawRect(x, y, 88, 68);
int x2 = curItemX * 100;
int y2 = curItemY * 80;
if (x2 >= 0) {
p.setPen(QColor(255,255,255));
p.drawRect(x2, y2, 88+2, 68+2);
p.drawRect(x2, y2, 88+3, 68+3);
}
int i = offset;
for (int y = 0; y < 4; y++)
for (int x = 0; x < 5; x++) {
QPixmap thumb;
if ( (int)dir.count() > i ) {
if ( entryList[i] == "." )
i++;
QString filename = "photos/" + directory + "/" + entryList[i];
if (QPixmapCache::find(filename, thumb)) {
p.drawPixmap(x*100+2, y*80+2, thumb.scaled(88,68));
//} else {
//p.drawPixmap(x*100+2, y*80+2, QPixmap(filename).scaled(88,68));
}
i++;
}
}
if (x2 >= 0) {
p.setPen(Qt::NoPen);
QRadialGradient g1(x2+80,y2-45,80,x2+60,y2-2);
g1.setColorAt(0,QColor(255,255,255,255));
g1.setColorAt(1,QColor(255,255,255,12));
p.setBrush(g1);
p.drawRect(x2+2, y2+2, 88, 68);
QRadialGradient g2(x2+50,y2-50,140,x2+90,y2+50);
g2.setColorAt(0,QColor(255,255,255,0));
g2.setColorAt(0.50,QColor(255,255,255,0));
g2.setColorAt(0.51,QColor(200,200,245,100));
g2.setColorAt(1,QColor(200,200,245,100));
p.setBrush(g2);
p.drawRect(x2+2, y2+2, 88, 68);
}
}