1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
|
/***************************************************************************
* *
* This file is part of the Fotowall project, *
* http://www.enricoros.com/opensource/fotowall *
* *
* Copyright (C) 2009 by Enrico Ros <enrico.ros@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. *
* *
***************************************************************************/
#include "UrlHistoryBox.h"
#include "Canvas/Canvas.h"
#include "Shared/GlowEffectWidget.h"
#include "Shared/PixmapButton.h"
#include "FotowallFile.h"
#include <QHBoxLayout>
#include <QFile>
#include <QMenu>
#include <QTimer>
#include <QVariant>
UrlHistoryBox::UrlHistoryBox(const QList<QUrl> &urls, QWidget *parent)
: GroupBoxWidget(parent)
, m_previewIndex(0)
{
// create this layout
QHBoxLayout * lay = new QHBoxLayout(this);
lay->setContentsMargins(2, 0, 0, 0);
lay->setSpacing(0);
setLayout(lay);
// set initial urls, if given
if (!urls.isEmpty())
changeUrls(urls, true);
}
UrlHistoryBox::~UrlHistoryBox()
{
qDeleteAll(m_entries);
m_entries.clear();
}
void UrlHistoryBox::changeUrls(const QList<QUrl> & urls, bool delayPreview)
{
// remove previous icons, if any
qDeleteAll(m_entries);
m_entries.clear();
if (urls.isEmpty())
return;
// add buttons
for (int i = 0; i < qMin(5, urls.size()); i++) {
const QUrl & url = urls[i];
PixmapButton * button = new PixmapButton(this);
connect(button, SIGNAL(clicked()), this, SLOT(slotClicked()));
connect(button, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(slotContextMenu(const QPoint &)));
button->setFixedSize(QSize(64, 60));
button->setContextMenuPolicy(Qt::CustomContextMenu);
button->setProperty("url", url);
button->setHoverText(QString::number(i+1));
button->setToolTip(url.toString());
int mag = (qrand() % 7) + (qrand() % 7);
static bool dir = true; dir = !dir;
int angle = dir ? mag : -mag;
button->setProperty("angle", angle);
layout()->addWidget(button);
m_entries.append(button);
if (delayPreview) {
#if 0
QImage img(48, 48, QImage::Format_ARGB32_Premultiplied);
img.fill(0xFF808080);
button->setPixmap(prettyPixmap(img, angle));
#endif
} else
genPreview(button);
}
// start preview jobs
if (delayPreview) {
m_previewIndex = 0;
QTimer::singleShot(100, this, SLOT(slotNextPreview()));
}
}
QUrl UrlHistoryBox::urlForEntry(int index) const
{
if (index < 0 || index >= m_entries.size())
return QUrl();
return m_entries[index]->property("url").toUrl();
}
QPixmap UrlHistoryBox::prettyPixmap(const QImage & image, int angle)
{
QTransform rot;
rot.rotate(angle);
const QImage rotated = image.transformed(rot, Qt::SmoothTransformation);
const QImage shadowed = GlowEffectWidget::dropShadow(rotated, QColor(64, 64, 64), 6, 1, 1);
return QPixmap::fromImage(shadowed);
}
void UrlHistoryBox::genPreview(PixmapButton * button)
{
QUrl currentUrl = button->property("url").toUrl();
QString fwFilePath = currentUrl.toString();
// get the embedded preview
QImage previewImage = FotowallFile::embeddedPreview(fwFilePath);
// generate preview
if (previewImage.isNull()) {
Canvas * canvas = new Canvas(physicalDpiX(), physicalDpiY(), this);
if (FotowallFile::read(fwFilePath, canvas, false)) {
// render canvas, rotate, drop shadow and set
canvas->resizeAutoFit();
canvas->setEmbeddedPainting(true);
previewImage = canvas->renderedImage(QSize(48, 48), Qt::KeepAspectRatio, true);
}
delete canvas;
}
// make a pretty preview (rotated and shadowed)
if (!previewImage.isNull()) {
int angle = button->property("angle").toInt();
button->setPixmap(prettyPixmap(previewImage, angle));
}
}
void UrlHistoryBox::slotClicked()
{
emit urlClicked(sender()->property("url").toUrl());
}
void UrlHistoryBox::slotContextMenu(const QPoint & widgetPos)
{
// get data from the sender button
PixmapButton * button = static_cast<PixmapButton *>(sender());
QPoint screenPos = button->mapToGlobal(widgetPos);
QUrl fileUrl = button->property("url").toUrl();
QString fwFilePath = fileUrl.toString();
if (!QFile::exists(fwFilePath))
return;
// build menu
QMenu menu;
QAction * openAction = menu.addAction(tr("Open"));
menu.addSeparator();
QAction * removeAction = menu.addAction(tr("Remove From History"));
QMenu * fileSubMenu = menu.addMenu(tr("File"));
QAction * deleteAction = fileSubMenu->addAction(QIcon(":/data/action-delete.png"), tr("Delete File"));
// popup menu and handle actions
QAction * action = menu.exec(screenPos);
if (action == openAction) {
emit urlClicked(fileUrl);
} else if (action == removeAction) {
m_entries.removeAll(button);
button->deleteLater();
emit urlRemoved(QUrl(fwFilePath));
} else if (action == deleteAction) {
if (QFile::remove(fwFilePath)) {
m_entries.removeAll(button);
button->deleteLater();
emit urlRemoved(QUrl(fwFilePath));
} else
qWarning("UrlHistoryBox::slotContextMenu: cannot remove file");
}
}
void UrlHistoryBox::slotNextPreview()
{
if (m_previewIndex < m_entries.size()) {
PixmapButton * btn = m_entries[m_previewIndex];
genPreview(btn);
m_previewIndex++;
// start next job right after
if (m_previewIndex < m_entries.size())
QTimer::singleShot(10, this, SLOT(slotNextPreview()));
}
}
|