blob: 41dfba37b6aa6580a420b67c42e844203ffe15f6 [file] [log] [blame]
/*
* Copyright (C) 2006 George Staikos <staikos@kde.org>
* Copyright (C) 2006 Dirk Mueller <mueller@kde.org>
* Copyright (C) 2006 Zack Rusin <zack@kde.org>
* Copyright (C) 2006 Simon Hausmann <hausmann@kde.org>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <qwebpage.h>
#include <qwebframe.h>
#include <qwebsettings.h>
#include <QtGui>
#include <QDebug>
class InfoWidget :public QProgressBar {
Q_OBJECT
public:
InfoWidget(QWidget *parent)
: QProgressBar(parent), m_progress(0)
{
setMinimum(0);
setMaximum(100);
}
QSize sizeHint() const
{
QSize size(100, 20);
return size;
}
public slots:
void startLoad()
{
setValue(m_progress);
show();
}
void changeLoad(int change)
{
m_progress = change;
setValue(change);
}
void endLoad()
{
QTimer::singleShot(1000, this, SLOT(hide()));
m_progress = 0;
}
protected:
int m_progress;
};
class HoverLabel : public QWidget {
Q_OBJECT
public:
HoverLabel(QWidget *parent=0)
: QWidget(parent),
m_animating(false),
m_percent(0)
{
m_timer.setInterval(1000/30);
m_hideTimer.setInterval(500);
m_hideTimer.setSingleShot(true);
connect(&m_timer, SIGNAL(timeout()),
this, SLOT(update()));
connect(&m_hideTimer, SIGNAL(timeout()),
this, SLOT(hide()));
}
public slots:
void setHoverLink(const QString &link) {
m_link = link;
if (m_link.isEmpty()) {
m_hideTimer.start();
} else {
m_hideTimer.stop();
m_oldSize = m_newSize;
m_newSize = sizeForFont();
resetAnimation();
updateSize();
show();
repaint();
}
}
QSize sizeForFont() const {
QFont f = font();
QFontMetrics fm(f);
return QSize(fm.width(m_link) + 10, fm.height() + 6);
}
QSize sizeHint() const {
if (!m_animating)
return sizeForFont();
else
return (m_newSize.width() > m_oldSize.width()) ? m_newSize : m_oldSize;
}
void updateSize() {
QRect r = geometry();
QSize newSize = sizeHint();
r = QRect(r.x(), r.y(), newSize.width(), newSize.height());
setGeometry(r);
}
void resetAnimation() {
m_animating = true;
m_percent = 0;
if (!m_timer.isActive())
m_timer.start();
}
protected:
void paintEvent(QPaintEvent *e) {
QPainter p(this);
p.setClipRect(e->rect());
p.setPen(QPen(Qt::black, 1));
QLinearGradient gradient(rect().topLeft(), rect().bottomLeft());
gradient.setColorAt(0, QColor(255, 255, 255, 220));
gradient.setColorAt(1, QColor(193, 193, 193, 220));
p.setBrush(QBrush(gradient));
QSize size;
{
//draw a nicely rounded corner rectangle. to avoid unwanted
// borders we move the coordinates outsize the our clip region
size = interpolate(m_oldSize, m_newSize, m_percent);
QRect r(-1, 0, size.width(), size.height()+2);
const int roundness = 20;
QPainterPath path;
path.moveTo(r.x(), r.y());
path.lineTo(r.topRight().x()-roundness, r.topRight().y());
path.cubicTo(r.topRight().x(), r.topRight().y(),
r.topRight().x(), r.topRight().y(),
r.topRight().x(), r.topRight().y() + roundness);
path.lineTo(r.bottomRight());
path.lineTo(r.bottomLeft());
path.closeSubpath();
p.setRenderHint(QPainter::Antialiasing);
p.drawPath(path);
}
if (m_animating) {
if (qFuzzyCompare(m_percent, 1)) {
m_animating = false;
m_percent = 0;
m_timer.stop();
} else {
m_percent += 0.1;
if (m_percent >= 0.99) {
m_percent = 1;
}
}
}
QString txt;
QFontMetrics fm(fontMetrics());
txt = fm.elidedText(m_link, Qt::ElideRight, size.width()-5);
p.drawText(5, height()-6, txt);
}
private:
QSize interpolate(const QSize &src, const QSize &dst, qreal percent) {
int widthDiff = int((dst.width() - src.width()) * percent);
int heightDiff = int((dst.height() - src.height()) * percent);
return QSize(src.width() + widthDiff,
src.height() + heightDiff);
}
QString m_link;
bool m_animating;
QTimer m_timer;
QTimer m_hideTimer;
QSize m_oldSize;
QSize m_newSize;
qreal m_percent;
};
class SearchEdit;
class ClearButton : public QPushButton {
Q_OBJECT
public:
ClearButton(QWidget *w)
: QPushButton(w)
{
setMinimumSize(24, 24);
setFixedSize(24, 24);
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
}
void paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
QPainter painter(this);
int height = parentWidget()->geometry().height();
int width = height; //parentWidget()->geometry().width();
painter.setRenderHint(QPainter::Antialiasing, true);
painter.setPen(Qt::lightGray);
painter.setBrush(isDown() ?
QColor(140, 140, 190) :
underMouse() ? QColor(220, 220, 255) : QColor(200, 200, 230)
);
painter.drawEllipse(4, 4, width - 8, height - 8);
painter.setPen(Qt::white);
int border = 8;
painter.drawLine(border, border, width - border, height - border);
painter.drawLine(border, height - border, width - border, border);
}
};
class SearchEdit : public QLineEdit
{
Q_OBJECT
public:
SearchEdit(const QString &str, QWidget *parent = 0)
: QLineEdit(str, parent)
{
setMinimumSize(QSize(400, 24));
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
setStyleSheet(":enabled { padding-right: 27px }");
clearButton = new ClearButton(this);
clearButton->setGeometry(QRect(geometry().right() - 27,
geometry().top() - 2,
geometry().right(), geometry().bottom()));
clearButton->setVisible(true);
#ifndef QT_NO_CURSOR
clearButton->setCursor(Qt::ArrowCursor);
#endif
#ifndef QT_NO_TOOLTIP
clearButton->setToolTip("Clear");
#endif
connect(clearButton, SIGNAL(clicked()), this, SLOT(clear()));
}
~SearchEdit() { }
protected:
virtual void paintEvent(QPaintEvent *e) {
QLineEdit::paintEvent(e);
if(text().isEmpty())
clearButton->setVisible(false);
else
clearButton->setVisible(true);
}
virtual void resizeEvent(QResizeEvent *) {
clearButton->setParent(this);
clearButton->setGeometry(QRect(width()-27,
0,
24, 24));
}
virtual void moveEvent(QMoveEvent *) {
clearButton->setParent(this);
clearButton->setGeometry(QRect(width()-27, 1,
24, 24));
}
QPushButton *clearButton;
};
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(const QUrl &url)
{
page = new QWebPage(this);
InfoWidget *info = new InfoWidget(page);
info->setGeometry(20, 20, info->sizeHint().width(),
info->sizeHint().height());
connect(page, SIGNAL(loadStarted(QWebFrame*)),
info, SLOT(startLoad()));
connect(page, SIGNAL(loadProgressChanged(int)),
info, SLOT(changeLoad(int)));
connect(page, SIGNAL(loadFinished(QWebFrame*)),
info, SLOT(endLoad()));
connect(page, SIGNAL(loadFinished(QWebFrame*)),
this, SLOT(loadFinished()));
connect(page, SIGNAL(titleChanged(const QString&)),
this, SLOT(setWindowTitle(const QString&)));
connect(page, SIGNAL(hoveringOverLink(const QString&, const QString&)),
this, SLOT(showLinkHover(const QString&, const QString&)));
setCentralWidget(page);
QToolBar *bar = addToolBar("Navigation");
urlEdit = new SearchEdit(url.toString());
connect(urlEdit, SIGNAL(returnPressed()),
SLOT(changeLocation()));
bar->addAction("Go back", page, SLOT(goBack()));
bar->addAction("Stop", page, SLOT(stop()));
bar->addAction("Go forward", page, SLOT(goForward()));
bar->addWidget(urlEdit);
hoverLabel = new HoverLabel(this);
hoverLabel->hide();
page->open(url);
info->raise();
}
protected slots:
void changeLocation()
{
QUrl url(urlEdit->text());
page->open(url);
}
void loadFinished()
{
urlEdit->setText(page->url().toString());
}
void showLinkHover(const QString &link, const QString &toolTip)
{
//statusBar()->showMessage(link);
hoverLabel->setHoverLink(link);
#ifndef QT_NO_TOOLTIP
if (!toolTip.isEmpty())
QToolTip::showText(QCursor::pos(), toolTip);
#endif
}
protected:
void resizeEvent(QResizeEvent *) {
QSize hoverSize = hoverLabel->sizeHint();
hoverLabel->setGeometry(0, height()-hoverSize.height(),
300, hoverSize.height());
}
private:
QWebPage *page;
QLineEdit *urlEdit;
HoverLabel *hoverLabel;
};
#include "main.moc"
int main(int argc, char **argv)
{
QString url = QString("%1/%2").arg(QDir::homePath()).arg(QLatin1String("index.html"));
QApplication app(argc, argv);
QWebSettings settings = QWebSettings::global();
settings.setAttribute(QWebSettings::PluginsEnabled);
QWebSettings::setGlobal(settings);
const QStringList args = app.arguments();
if (args.count() > 1)
url = args.at(1);
QUrl qurl(url);
if (qurl.scheme().isEmpty())
qurl = QUrl::fromLocalFile(QFileInfo(url).absoluteFilePath());
MainWindow window(qurl);
window.show();
return app.exec();
}