Skip to content

Commit

Permalink
Add a simple start page with a search box pointing at the active
Browse files Browse the repository at this point in the history
search engine. It has been created by Fernando Lemos and has some
modifications of mine:
1. It now uses engines from the user's collection.
2. It is translatable now.
3. It uses our SVG icon so that it is fully resizable.

Changes behind the scenes:
- It uses the window.arora interface that we will expose to the
  JavaScript scope for our custom pages. One of the methods is
  translate(), which is a wrapper for tr() function.
  Drawback: translatable strings need to be predeclared using the
  QT_TR_NOOP macro.
- Another object that is exposed is the current engine object. It is
  available under the window.arora.currentEngine interface. All
  properties that are declared using the Q_PROPERTY macro will be
  available as JS properties.
  • Loading branch information
Jakub Wieczorek committed Jul 4, 2009
1 parent 541eabc commit 80189ce
Show file tree
Hide file tree
Showing 11 changed files with 229 additions and 9 deletions.
30 changes: 30 additions & 0 deletions autotests/webpage/tst_webpage.cpp
Expand Up @@ -51,6 +51,8 @@ private slots:
void createWindow();
void handleUnsupportedContent();
void linkedResources();
void javaScriptObjects_data();
void javaScriptObjects();
};

// Subclass that exposes the protected functions.
Expand Down Expand Up @@ -337,6 +339,34 @@ void tst_WebPage::linkedResources()
QCOMPARE(resources.at(3).href, QUrl("http://external.foo/search.xml"));
}

void tst_WebPage::javaScriptObjects_data()
{
QTest::addColumn<QUrl>("url");
QTest::addColumn<bool>("windowExternal");
QTest::addColumn<bool>("windowArora");

QTest::newRow("qrc:/notfound.html") << QUrl("qrc:/notfound.html") << true << false;
QTest::newRow("qrc:/startpage.html") << QUrl("qrc:/startpage.html") << true << true;
}

void tst_WebPage::javaScriptObjects()
{
QFETCH(QUrl, url);
QFETCH(bool, windowExternal);
QFETCH(bool, windowArora);

SubWebPage page;
QSignalSpy spy(&page, SIGNAL(loadFinished(bool)));
page.mainFrame()->load(url);
QTRY_COMPARE(spy.count(), 1);

QVariant windowExternalVariant = page.mainFrame()->evaluateJavaScript(QLatin1String("window.external"));
QVariant windowAroraVariant = page.mainFrame()->evaluateJavaScript(QLatin1String("window.arora"));

QCOMPARE(windowExternal, !windowExternalVariant.isNull());
QCOMPARE(windowArora, !windowAroraVariant.isNull());
}

QTEST_MAIN(tst_WebPage)
#include "tst_webpage.moc"

2 changes: 1 addition & 1 deletion src/browsermainwindow.cpp
Expand Up @@ -1328,7 +1328,7 @@ void BrowserMainWindow::goHome()
{
QSettings settings;
settings.beginGroup(QLatin1String("MainWindow"));
QString home = settings.value(QLatin1String("home"), QLatin1String("http://www.arora-browser.org")).toString();
QString home = settings.value(QLatin1String("home"), QLatin1String("about:home")).toString();
tabWidget()->loadString(home);
}

Expand Down
1 change: 1 addition & 0 deletions src/data/data.qrc
@@ -1,6 +1,7 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>128x128/arora.png</file>
<file>arora.svg</file>
<file>defaultbookmarks.xbel</file>
<file>fetchLinks.js</file>
<file>../../AUTHORS</file>
Expand Down
4 changes: 3 additions & 1 deletion src/htmls/htmls.qrc
@@ -1,6 +1,8 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>notfound.html</file>
<file>dirlist.html</file>
<file>notfound.html</file>
<file>startpage.html</file>
<file>startpage.css</file>
</qresource>
</RCC>
74 changes: 74 additions & 0 deletions src/htmls/startpage.css
@@ -0,0 +1,74 @@
* {
margin: 0;
padding: 0;
font-family: "DejaVu Sans";
}

body {
background: -webkit-gradient(linear, left top, left bottom, from(#ccc), to(#fff), color-stop(0.5, #fff));
background-repeat: repeat-x;
margin-top: 200px;
}

#header, #search, #footer {
width: 500px;
margin: 10px auto;
}

#header, #search {
-webkit-border-radius: 0.8em;
padding: 25px;
}

#header {
background: -webkit-gradient(linear, left top, left bottom, from(#228), to(#668), color-stop(0.9, #66a));
height: 20px;
}

#header h1 {
display: inline;
font-size: 1.7em;
color: #fff;
font-weight: bold;
}

#header img {
display: inline;
float: right;
height: 150px;
margin-top: -80px;
}

#search {
background: -webkit-gradient(linear, left top, right top, from(#cdf), to(#cdf), color-stop(0.5, #eff));
height: 50px;
color: #000;
text-align: center;
padding-top: 40px !important;
}

#search fieldset {
border: 0;
}

#search input[type=text] {
width: 65%;
}

#search input[type=submit] {
width: 25%;
}

#footer {
text-align: center;
color: #999;
}

#footer a {
color: #555;
text-decoration: none;
}

#footer a:hover {
text-decoration: underline;
}
49 changes: 49 additions & 0 deletions src/htmls/startpage.html
@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title></title>
<link rel="stylesheet" href="qrc:/startpage.css" type="text/css" />
<script type="text/javascript">
function update()
{
var searchEngine = window.arora.currentEngine;

document.title = window.arora.translate('Welcome to Arora!');
document.getElementById('headerTitle').innerHTML = window.arora.translate('Arora Start');
document.getElementById('searchButton').value = window.arora.translate('Search!');
document.getElementById('footer').innerHTML = window.arora.translate('Search results provided by') + ' '
+ searchEngine.name + ' | ' + '<a href="http://arora-browser.org/">'
+ window.arora.translate('About Arora') + '</a>';
document.getElementById('lineEdit').innerHTML = searchEngine.name;
}

function formSubmitted()
{
var string = lineEdit.value;

if (string.length == 0)
return;

var url = window.arora.searchUrl(string);
window.location.href = url;
}
</script>
</head>
<body onload="document.forms[0].lineEdit.select(); update();">
<div id="header">
<h1 id="headerTitle"></h1>
<img src="qrc:/arora.svg" />
</div>
<div id="search">
<form action="javascript:formSubmitted();">
<fieldset>
<input id="lineEdit" name="lineEdit" type="text" />
<input id="searchButton" type="submit" />
</fieldset>
</form>
</div>
<div id="footer"></div>
</body>
</html>
2 changes: 2 additions & 0 deletions src/opensearch/opensearchengine.h
Expand Up @@ -34,6 +34,8 @@ class OpenSearchEngine : public QObject
{
Q_OBJECT

Q_PROPERTY(QString name READ name)

signals:
void imageChanged();
void suggestions(const QStringList &suggestions);
Expand Down
2 changes: 1 addition & 1 deletion src/settings.cpp
Expand Up @@ -135,7 +135,7 @@ void SettingsDialog::loadFromSettings()
{
QSettings settings;
settings.beginGroup(QLatin1String("MainWindow"));
QString defaultHome = QLatin1String("http://www.arora-browser.org");
QString defaultHome = QLatin1String("about:home");
homeLineEdit->setText(settings.value(QLatin1String("home"), defaultHome).toString());
startupBehavior->setCurrentIndex(settings.value(QLatin1String("startupBehavior"), 0).toInt());
settings.endGroup();
Expand Down
4 changes: 4 additions & 0 deletions src/tabwidget.cpp
Expand Up @@ -928,6 +928,10 @@ QUrl TabWidget::guessUrlFromString(const QString &string)
{
QUrl url = WebView::guessUrlFromString(string);

if (url.scheme() == QLatin1String("about")
&& url.path() == QLatin1String("home"))
url = QUrl(QLatin1String("qrc:/startpage.html"));

// QUrl::isValid() is too much tolerant.
// We actually want to check if the url conforms to the RFC, which QUrl::isValid() doesn't state.
if (!url.scheme().isEmpty() && (!url.host().isEmpty() || !url.path().isEmpty()))
Expand Down
51 changes: 46 additions & 5 deletions src/webpage.cpp
Expand Up @@ -24,6 +24,7 @@
#include "downloadmanager.h"
#include "historymanager.h"
#include "networkaccessmanager.h"
#include "opensearchengine.h"
#include "opensearchmanager.h"
#include "tabwidget.h"
#include "toolbarsearch.h"
Expand Down Expand Up @@ -54,10 +55,42 @@ void JavaScriptExternalObject::AddSearchProvider(const QString &url)
ToolbarSearch::openSearchManager()->addEngine(QUrl(url));
}

Q_DECLARE_METATYPE(OpenSearchEngine*)
JavaScriptAroraObject::JavaScriptAroraObject(QObject *parent)
: QObject(parent)
{
static const char *translations[] = {
QT_TR_NOOP("Welcome to Arora!"),
QT_TR_NOOP("Arora Start"),
QT_TR_NOOP("Search!"),
QT_TR_NOOP("Search results provided by"),
QT_TR_NOOP("About Arora")
};
Q_UNUSED(translations);

qRegisterMetaType<OpenSearchEngine*>("OpenSearchEngine*");
}

QString JavaScriptAroraObject::translate(const QString &string)
{
return trUtf8(string.toUtf8().constData());
}

QObject *JavaScriptAroraObject::currentEngine() const
{
return ToolbarSearch::openSearchManager()->currentEngine();
}

QString JavaScriptAroraObject::searchUrl(const QString &string) const
{
return QString::fromUtf8(ToolbarSearch::openSearchManager()->currentEngine()->searchUrl(string).toEncoded());
}

WebPage::WebPage(QObject *parent)
: QWebPage(parent)
, m_openTargetBlankLinksIn(TabWidget::NewWindow)
, m_javaScriptBinding(0)
, m_javaScriptExternalObject(0)
, m_javaScriptAroraObject(0)
{
setPluginFactory(webPluginFactory());
setNetworkAccessManager(BrowserApplication::networkAccessManager());
Expand Down Expand Up @@ -139,17 +172,25 @@ QList<WebPageLinkedResource> WebPage::linkedResources(const QString &relation)

void WebPage::addExternalBinding(QWebFrame *frame)
{
if (!m_javaScriptBinding)
m_javaScriptBinding = new JavaScriptExternalObject(this);
if (!m_javaScriptExternalObject)
m_javaScriptExternalObject = new JavaScriptExternalObject(this);

if (frame == 0) { // called from QWebFrame::javaScriptWindowObjectCleared
frame = qobject_cast<QWebFrame*>(sender());

if (frame->url().scheme() == QLatin1String("qrc")
&& frame->url().path() == QLatin1String("/startpage.html")) {

if (!m_javaScriptAroraObject)
m_javaScriptAroraObject = new JavaScriptAroraObject(this);

frame->addToJavaScriptWindowObject(QLatin1String("arora"), m_javaScriptAroraObject);
}
} else { // called from QWebPage::frameCreated
connect(frame, SIGNAL(javaScriptWindowObjectCleared()),
this, SLOT(addExternalBinding()));
}
frame->addToJavaScriptWindowObject(QLatin1String("external"),
m_javaScriptBinding);
frame->addToJavaScriptWindowObject(QLatin1String("external"), m_javaScriptExternalObject);
}

bool WebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request,
Expand Down
19 changes: 18 additions & 1 deletion src/webpage.h
Expand Up @@ -34,6 +34,7 @@ class WebPageLinkedResource
QString title;
};

class OpenSearchEngine;
class QNetworkReply;
class WebPluginFactory;
// See https://developer.mozilla.org/en/adding_search_engines_from_web_pages
Expand All @@ -48,6 +49,21 @@ public slots:
void AddSearchProvider(const QString &url);
};

class JavaScriptAroraObject : public QObject
{
Q_OBJECT

Q_PROPERTY(QObject* currentEngine READ currentEngine)

public:
JavaScriptAroraObject(QObject *parent = 0);

public slots:
QString translate(const QString &string);
QObject *currentEngine() const;
QString searchUrl(const QString &string) const;
};

class WebPage : public QWebPage
{
Q_OBJECT
Expand Down Expand Up @@ -76,7 +92,8 @@ protected slots:
static WebPluginFactory *s_webPluginFactory;
TabWidget::OpenUrlIn m_openTargetBlankLinksIn;
QUrl m_requestedUrl;
JavaScriptExternalObject *m_javaScriptBinding;
JavaScriptExternalObject *m_javaScriptExternalObject;
JavaScriptAroraObject *m_javaScriptAroraObject;
};

#endif // WEBPAGE_H
Expand Down

0 comments on commit 80189ce

Please sign in to comment.