1// program to test the new khtml implementation
2
3#include "testkhtml.h"
4#include "testkhtml.moc"
5
6#include <stdlib.h>
7#include "kapplication.h"
8#include "khtmlview.h"
9#include "html_document.h"
10#include "htmltokenizer.h"
11// to be able to delete a static protected member pointer in kbrowser...
12// just for memory debugging
13#define protected public
14#include "khtml_part.h"
15#undef protected
16#include "misc/loader.h"
17#include <QtGui/QCursor>
18#include <QDomDocument>
19#include <dom_string.h>
20#include "dom/dom2_range.h"
21#include "dom/html_document.h"
22#include "dom/dom_exception.h"
23#include <stdio.h>
24#include "css/cssstyleselector.h"
25#include "html/html_imageimpl.h"
26#include "rendering/render_style.h"
27#include "khtml_global.h"
28#include <kxmlguiwindow.h>
29#include <kcmdlineargs.h>
30#include <ktoggleaction.h>
31#include <kactioncollection.h>
32#include <kicon.h>
33#include "kxmlguifactory.h"
34#include <kfiledialog.h>
35
36int main(int argc, char *argv[])
37{
38 KCmdLineOptions options;
39 options.add("+file", ki18n("URL to open"));
40
41 KCmdLineArgs::init(argc, argv, "testkhtml", 0, ki18n("Testkhtml"),
42 "1.0", ki18n("a basic web browser using the KHTML library"));
43 KCmdLineArgs::addCmdLineOptions(options);
44
45 KApplication a;
46 KCmdLineArgs *args = KCmdLineArgs::parsedArgs( );
47 if ( args->count() == 0 ) {
48 KCmdLineArgs::usage();
49 ::exit( 1 );
50 }
51
52 new KHTMLGlobal;
53
54 KXmlGuiWindow *toplevel = new KXmlGuiWindow();
55 KHTMLPart *doc = new KHTMLPart( toplevel, toplevel, KHTMLPart::BrowserViewGUI );
56
57 Dummy *dummy = new Dummy( doc );
58 QObject::connect( doc->browserExtension(), SIGNAL(openUrlRequest(KUrl,KParts::OpenUrlArguments,KParts::BrowserArguments)),
59 dummy, SLOT(slotOpenURL(KUrl,KParts::OpenUrlArguments,KParts::BrowserArguments)) );
60
61 QObject::connect( doc, SIGNAL(completed()), dummy, SLOT(handleDone()) );
62
63 if (args->url(0).url().right(4).toLower() == ".xml") {
64 KParts::OpenUrlArguments args(doc->arguments());
65 args.setMimeType("text/xml");
66 doc->setArguments(args);
67 }
68
69 doc->openUrl( args->url(0) );
70
71 toplevel->setCentralWidget( doc->widget() );
72 toplevel->resize( 800, 600);
73
74 QDomDocument d = doc->domDocument();
75 QDomElement viewMenu = d.documentElement().firstChild().childNodes().item( 2 ).toElement();
76 QDomElement e = d.createElement( "action" );
77 e.setAttribute( "name", "debugRenderTree" );
78 viewMenu.appendChild( e );
79 e = d.createElement( "action" );
80 e.setAttribute( "name", "debugDOMTree" );
81 viewMenu.appendChild( e );
82 e = d.createElement( "action" );
83 e.setAttribute( "name", "debugDoBenchmark" );
84 viewMenu.appendChild( e );
85
86 QDomElement toolBar = d.documentElement().firstChild().nextSibling().toElement();
87 e = d.createElement( "action" );
88 e.setAttribute( "name", "editable" );
89 toolBar.insertBefore( e, toolBar.firstChild() );
90 e = d.createElement( "action" );
91 e.setAttribute( "name", "navigable" );
92 toolBar.insertBefore( e, toolBar.firstChild() );
93 e = d.createElement( "action" );
94 e.setAttribute( "name", "reload" );
95 toolBar.insertBefore( e, toolBar.firstChild() );
96 e = d.createElement( "action" );
97 e.setAttribute( "name", "print" );
98 toolBar.insertBefore( e, toolBar.firstChild() );
99
100 KAction *action = new KAction(KIcon("view-refresh"), "Reload", doc );
101 doc->actionCollection()->addAction( "reload", action );
102 QObject::connect(action, SIGNAL(triggered(bool)), dummy, SLOT(reload()));
103 action->setShortcut(Qt::Key_F5);
104
105 KAction *bench = new KAction( KIcon(), "Benchmark...", doc );
106 doc->actionCollection()->addAction( "debugDoBenchmark", bench );
107 QObject::connect(bench, SIGNAL(triggered(bool)), dummy, SLOT(doBenchmark()));
108
109 KAction *kprint = new KAction(KIcon("document-print"), "Print", doc );
110 doc->actionCollection()->addAction( "print", kprint );
111 QObject::connect(kprint, SIGNAL(triggered(bool)), doc->browserExtension(), SLOT(print()));
112 kprint->setEnabled(true);
113 KToggleAction *ta = new KToggleAction( KIcon("edit-rename"), "Navigable", doc );
114 doc->actionCollection()->addAction( "navigable", ta );
115 ta->setShortcuts( KShortcut() );
116 ta->setChecked(doc->isCaretMode());
117 QWidget::connect(ta, SIGNAL(toggled(bool)), dummy, SLOT(toggleNavigable(bool)));
118 ta = new KToggleAction( KIcon("document-properties"), "Editable", doc );
119 doc->actionCollection()->addAction( "editable", ta );
120 ta->setShortcuts( KShortcut() );
121 ta->setChecked(doc->isEditable());
122 QWidget::connect(ta, SIGNAL(toggled(bool)), dummy, SLOT(toggleEditable(bool)));
123 toplevel->guiFactory()->addClient( doc );
124
125 doc->setJScriptEnabled(true);
126 doc->setJavaEnabled(true);
127 doc->setPluginsEnabled( true );
128 doc->setURLCursor(QCursor(Qt::PointingHandCursor));
129 a.setTopWidget(doc->widget());
130 QWidget::connect(doc, SIGNAL(setWindowCaption(QString)),
131 doc->widget()->topLevelWidget(), SLOT(setCaption(QString)));
132 doc->widget()->show();
133 toplevel->show();
134 doc->view()->viewport()->show();
135 doc->view()->widget()->show();
136
137
138 int ret = a.exec();
139 return ret;
140}
141
142void Dummy::doBenchmark()
143{
144 KConfigGroup settings(KGlobal::config(), "bench");
145 results.clear();
146
147 QString directory = KFileDialog::getExistingDirectory(settings.readPathEntry("path", QString()), m_part->view(),
148 QString::fromLatin1("Please select directory with tests"));
149
150 if (!directory.isEmpty()) {
151 settings.writePathEntry("path", directory);
152 KGlobal::config()->sync();
153
154 QDir dirListing(directory, "*.html");
155 for (unsigned i = 0; i < dirListing.count(); ++i) {
156 filesToBenchmark.append(dirListing.absoluteFilePath(dirListing[i]));
157 }
158 }
159
160 benchmarkRun = 0;
161
162 if (!filesToBenchmark.isEmpty())
163 nextRun();
164}
165
166const int COLD_RUNS = 2;
167const int HOT_RUNS = 6;
168
169void Dummy::nextRun()
170{
171 if (benchmarkRun == (COLD_RUNS + HOT_RUNS)) {
172 filesToBenchmark.removeFirst();
173 benchmarkRun = 0;
174 }
175
176 if (!filesToBenchmark.isEmpty()) {
177 loadTimer.start();
178 m_part->openUrl(filesToBenchmark[0]);
179 } else {
180 //Generate HTML for report.
181 m_part->begin();
182 m_part->write("<html><body><table border=1>");
183
184 for (QMap<QString, QList<int> >::iterator i = results.begin(); i != results.end(); ++i) {
185 m_part->write("<tr><td>" + i.key() + "</td>");
186 QList<int> timings = i.value();
187 int total = 0;
188 for (int pos = 0; pos < timings.size(); ++pos) {
189 int t = timings[pos];
190 if (pos < COLD_RUNS)
191 m_part->write(QString::fromLatin1("<td>(Cold):") + QString::number(t) + "</td>");
192 else {
193 total += t;
194 m_part->write(QString::fromLatin1("<td><i>") + QString::number(t) + "</i></td>");
195 }
196 }
197
198 m_part->write(QString::fromLatin1("<td>Average:<b>") + QString::number(double(total) / HOT_RUNS) + "</b></td>");
199
200 m_part->write("</tr>");
201 }
202
203 m_part->end();
204 }
205}
206
207void Dummy::handleDone()
208{
209 if (filesToBenchmark.isEmpty()) return;
210
211 results[filesToBenchmark[0]].append(loadTimer.elapsed());
212 ++benchmarkRun;
213 QTimer::singleShot(100, this, SLOT(nextRun()));
214}
215