| 1 |
/**************************************************************************** |
| 2 |
** |
| 3 |
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
| 4 |
** Contact: Qt Software Information (qt-info@nokia.com) |
| 5 |
** |
| 6 |
** This file is part of the Graphics Dojo project on Qt Labs. |
| 7 |
** |
| 8 |
** This file may be used under the terms of the GNU General Public |
| 9 |
** License version 2.0 or 3.0 as published by the Free Software Foundation |
| 10 |
** and appearing in the file LICENSE.GPL included in the packaging of |
| 11 |
** this file. Please review the following information to ensure GNU |
| 12 |
** General Public Licensing requirements will be met: |
| 13 |
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and |
| 14 |
** http://www.gnu.org/copyleft/gpl.html. |
| 15 |
** |
| 16 |
** If you are unsure which license is appropriate for your use, please |
| 17 |
** contact the sales department at qt-sales@nokia.com. |
| 18 |
** |
| 19 |
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE |
| 20 |
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
| 21 |
** |
| 22 |
****************************************************************************/ |
| 23 |
|
| 24 |
#include <iostream> |
| 25 |
|
| 26 |
#include <QtGui> |
| 27 |
#include <QtWebKit> |
| 28 |
|
| 29 |
class WebSnap : public QObject |
| 30 |
{ |
| 31 |
Q_OBJECT |
| 32 |
|
| 33 |
public: |
| 34 |
WebSnap(); |
| 35 |
QSize targetSize() const; |
| 36 |
void setTargetSize(const QSize &s); |
| 37 |
QImage image() const; |
| 38 |
void load(const QUrl &url, const QString &outputFileName); |
| 39 |
|
| 40 |
signals: |
| 41 |
void finished(); |
| 42 |
|
| 43 |
private slots: |
| 44 |
void saveResult(bool ok); |
| 45 |
|
| 46 |
private: |
| 47 |
QWebPage m_page; |
| 48 |
QString m_fileName; |
| 49 |
QSize m_targetSize; |
| 50 |
QImage m_image; |
| 51 |
}; |
| 52 |
|
| 53 |
WebSnap::WebSnap(): QObject() |
| 54 |
{ |
| 55 |
m_targetSize = QSize(400, 300); |
| 56 |
connect(&m_page, SIGNAL(loadFinished(bool)), this, SLOT(saveResult(bool))); |
| 57 |
} |
| 58 |
|
| 59 |
void WebSnap::setTargetSize(const QSize &s) |
| 60 |
{ |
| 61 |
m_targetSize = s; |
| 62 |
} |
| 63 |
|
| 64 |
QSize WebSnap::targetSize() const |
| 65 |
{ |
| 66 |
return m_targetSize; |
| 67 |
} |
| 68 |
|
| 69 |
QImage WebSnap::image() const |
| 70 |
{ |
| 71 |
return m_image; |
| 72 |
} |
| 73 |
|
| 74 |
void WebSnap::load(const QUrl &url, const QString &outputFileName) |
| 75 |
{ |
| 76 |
m_fileName = outputFileName; |
| 77 |
m_image = QImage(); |
| 78 |
m_page.mainFrame()->load(url); |
| 79 |
} |
| 80 |
|
| 81 |
void WebSnap::saveResult(bool ok) |
| 82 |
{ |
| 83 |
// crude error-checking |
| 84 |
if (!ok) { |
| 85 |
std::cerr << "Failed loading " << qPrintable(m_page.mainFrame()->url().toString()) << std::endl; |
| 86 |
emit finished(); |
| 87 |
return; |
| 88 |
} |
| 89 |
|
| 90 |
// find proper size, we stick to sensible aspect ratio |
| 91 |
QSize size = m_page.mainFrame()->contentsSize(); |
| 92 |
size.setHeight(size.width() * m_targetSize.height() / m_targetSize.width()); |
| 93 |
|
| 94 |
// create the target surface |
| 95 |
m_image = QImage(size, QImage::Format_ARGB32_Premultiplied); |
| 96 |
m_image.fill(Qt::transparent); |
| 97 |
|
| 98 |
// render and rescale |
| 99 |
QPainter p(&m_image); |
| 100 |
m_page.setViewportSize(m_page.mainFrame()->contentsSize()); |
| 101 |
m_page.mainFrame()->render(&p); |
| 102 |
p.end(); |
| 103 |
m_image = m_image.scaled(m_targetSize, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation); |
| 104 |
|
| 105 |
if (!m_fileName.isEmpty()) { |
| 106 |
if (m_image.save(m_fileName, "png")) |
| 107 |
std::cout << "Result saved to " << qPrintable(m_fileName) << std::endl; |
| 108 |
else |
| 109 |
std::cout << "Failed to save to " << qPrintable(m_fileName) << std::endl; |
| 110 |
} |
| 111 |
|
| 112 |
emit finished(); |
| 113 |
} |
| 114 |
|
| 115 |
// shamelessly copied from Qt Demo Browser |
| 116 |
static QUrl guessUrlFromString(const QString &string) |
| 117 |
{ |
| 118 |
QString urlStr = string.trimmed(); |
| 119 |
QRegExp test(QLatin1String("^[a-zA-Z]+\\:.*")); |
| 120 |
|
| 121 |
// Check if it looks like a qualified URL. Try parsing it and see. |
| 122 |
bool hasSchema = test.exactMatch(urlStr); |
| 123 |
if (hasSchema) { |
| 124 |
QUrl url(urlStr, QUrl::TolerantMode); |
| 125 |
if (url.isValid()) |
| 126 |
return url; |
| 127 |
} |
| 128 |
|
| 129 |
// Might be a file. |
| 130 |
if (QFile::exists(urlStr)) |
| 131 |
return QUrl::fromLocalFile(urlStr); |
| 132 |
|
| 133 |
// Might be a shorturl - try to detect the schema. |
| 134 |
if (!hasSchema) { |
| 135 |
int dotIndex = urlStr.indexOf(QLatin1Char('.')); |
| 136 |
if (dotIndex != -1) { |
| 137 |
QString prefix = urlStr.left(dotIndex).toLower(); |
| 138 |
QString schema = (prefix == QLatin1String("ftp")) ? prefix : QLatin1String("http"); |
| 139 |
QUrl url(schema + QLatin1String("://") + urlStr, QUrl::TolerantMode); |
| 140 |
if (url.isValid()) |
| 141 |
return url; |
| 142 |
} |
| 143 |
} |
| 144 |
|
| 145 |
// Fall back to QUrl's own tolerant parser. |
| 146 |
return QUrl(string, QUrl::TolerantMode); |
| 147 |
} |
| 148 |
|
| 149 |
#include "websnap.moc" |
| 150 |
|
| 151 |
int main(int argc, char * argv[]) |
| 152 |
{ |
| 153 |
if ((argc < 2) || (argc == 4)) { |
| 154 |
std::cout << "Create a thumbnail preview of a web page" << std::endl << std::endl; |
| 155 |
std::cout << " websnap url [outputfile [width height]]" << std::endl << std::endl; |
| 156 |
std::cout << "Examples: " << std::endl; |
| 157 |
std::cout << " websnap www.trolltech.com" << std::endl; |
| 158 |
std::cout << " websnap www.nokia.com" << std::endl; |
| 159 |
std::cout << " websnap www.google.com google.png 400 300" << std::endl; |
| 160 |
std::cout << std::endl; |
| 161 |
return 0; |
| 162 |
} |
| 163 |
|
| 164 |
QString fileName; |
| 165 |
|
| 166 |
QUrl url = guessUrlFromString(QString::fromLatin1(argv[1])); |
| 167 |
if (argc >= 3) { |
| 168 |
fileName = QString::fromLatin1(argv[2]); |
| 169 |
} else { |
| 170 |
fileName = QFileInfo(url.path()).completeBaseName(); |
| 171 |
if (fileName.isEmpty()) |
| 172 |
fileName = "result"; |
| 173 |
fileName += ".png"; |
| 174 |
} |
| 175 |
|
| 176 |
QApplication a(argc, argv); |
| 177 |
WebSnap websnap; |
| 178 |
QObject::connect(&websnap, SIGNAL(finished()), QApplication::instance(), SLOT(quit())); |
| 179 |
|
| 180 |
if (argc == 5) { |
| 181 |
int w = QString::fromLatin1(argv[3]).toInt(); |
| 182 |
int h = QString::fromLatin1(argv[4]).toInt(); |
| 183 |
websnap.setTargetSize(QSize(w, h)); |
| 184 |
if (!websnap.targetSize().isValid() || w <= 0 || h <= 0) { |
| 185 |
std::cerr << "Please specify a valid target size !" << std::endl; |
| 186 |
return 0; |
| 187 |
} |
| 188 |
} |
| 189 |
|
| 190 |
websnap.load(url, fileName); |
| 191 |
return a.exec(); |
| 192 |
} |