Commit MetaInfo

Revisioneabf6fad361c2f4b191ed202a577b2f88dd74719 (tree)
Zeit2009-01-05 09:54:54
Autorgoran
Commitergoran

Log Message

dikt import

Ändern Zusammenfassung

Diff

diff -r 000000000000 -r eabf6fad361c CMakeLists.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/CMakeLists.txt Mon Jan 05 00:54:54 2009 +0000
@@ -0,0 +1,24 @@
1+project(dikt)
2+
3+find_package(KDE4 REQUIRED)
4+include(KDE4Defaults)
5+include_directories(${KDE4_INCLUDES})
6+
7+set(dikt_SRCS
8+ dict.cpp
9+ dictbrowser.cpp
10+ dictpage.cpp
11+ dictsettings.cpp
12+ dictwidgets.cpp
13+ dictwindow.cpp
14+ main.cpp
15+)
16+
17+kde4_add_ui_files(dikt_SRCS searchbar.ui settings.ui)
18+kde4_add_executable(dikt ${dikt_SRCS})
19+
20+target_link_libraries(dikt ${KDE4_KDEUI_LIBS})
21+
22+install(TARGETS dikt DESTINATION ${BIN_INSTALL_DIR})
23+install(FILES diktui.rc DESTINATION ${DATA_INSTALL_DIR}/dikt)
24+install(FILES dikt.desktop DESTINATION ${XDG_APPS_INSTALL_DIR})
diff -r 000000000000 -r eabf6fad361c LICENSE
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/LICENSE Mon Jan 05 00:54:54 2009 +0000
@@ -0,0 +1,22 @@
1+Copyright 2008 by Goran Tal. All rights reserved.
2+
3+Redistribution and use in source and binary forms, with or without
4+modification, are permitted provided that the following conditions
5+are met:
6+
7+1. Redistributions of source code must retain the above copyright
8+ notice, this list of conditions and the following disclaimer.
9+2. Redistributions in binary form must reproduce the above copyright
10+ notice, this list of conditions and the following disclaimer in the
11+ documentation and/or other materials provided with the distribution.
12+
13+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff -r 000000000000 -r eabf6fad361c README
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/README Mon Jan 05 00:54:54 2009 +0000
@@ -0,0 +1,13 @@
1+Dikt - dictionary for KDE
2+
3+Dikt is a KDE4 application and it is configured, built, and installs
4+like all KDE4 applications. Information for setting up KDE4 is available
5+at KDE TechBase at http://techbase.kde.org/Getting_Started/Build/KDE4.
6+
7+Once KDE4 is set up properly, you can install Dikt with:
8+
9+cmake . && make install
10+
11+For more information and for the latest version see Dikt web site
12+http://diktv1.googlepages.com/.
13+For licensing, copyright and warranty see LICENSE file.
diff -r 000000000000 -r eabf6fad361c dict.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dict.cpp Mon Jan 05 00:54:54 2009 +0000
@@ -0,0 +1,508 @@
1+#include "dict.h"
2+
3+#include <KCodecs>
4+#include <KLocale>
5+#include <QTcpSocket>
6+#include <QTimer>
7+#include <QRegExp>
8+#include <QDebug>
9+
10+const char *DictClient = "Dikt 1";
11+
12+const char *Dict::DefaultHost = "dict.org";
13+const int Dict::DefaultPort = 2628;
14+const char *Dict::DefaultDatabase = "!";
15+const char *Dict::DefaultStrategy = ".";
16+
17+Dict::Dict(const QString &host, int port)
18+ : socket(0), state(Disconnected)
19+{
20+ dict.host = host;
21+ dict.port = port;
22+ socket = new QTcpSocket(this);
23+ setupSocket();
24+ setupTimers();
25+}
26+
27+void Dict::reset()
28+{
29+ delete socket;
30+ socket = new QTcpSocket(this);
31+ state = Disconnected;
32+ setupSocket();
33+}
34+
35+void Dict::setupSocket()
36+{
37+ connect(socket, SIGNAL(readyRead()), SLOT(read()));
38+ connect(socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
39+ SLOT(socketState()));
40+ connect(socket, SIGNAL(error(QAbstractSocket::SocketError)),
41+ SLOT(error()));
42+}
43+
44+void Dict::setupTimers()
45+{
46+ setTimeouts(20000, 15000, 240000);
47+ connect(&connectTimer, SIGNAL(timeout()), SLOT(connectTimeout()));
48+ connect(&readTimer, SIGNAL(timeout()), SLOT(readTimeout()));
49+ connect(&idleTimer, SIGNAL(timeout()), SLOT(idleTimeout()));
50+}
51+
52+void Dict::setTimeouts(int connect, int read, int idle)
53+{
54+ timeout.connect = connect;
55+ timeout.read = read;
56+ timeout.idle = idle;
57+}
58+
59+void Dict::connectTimeout()
60+{
61+ connectTimer.stop();
62+ reset();
63+ request.clear();
64+ queue.clear();
65+ emit errorMessage(i18n("Connect Timeout"));
66+ emit statusMessage(i18n("Canceled"));
67+}
68+
69+void Dict::readTimeout()
70+{
71+ readTimer.stop();
72+ socket->abort();
73+ request.clear();
74+ queue.clear();
75+ emit errorMessage(i18n("Read Timeout"));
76+ emit statusMessage(i18n("Canceled"));
77+}
78+
79+void Dict::idleTimeout()
80+{
81+ send("quit");
82+}
83+
84+void Dict::open()
85+{
86+ socket->connectToHost(dict.host, dict.port);
87+ connectTimer.start(timeout.connect);
88+}
89+
90+void Dict::setHost(const QString &host, int port)
91+{
92+ if (dict.host != host || dict.port != port) {
93+ dict.host = host;
94+ dict.port = port;
95+ if (state >= Connected)
96+ socket->abort();
97+ else if (state == Connecting)
98+ reset();
99+ queue.clear();
100+ dict.ident.clear();
101+ dict.user.clear();
102+ }
103+}
104+
105+void Dict::read()
106+{
107+ readTimer.stop();
108+ int bytes = socket->bytesAvailable();
109+ if (!bytes) return;
110+
111+ if (state == Writing || state == Connected) state = Reading;
112+ emit statusMessage(i18n("Reading"));
113+ QByteArray buf = socket->read(bytes);
114+
115+ // convert from utf only at newline
116+ // since a multibyte character can get split across packets
117+ int end = buf.lastIndexOf('\n');
118+ int len = buf.length();
119+ read(QString::fromUtf8(extra + buf.mid(0, end)).remove('\r'));
120+
121+ if (len == end + 1) extra.clear();
122+ else extra = buf.mid(end + 1);
123+}
124+
125+void Dict::send(const QString &command)
126+{
127+// qDebug() << "send" << command;
128+
129+ if (state > Connected) {
130+ state = Writing;
131+ socket->write(command.toUtf8() + '\n');
132+ readTimer.start(timeout.read);
133+ idleTimer.start(timeout.idle);
134+ emit statusMessage(i18n("Sending"));
135+ } else {
136+ if (state == Disconnected)
137+ open();
138+ queue.append(command);
139+ }
140+}
141+
142+void Dict::cancel()
143+{
144+ request.clear();
145+ queue.clear();
146+ connectTimer.stop();
147+ readTimer.stop();
148+
149+ if (state > Connected) {
150+ state = Canceling;
151+ idleTimer.start();
152+ }
153+ else if (state == Connected)
154+ socket->abort();
155+ else if (state == Connecting)
156+ reset();
157+
158+ emit statusMessage(i18n("Canceled"));
159+}
160+
161+void Dict::status()
162+{
163+ request.type = Status;
164+ request.command = "status";
165+ send(request.command);
166+}
167+
168+void Dict::define(const QString &query, const QString &database)
169+{
170+ Q_ASSERT(!database.isEmpty());
171+
172+ request.type = Define;
173+ request.query = query;
174+ request.database = database;
175+ request.command = QString("define %1 \"%2\"")
176+ .arg(database).arg(request.query.remove('\"'));
177+ send(request.command);
178+}
179+
180+void Dict::match(const QString &query, const QString &database, const QString &strategy)
181+{
182+ Q_ASSERT(!database.isEmpty());
183+ Q_ASSERT(!strategy.isEmpty());
184+
185+ request.type = Match;
186+ request.query = query;
187+ request.database = database;
188+ request.strategy = strategy;
189+ request.command = QString("match %1 %2 \"%3\"")
190+ .arg(database).arg(strategy).arg(request.query.remove('\"'));
191+ send(request.command);
192+}
193+
194+void Dict::info(const QString &query)
195+{
196+ if (query == "server")
197+ request.type = Server;
198+ else if (query == "databases")
199+ request.type = Databases;
200+ else if (query == "strategies")
201+ request.type = Strategies;
202+ else
203+ request.type = Info;
204+
205+ request.command = QString("show %1").arg(query);
206+ send(request.command);
207+}
208+
209+void Dict::setUser(const QString &username, const QString &password)
210+{
211+ dict.user = username;
212+ dict.password = password;
213+}
214+
215+void Dict::auth(const QString &username, const QString &password)
216+{
217+ setUser(username, password);
218+ if (!dict.user.isEmpty()) {
219+ request.type = Auth;
220+ request.command = "";
221+ (state >= Connected)
222+ ? auth() : open();
223+ }
224+}
225+
226+void Dict::auth()
227+{
228+ KMD5 context(dict.msgid.toAscii());
229+ context.update(dict.password.toAscii());
230+
231+ send(QString("auth %1 ").arg(dict.user) + context.hexDigest());
232+}
233+
234+void Dict::serverIdent(const QString &text)
235+{
236+ QRegExp rx("(.*) <(.*)> (<.*>)");
237+ rx.indexIn(text);
238+ QStringList list = rx.capturedTexts();
239+ dict.ident = list[1];
240+ dict.capabilities = list[2].split('.');
241+ dict.msgid = list[3];
242+}
243+
244+inline ResponseCode responseCode(const QString &line)
245+{
246+ return (ResponseCode)((line.size() >= 3) ? line.mid(0,3).toInt() : 0);
247+}
248+
249+inline QString responseMessage(const QString &line)
250+{
251+ return (line.size() > 4) ? line.mid(4) : "";
252+}
253+
254+inline bool endMark(const QString &line)
255+{
256+ return (line == ".");
257+}
258+
259+void Dict::read(const QString &text)
260+{
261+ QStringList list = text.split('\n');
262+ int size = list.size();
263+
264+ if (state == Reading) state = Parsing;
265+
266+ for (int i = 0; i < size; i++) {
267+ QString line = list[i];
268+ if (state == Parsing) {
269+ if (!line.isEmpty())
270+ parse(line);
271+ } else if (state == Appending) {
272+ if (endMark(line)) {
273+ if (response.type == Words)
274+ response.text += '\n';
275+ state = Parsing;
276+ } else
277+ append(line);
278+ }
279+ }
280+
281+ if (state == Parsing) state = Reading;
282+}
283+
284+DictPair headpair(const QString &line)
285+{
286+ QString key = line.section('\"', 2, 2).trimmed();
287+ QString val = line.section('\"', 3, 3);
288+ return qMakePair(key, val);
289+}
290+
291+void Dict::parse(const QString &line)
292+{
293+// qDebug() << line;
294+ ResponseCode code = responseCode(line);
295+
296+ if (code != OK) {
297+ response.type = code;
298+ response.desc = responseMessage(line);
299+ emit responseReceived(response);
300+ }
301+
302+ switch (code) {
303+ case Definitions:
304+// emit statusMessage(response.desc);
305+ break;
306+ case Words:
307+ state = Appending;
308+ break;
309+ case Matches:
310+ state = Appending;
311+ break;
312+ case OK:
313+ switch (response.type) {
314+ case Words:
315+ response.database = headpair(response.desc).second;
316+ break;
317+ case Matches:
318+ response.database = response.list[0].first;
319+ response.strategy = request.strategy;
320+ break;
321+ case DatabaseList:
322+ case StrategyList:
323+ case DatabaseInfo:
324+ case ServerInfo:
325+ break;
326+ case Hello:
327+ case Bye:
328+ return;
329+ break;
330+ default:
331+ qDebug() << "unhandled response" << response.type;
332+ return;
333+ }
334+ emit responseProcessed(response);
335+ emit responseText(response.text);
336+ emit statusMessage(i18n("Done"));
337+ response.clear();
338+ break;
339+ case NoMatch:
340+ response.text = i18n("No matches found");
341+ emit responseText(response.text);
342+ emit responseProcessed(response);
343+ emit statusMessage(i18n("Done"));
344+ response.clear();
345+ break;
346+ case DatabaseList:
347+ case StrategyList:
348+ case ServerInfo:
349+ case DatabaseInfo:
350+ state = Appending;
351+ break;
352+ case Hello:
353+ serverIdent(response.desc);
354+ send(QString("client \"%1\"").arg(DictClient));
355+ if (!dict.user.isEmpty())
356+ auth();
357+ if (!queue.isEmpty()) {
358+ foreach(QString command, queue)
359+ send(command);
360+ queue.clear();
361+ }
362+ break;
363+ case Bye:
364+ break;
365+ case StatusMessage:
366+ response.text = i18n("Connected to %1", dict.ident);
367+ emit responseProcessed(response);
368+ emit responseText(response.text);
369+ emit statusMessage(i18n("Done"));
370+ response.clear();
371+ break;
372+ case AuthOK:
373+ emit authenticated(true);
374+ if (request.type == Auth) {
375+ response.text = i18n("Authenticated to %1", dict.host);
376+ emit responseProcessed(response);
377+ emit responseText(response.text);
378+ emit statusMessage(i18n("Done"));
379+ }
380+ break;
381+ case AuthDenied:
382+ emit authenticated(false);
383+ if (request.type == Auth)
384+ emit errorMessage(i18n("Authentication failed"));
385+ break;
386+ case AccessDenied:
387+ emit errorMessage(i18n("Access denied"));
388+ break;
389+ case InvalidDatabase:
390+ emit errorMessage(i18n("Invalid database: %1", request.database));
391+ break;
392+ case InvalidStrategy:
393+ emit errorMessage(i18n("Invalid strategy: %1", request.strategy));
394+ break;
395+ case NoDatabase:
396+ emit errorMessage(i18n("No databases available"));
397+ break;
398+ case NoStrategy:
399+ emit errorMessage(i18n("No strategies available"));
400+ break;
401+ case ServerUnavailable:
402+ emit errorMessage(i18n("Server temporarily unavailable"));
403+ break;
404+ case ServerShutdown:
405+ emit errorMessage(i18n("Server shutting down"));
406+ break;
407+ default:
408+ qDebug() << "unhandled code" << code;
409+ }
410+}
411+
412+QPair<QString, QString> pair(const QString &line)
413+{
414+ QString key = line.section(' ', 0, 0);
415+ QString val = line.section('\"', 1, 1);
416+ return qMakePair(key, val);
417+}
418+
419+void Dict::append(const QString &line)
420+{
421+ switch (response.type) {
422+ case Words:
423+ response.text += line;
424+ break;
425+ case Matches:
426+ if (line.isEmpty()) return;
427+// response.text += line;
428+ response.list.append(pair(line));
429+ break;
430+ case DatabaseList:
431+ if (line.isEmpty()) return;
432+ response.list.append(pair(line));
433+ break;
434+ case StrategyList:
435+ if (line.isEmpty()) return;
436+ response.list.append(pair(line));
437+ break;
438+ case ServerInfo:
439+ if (line.isEmpty()) return;
440+ response.text += line;
441+ break;
442+ case DatabaseInfo:
443+ response.text += line;
444+ break;
445+ default:
446+ qDebug() << "unhandled code" << response.type;
447+ }
448+ if (!response.isEmpty()) response.text += '\n';
449+}
450+
451+void Dict::socketState()
452+{
453+ QString message;
454+ switch (socket->state()) {
455+ case QAbstractSocket::UnconnectedState:
456+ readTimer.stop();
457+ idleTimer.stop();
458+ state = Disconnected;
459+ message = i18n("Disconnected");
460+ break;
461+ case QAbstractSocket::HostLookupState:
462+ state = HostLookup;
463+ message = i18n("Looking for %1...", dict.host);
464+ break;
465+ case QAbstractSocket::ConnectingState:
466+ state = Connecting;
467+ message = i18n("Connecting to %1...", dict.host);
468+ break;
469+ case QAbstractSocket::ConnectedState:
470+ connectTimer.stop();
471+ readTimer.start(timeout.read);
472+ state = Connected;
473+ message = i18n("Waiting for %1...", dict.host);
474+ break;
475+ case QAbstractSocket::ClosingState:
476+ message = i18n("Disconnecting");
477+ break;
478+ default:
479+ qDebug() << "unhandled state" << socket->state();
480+ }
481+ if (!message.isEmpty())
482+ emit statusMessage(message);
483+
484+// qDebug() << "state" << socket->state();
485+}
486+
487+void Dict::error()
488+{
489+ connectTimer.stop();
490+ QString message;
491+ switch (socket->error()) {
492+ case QAbstractSocket::RemoteHostClosedError:
493+ break;
494+ case QAbstractSocket::ConnectionRefusedError:
495+ message = i18n("Connection refused by %1", dict.host);
496+ break;
497+ case QAbstractSocket::HostNotFoundError:
498+ message = i18n("Host %1 not found", dict.host);
499+ break;
500+ default:
501+ message = socket->errorString();
502+// qDebug() << "unhandled error" << socket->error();
503+ }
504+ if (!message.isEmpty())
505+ emit errorMessage(message);
506+
507+// qDebug() << "error" << socket->error();
508+}
diff -r 000000000000 -r eabf6fad361c dict.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dict.h Mon Jan 05 00:54:54 2009 +0000
@@ -0,0 +1,172 @@
1+#ifndef DICT_H
2+#define DICT_H
3+
4+#include <QPair>
5+#include <QList>
6+#include <QStringList>
7+#include <QTimer>
8+#include <QByteArray>
9+
10+typedef QPair<QString, QString> DictPair;
11+typedef QList<DictPair> DictList;
12+
13+class QTcpSocket;
14+
15+enum RequestCommand {
16+ Define = 1,
17+ Match,
18+ Databases,
19+ Strategies,
20+ Info,
21+ Server,
22+ Auth,
23+ Status,
24+ Help,
25+ Quit
26+};
27+
28+enum ResponseCode {
29+ DatabaseList = 110,
30+ StrategyList = 111,
31+ DatabaseInfo = 112,
32+ HelpMessage = 113,
33+ ServerInfo = 114,
34+ Definitions = 150,
35+ Words = 151,
36+ Matches = 152,
37+
38+ StatusMessage = 210,
39+ Hello = 220,
40+ Bye = 221,
41+ AuthOK = 230,
42+ OK = 250,
43+
44+ ServerUnavailable = 420,
45+ ServerShutdown = 421,
46+
47+ SyntaxError = 500,
48+ IllegalParameter = 501,
49+ UnimplementedCommand = 502,
50+ UnimplementedParameter = 503,
51+ AccessDenied = 530,
52+ AuthDenied = 531,
53+ InvalidDatabase = 550,
54+ InvalidStrategy = 551,
55+ NoMatch = 552,
56+ NoDatabase = 554,
57+ NoStrategy = 555,
58+};
59+
60+struct DictRequest {
61+ RequestCommand type;
62+ QString query;
63+ QString command;
64+ QString database;
65+ QString strategy;
66+ bool isEmpty() { return command.isEmpty(); };
67+ void clear() { command.clear(); type = RequestCommand(0); };
68+};
69+
70+struct DictResponse {
71+ ResponseCode type;
72+ QString desc;
73+ QString text;
74+ QString database;
75+ QString strategy;
76+ DictList list;
77+ bool isEmpty() { return text.isEmpty(); };
78+ void clear() { text.clear(); type = ResponseCode(0); list.clear(); };
79+};
80+
81+class Dict : public QObject
82+{
83+ Q_OBJECT
84+
85+public:
86+ static const char *DefaultHost;
87+ static const int DefaultPort;
88+ static const char *DefaultDatabase;
89+ static const char *DefaultStrategy;
90+
91+ Dict(const QString &host = DefaultHost, int port = DefaultPort);
92+ QString host() const { return dict.host; };
93+ int port() const { return dict.port; };
94+ void setTimeouts(int connect, int read, int idle);
95+
96+ QString user() const { return dict.user; };
97+ QStringList capabilities() const { return dict.capabilities; };
98+ void cancel();
99+ void status();
100+
101+public Q_SLOTS:
102+ void define(const QString &query, const QString &database = DefaultDatabase);
103+ void match(const QString &query, const QString &database = DefaultDatabase, const QString &strategy = DefaultStrategy);
104+ void info(const QString &query);
105+ void auth(const QString &username, const QString &password);
106+ void setHost(const QString &name, int port = DefaultPort);
107+ void setUser(const QString &name, const QString &password);
108+
109+private Q_SLOTS:
110+ void read();
111+ void error();
112+ void socketState();
113+ void connectTimeout();
114+ void readTimeout();
115+ void idleTimeout();
116+
117+Q_SIGNALS:
118+ void responseReceived(const DictResponse &);
119+ void responseProcessed(const DictResponse &);
120+ void responseText(const QString &);
121+ void connected(bool);
122+ void authenticated(bool);
123+ void statusMessage(const QString &);
124+ void errorMessage(const QString &);
125+
126+private:
127+ enum DictState {
128+ Disconnected,
129+ HostLookup,
130+ Connecting,
131+ Connected,
132+ Writing,
133+ Reading,
134+ Parsing,
135+ Appending,
136+ Canceling,
137+ };
138+ QTcpSocket *socket;
139+
140+ struct DictInfo {
141+ QString host;
142+ int port;
143+ QString user, password;
144+ QString ident, msgid;
145+ QStringList capabilities;
146+ } dict;
147+
148+ struct DictTimeout {
149+ int connect, read, idle;
150+ } timeout;
151+ QTimer connectTimer, readTimer, idleTimer;
152+
153+ DictState state;
154+ DictRequest request;
155+ DictResponse response;
156+ QStringList queue;
157+ QByteArray extra;
158+
159+ void setupSocket();
160+ void setupTimers();
161+ void reset();
162+
163+ void open();
164+ void auth();
165+ void serverIdent(const QString &text);
166+ void send(const QString &command);
167+ void read(const QString &text);
168+ void parse(const QString &text);
169+ void append(const QString &text);
170+};
171+
172+#endif
diff -r 000000000000 -r eabf6fad361c dictbrowser.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dictbrowser.cpp Mon Jan 05 00:54:54 2009 +0000
@@ -0,0 +1,144 @@
1+#include "dictbrowser.h"
2+
3+#include <QScrollBar>
4+#include <QDebug>
5+
6+DictBrowser::DictBrowser(QWidget *parent)
7+ : QTextBrowser(parent), histSize(100)
8+{
9+ plaintext = false;
10+ setOpenLinks(false);
11+ connect(this, SIGNAL(highlighted(const QString &)),
12+ SLOT(pointCursor(const QString &)));
13+}
14+
15+void DictBrowser::moveTo(int steps)
16+{
17+ QList<HistoryEntry> &history = (steps > 0)
18+ ? forwardHistory : backwardHistory;
19+
20+ if (history.isEmpty())
21+ return;
22+
23+ QList<HistoryEntry> &other = (steps > 0)
24+ ? backwardHistory : forwardHistory;
25+
26+ savePosition();
27+ if (steps < 0)
28+ steps = -steps;
29+ while (steps--) {
30+ other.prepend(entry);
31+ entry = history.takeFirst();
32+ }
33+ displayPage(entry.page);
34+ restorePosition();
35+
36+ emit backwardAvailable(!backwardHistory.isEmpty());
37+ emit forwardAvailable(!forwardHistory.isEmpty());
38+ emit historyChanged(entry.title);
39+}
40+
41+void DictBrowser::savePosition()
42+{
43+ entry.hpos = horizontalScrollBar()->value();
44+ entry.vpos = verticalScrollBar()->value();
45+}
46+
47+void DictBrowser::restorePosition()
48+{
49+ horizontalScrollBar()->setValue(entry.hpos);
50+ verticalScrollBar()->setValue(entry.vpos);
51+}
52+
53+void DictBrowser::clearHistory()
54+{
55+ backwardHistory.clear();
56+ forwardHistory.clear();
57+ emit backwardAvailable(false);
58+ emit forwardAvailable(false);
59+}
60+
61+QStringList DictBrowser::historyList(const QList<HistoryEntry> &history, int len) const
62+{
63+ QStringList list;
64+ len = qMin(history.size(), len);
65+ for (int i = 0; i < len; i++)
66+ list << history[i].title;
67+ return list;
68+}
69+
70+void DictBrowser::setPage(const QString &query, const QString &text)
71+{
72+ savePosition();
73+ displayPage(text);
74+
75+ if (entry.title != query && !entry.title.isEmpty())
76+ backwardHistory.prepend(entry);
77+ if (backwardHistory.size() > histSize)
78+ backwardHistory.removeLast();
79+ forwardHistory.clear();
80+ entry.title = query;
81+ entry.page = text;
82+
83+ emit backwardAvailable(!backwardHistory.isEmpty());
84+ emit forwardAvailable(false);
85+ emit historyChanged(query);
86+}
87+
88+void DictBrowser::appendPage(const QString &query, const QString &text)
89+{
90+ savePosition();
91+ append(text);
92+ restorePosition();
93+ entry.page += text;
94+}
95+
96+void DictBrowser::displayPage(const QString &text)
97+{
98+ if (plaintext) setPlainText(text);
99+ else setHtml(text);
100+}
101+
102+void DictBrowser::plainText(bool toggle)
103+{
104+ plaintext = toggle;
105+ displayPage(entry.page);
106+}
107+
108+void DictBrowser::setStyleSheet(const QString &style)
109+{
110+ document()->setDefaultStyleSheet(style);
111+}
112+
113+void DictBrowser::setFont(const QFont &font)
114+{
115+ document()->setDefaultFont(font);
116+ displayPage(entry.page);
117+}
118+
119+void DictBrowser::clearSelection()
120+{
121+ QTextCursor cursor = textCursor();
122+ cursor.clearSelection();
123+ setTextCursor(cursor);
124+}
125+
126+void DictBrowser::busyCursor(bool busy)
127+{
128+ if (busy)
129+ viewport()->setCursor(Qt::BusyCursor);
130+ else
131+ viewport()->setCursor(Qt::ArrowCursor);
132+ cursor = viewport()->cursor();
133+}
134+
135+void DictBrowser::pointCursor(const QString &text)
136+{
137+ if (text.isEmpty())
138+ viewport()->setCursor(cursor);
139+}
140+
141+void DictBrowser::focusOutEvent(QFocusEvent *event)
142+{
143+ QTextEdit::focusOutEvent(event);
144+}
diff -r 000000000000 -r eabf6fad361c dictbrowser.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dictbrowser.h Mon Jan 05 00:54:54 2009 +0000
@@ -0,0 +1,56 @@
1+#ifndef DICTBROWSER_H
2+#define DICTBROWSER_H
3+
4+#include <KTextBrowser>
5+
6+class DictBrowser : public QTextBrowser
7+{
8+ Q_OBJECT
9+
10+ friend class DictSearch;
11+ struct HistoryEntry {
12+ QString title, page;
13+ int hpos, vpos;
14+ };
15+
16+public:
17+ DictBrowser(QWidget *parent = 0);
18+ QStringList backwardList(int len = 10) const
19+ { return historyList(backwardHistory, len); };
20+ QStringList forwardList(int len = 10) const
21+ { return historyList(forwardHistory, len); };
22+ int historySize() const { return histSize; };
23+ void setHistorySize(int size) { histSize = size; };
24+
25+public Q_SLOTS:
26+ void backward() { moveTo(-1); };
27+ void forward() { moveTo(1); };
28+ void moveTo(int steps);
29+ void setPage(const QString &query, const QString &text);
30+ void appendPage(const QString &query, const QString &text);
31+ void plainText(bool toggle);
32+ void setStyleSheet(const QString &style);
33+ void clearHistory();
34+ void setFont(const QFont &font);
35+ void busyCursor(bool busy);
36+ void pointCursor(const QString &text);
37+ void focusOutEvent(QFocusEvent *event);
38+
39+Q_SIGNALS:
40+ void historyChanged(const QString &);
41+
42+private:
43+ QList<HistoryEntry> backwardHistory, forwardHistory;
44+ HistoryEntry entry;
45+ QStringList historyList(const QList<HistoryEntry> &history, int len) const;
46+ int histSize;
47+ void savePosition();
48+ void restorePosition();
49+
50+ QCursor cursor;
51+ bool plaintext;
52+ void clearSelection();
53+ void displayPage(const QString &text);
54+};
55+
56+#endif
diff -r 000000000000 -r eabf6fad361c dictpage.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dictpage.cpp Mon Jan 05 00:54:54 2009 +0000
@@ -0,0 +1,198 @@
1+#include "dictpage.h"
2+
3+#include <KLocale>
4+#include <QString>
5+#include <QStringList>
6+#include <QPalette>
7+#include <QDebug>
8+
9+DictPage::DictPage(const DictResponse &response)
10+{
11+ set(response);
12+}
13+
14+void DictPage::set(const DictResponse &response)
15+{
16+ switch (response.type) {
17+ case Words:
18+ words(response.text);
19+ break;
20+ case Matches:
21+ matches(response.list);
22+ break;
23+ case DatabaseList:
24+ databases(response.list);
25+ break;
26+ case StrategyList:
27+ strategies(response.list);
28+ break;
29+ case DatabaseInfo:
30+ words(response.text);
31+ break;
32+ case ServerInfo:
33+ server(response.text);
34+ break;
35+ default:
36+ set(response.text);
37+ }
38+}
39+
40+QString DictPage::htmltext()
41+{
42+ return html;
43+}
44+
45+void DictPage::set(const QString &text)
46+{
47+ html = text;
48+}
49+
50+void DictPage::matches(const QString &text, bool suggestions)
51+{
52+ QString message = i18n("No matches found for %1", text);
53+ if (suggestions)
54+ html.prepend(QString("<div class=\"message\">%1. Suggestions:</div>").arg(message));
55+ else
56+ set(QString("<div class=\"message\">%1.</div>").arg(message));
57+}
58+
59+void DictPage::heading2(const QString &text)
60+{
61+ html.prepend("<div class=\"head2\">" + text + ": ");
62+ html.append("</div>");
63+}
64+
65+void DictPage::heading(const QString &text)
66+{
67+ html.prepend("<div class=\"head\">" + text + "</div>");
68+}
69+
70+void DictPage::words(const QString &text)
71+{
72+ html = text;
73+ // replace html tags
74+ html.replace('<', "&lt;");
75+ html.replace('>', "&gt;");
76+ html.prepend("<div class=\"define\">");
77+
78+ int start = 0;
79+ while ((start = html.indexOf('{', start + 1)) >= 0) {
80+ int end = html.indexOf('}', start);
81+ // missing matching brace
82+ if (end < 0) break;
83+
84+ int len = end - start;
85+ // too long for a link
86+ if (len > 240) continue;
87+
88+ QString link = html.mid(start + 1, len - 1);
89+ // multiple lines inside braces, could be source code
90+ if (link.count('\n') > 1) continue;
91+
92+ int pos;
93+ // skip external links
94+ if ((pos = link.indexOf('(')) >= 0 && link.indexOf(')') > pos) {
95+ html.replace(start, len + 1, link);
96+ continue;
97+ }
98+ // format link
99+ html.replace(start, len + 1, QString("<a href=\"%1\">%2</a>")
100+ .arg(link.simplified()).arg(link));
101+ }
102+ html.append("</div>");
103+}
104+
105+void DictPage::server(const QString &text)
106+{
107+ html = "<div class=\"info\">";
108+ html += text;
109+ html += "</div>";
110+}
111+
112+void DictPage::matches(const DictList &list)
113+{
114+ html = "<div class=\"match\">";
115+ int count = qMin(list.size(), 240);
116+ for (int i = 0; i < count; i++)
117+ html += QString("<a href=\"%1\">%1</a>\n")
118+ .arg(list[i].second);
119+ html += "</div>";
120+}
121+
122+void DictPage::suggestions(const DictList &list)
123+{
124+ html = "<span class=\"suggestion\">";
125+ int count = qMin(list.size(), 12);
126+ for (int i = 0; i < count; i++)
127+ html += QString("<a href=\"%1\">%1</a>, ")
128+ .arg(list[i].second);
129+ html.chop(2);
130+ html += "</span>";
131+}
132+
133+void DictPage::databases(const DictList &list)
134+{
135+ html = "<table>";
136+ foreach (DictPair pair, list) {
137+ html += QString("<tr><td class=\"key\"><a href=\"about:%1\">%1</a><td>")
138+ .arg(pair.first);
139+ html += "<td>" + pair.second;
140+ }
141+ html += "</table>";
142+}
143+
144+void DictPage::strategies(const DictList &list)
145+{
146+ html = "<table>";
147+ foreach (DictPair pair, list) {
148+ html += "<tr><td class=\"key\">" + pair.first;
149+ html += "<td>" + pair.second;
150+ }
151+ html += "</table>";
152+}
153+
154+void DictPage::error(const QString &text, const QString &host)
155+{
156+ html = "<div class=\"error\">";
157+ html += QString("Error when connecting to %1").arg(host);
158+ html += QString("<div class=\"define\">%1</div>").arg(text);
159+ html += "</div>";
160+}
161+
162+QString DictPage::stylesheet()
163+{
164+// QPalette palette;
165+ QString style;
166+ style += ".define { white-space: pre }";
167+ style += ".define { margin-top: 1em }";
168+ style += ".match { white-space: pre }";
169+ style += ".head { color: white; background: steelblue }";
170+// style += QString(".head { color: %1 }")
171+// .arg(palette.color(QPalette::HighlightedText).name());;
172+// style += QString(".head { background: %1 }")
173+// .arg(palette.color(QPalette::Highlight).name());
174+ style += ".info { font-family: mono }";
175+ style += ".info { white-space: pre }";
176+ style += ".key { padding-right: 1em }";
177+ style += ".head2 { margin-top: 1em; margin-bottom: 1em }";
178+ style += ".message { margin-bottom: 1em }";
179+ style += ".error { margin: 2em }";
180+ style += ".error { background: lightgrey }";
181+// style += QString(".error { background: %1 }")
182+// .arg(palette.color(QPalette::Background).name());
183+ style += "a { text-decoration: none }";
184+ return style;
185+}
186+
187+void DictPage::about(const QString &text)
188+{
189+ html = "<div class=\"about\">";
190+ html += QString("<h2>%1</h2>").arg(text);
191+ html += "<p>Dikt is a dictionary client implementation of Dict protocol. Dikt looks up words on dict servers. You don't need to install any dictionaries, you only need a connection to Internet. You can find more about Dict protocol at <a href=\"http://www.dict.org/\">www.dict.org</a>.";
192+ html += "<p>To look up the word, enter it into the query bar. By default Dikt searches dict.org dict server. To switch to a different server, enter the URL in the form <b>dict://host/word</b>, where <b>host</b> is the dict server to connect to, and <b>word</b> is the word to look for. You only need to specify a URL when you want to change the server, and only the first time. Dikt remembers previous hosts, and you can access them from the host menu.";
193+ html += "<p>You can find a list of dict servers at <a href=\"http://luetzschena-stahmeln.de/dictd/\">luetzschena-stahmeln.de</a>.";
194+ html += "<p>Dikt is very similar to web browsers, and it should be easy to use without long explanations. One option that needs some explanation is to yank selections. When it is set, Dikt will look up the text you select in your KDE and Qt applications.";
195+ html += "<p>Also like web browsers, Dikt doesn't have the control over the content it displays. Some dictionaries are misformatted, just like some web pages are. If you think that the problem is with Dikt, please report it over the <a href=\"http://diktv1.googlepages.com/\">Dikt web site</a>.";
196+ html += "<p>You can see this page again at any time by entering <b>about:</b> in the query bar.";
197+ html += "<p></div>";
198+}
diff -r 000000000000 -r eabf6fad361c dictpage.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dictpage.h Mon Jan 05 00:54:54 2009 +0000
@@ -0,0 +1,33 @@
1+#ifndef DICTPAGE_H
2+#define DICTPAGE_H
3+
4+#include "dict.h"
5+
6+class QString;
7+
8+class DictPage
9+{
10+public:
11+ DictPage() {};
12+ DictPage(const DictResponse &response);
13+ void set(const DictResponse &response);
14+ void set(const QString &text);
15+ QString htmltext();
16+ QString stylesheet();
17+ void error(const QString &text, const QString &host);
18+ void about(const QString &text);
19+ void heading(const QString &text);
20+ void words(const QString &text);
21+ void matches(const DictList &list);
22+ void suggestions(const DictList &list);
23+ void server(const QString &text);
24+ void databases(const DictList &list);
25+ void strategies(const DictList &list);
26+ void matches(const QString &text, bool suggestions);
27+ void heading2(const QString &text);
28+
29+private:
30+ QString html;
31+};
32+
33+#endif
diff -r 000000000000 -r eabf6fad361c dictsettings.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dictsettings.cpp Mon Jan 05 00:54:54 2009 +0000
@@ -0,0 +1,45 @@
1+#include "dictsettings.h"
2+
3+#include <KConfig>
4+#include <QDebug>
5+
6+DictSettings::DictSettings(QWidget *parent)
7+ : KDialog(parent)
8+{
9+ setupUi(this);
10+ setMainWidget(tab);
11+ listbox->setFocus();
12+}
13+
14+QStringList DictSettings::hosts()
15+{
16+ return listbox->items();
17+}
18+
19+void DictSettings::setHosts(const QStringList &hosts)
20+{
21+ listbox->setItems(hosts);
22+}
23+
24+void DictSettings::setFont(const QFont &font)
25+{
26+ fontrequester->setFont(font);
27+}
28+
29+void DictSettings::readConf(const DictConf &conf)
30+{
31+ corrections->setChecked(conf.corrections);
32+ headings->setChecked(conf.headings);
33+ matchFrame->setChecked(conf.matchFrame);
34+// autoMatch->setChecked(conf.autoMatch);
35+ sidebar->setCurrentIndex(conf.sidebar);
36+}
37+
38+void DictSettings::writeConf(DictConf &conf)
39+{
40+ conf.corrections = corrections->isChecked();
41+ conf.headings = headings->isChecked();
42+ conf.matchFrame = matchFrame->isChecked();
43+// conf.autoMatch = autoMatch->isChecked();
44+ conf.sidebar = sidebar->currentIndex();
45+}
diff -r 000000000000 -r eabf6fad361c dictsettings.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dictsettings.h Mon Jan 05 00:54:54 2009 +0000
@@ -0,0 +1,27 @@
1+#ifndef DICTSETTINGS_H
2+#define DICTSETTINGS_H
3+
4+#include "ui_settings.h"
5+
6+#include <KDialog>
7+
8+struct DictConf {
9+ bool corrections, headings, matchFrame, autoMatch;
10+ int sidebar;
11+};
12+
13+class DictSettings : public KDialog, public Ui::Settings
14+{
15+ Q_OBJECT
16+
17+public:
18+ DictSettings(QWidget *parent);
19+ void setHosts(const QStringList &hosts);
20+ QStringList hosts();
21+ void setFont(const QFont &font);
22+ void readConf(const DictConf &conf);
23+ void writeConf(DictConf &conf);
24+ QFont font() { return fontrequester->font(); };
25+};
26+
27+#endif
diff -r 000000000000 -r eabf6fad361c dictwidgets.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dictwidgets.cpp Mon Jan 05 00:54:54 2009 +0000
@@ -0,0 +1,301 @@
1+#include "dictwidgets.h"
2+
3+#include <KComboBox>
4+#include <QToolBar>
5+#include <QDebug>
6+
7+DictSelect::DictSelect(QObject *parent)
8+ : KSelectAction(parent), combobox(0) {}
9+
10+QString DictSelect::currentData() const
11+{
12+ return (currentItem() >= 0 && actions().count())
13+ ? currentAction()->data().toString() : 0;
14+}
15+
16+void DictSelect::setCurrentData(const QString &data)
17+{
18+ foreach (QAction *action, actions())
19+ if (action->data().toString() == data) {
20+ setCurrentAction(action);
21+ if (combobox) combobox->setCurrentIndex(currentItem());
22+ }
23+}
24+
25+void DictSelect::addData(const QString &text, const QString &data)
26+{
27+ addAction(text)->setData(data);
28+ if (combobox) combobox->addItem(data);
29+}
30+
31+void DictSelect::setList(const DictList &list, const QString &selected)
32+{
33+ clear();
34+ foreach(DictPair action, list)
35+ addData(action.second, action.first);
36+ setCurrentData(selected);
37+ setEnabled(!list.isEmpty());
38+}
39+
40+void DictSelect::clear()
41+{
42+ KSelectAction::clear();
43+ if (combobox) combobox->clear();
44+}
45+
46+void DictSelect::actionTriggered(QAction *action)
47+{
48+ emit triggered(action->data().toString());
49+ emit triggered(currentItem());
50+}
51+
52+QWidget *DictSelect::createWidget(QWidget *parent)
53+{
54+ QToolBar *toolbar = qobject_cast<QToolBar *>(parent);
55+ if (!toolbar)
56+ return KSelectAction::createWidget(parent);
57+
58+ combobox = new KComboBox(toolbar);
59+ connect (combobox, SIGNAL(currentIndexChanged(const QString &)),
60+ SLOT(setCurrentData(const QString &)));
61+ connect (this, SIGNAL(triggered(int)),
62+ combobox, SLOT(setCurrentIndex(int)));
63+
64+ int index = currentItem();
65+ foreach (QAction *action, actions())
66+ combobox->addItem(action->data().toString());
67+ combobox->setCurrentIndex(index);
68+
69+ return combobox;
70+}
71+
72+
73+DictMenu::DictMenu(QObject *parent)
74+ : KActionMenu(parent)
75+{
76+ setDelayed(false);
77+ connect(menu(), SIGNAL(triggered(QAction *)),
78+ SLOT(actionTriggered(QAction *)));
79+}
80+
81+QString DictMenu::text(const QString &data)
82+{
83+ foreach (QAction *action, menu()->actions())
84+ if (action->data().toString() == data)
85+ return action->text().remove('&');
86+ return 0;
87+}
88+
89+void DictMenu::addData(const QString &text, const QString &data)
90+{
91+ QAction *action = menu()->addAction(text);
92+ action->setData(data);
93+ action->setCheckable(true);
94+}
95+
96+void DictMenu::setList(const DictList &list, const QStringList &selected)
97+{
98+ clear();
99+ foreach(DictPair action, list)
100+ addData(action.second, action.first);
101+ setCurrentData(selected);
102+ setEnabled(!list.isEmpty());
103+}
104+
105+void DictMenu::setCurrentData(const QStringList &list)
106+{
107+ foreach (QAction *action, menu()->actions())
108+ action->setChecked(list.contains(action->data().toString()));
109+}
110+
111+QStringList DictMenu::currentData()
112+{
113+ QStringList list;
114+ foreach (QAction *action, menu()->actions())
115+ if (action->isChecked())
116+ list.append(action->data().toString());
117+ return list;
118+}
119+
120+void DictMenu::actionTriggered(QAction *action)
121+{
122+ emit selected(currentData());
123+}
124+
125+
126+DictHistory::DictHistory(DictBrowser *parent, Direction dir)
127+ : QMenu(parent)
128+{
129+ browser = parent;
130+ direction = dir;
131+ connect(this, SIGNAL(triggered(QAction *)), SLOT(steps(QAction *)));
132+ connect(this, SIGNAL(aboutToShow()), SLOT(setMenu()));
133+}
134+
135+void DictHistory::steps(QAction *action)
136+{
137+ browser->moveTo((direction) ? action->data().toInt() : -action->data().toInt());
138+}
139+
140+void DictHistory::setMenu()
141+{
142+ setList((direction) ? browser->forwardList() : browser->backwardList());
143+}
144+
145+void DictHistory::setList(const QStringList &list)
146+{
147+ clear();
148+ for (int i = 0; i < list.size(); i++)
149+ addAction(list.at(i))->setData(i + 1);
150+}
151+
152+
153+DictView::DictView(QWidget *parent)
154+ : QListWidget(parent)
155+{
156+ setSelectionMode(QAbstractItemView::MultiSelection);
157+ connect(this, SIGNAL(itemSelectionChanged()), SLOT(selection()));
158+}
159+
160+void DictView::selection()
161+{
162+ QStringList list;
163+ for (int i = 0; i < count(); ++i)
164+ if (item(i)->isSelected())
165+ list << item(i)->data(Qt::UserRole).toString();
166+ emit selected(list);
167+}
168+
169+void DictView::setList(const DictList &list, const QStringList &selected)
170+{
171+ blockSignals(true);
172+ clear();
173+ blockSignals(false);
174+ foreach (DictPair pair, list)
175+ addItem(pair.second);
176+ for (int i = 0; i < count(); ++i)
177+ item(i)->setData(Qt::UserRole, list[i].first);
178+ setCurrentData(selected);
179+}
180+
181+QString DictView::data(int index)
182+{
183+ return item(index)->data(Qt::UserRole).toString();
184+}
185+
186+void DictView::setCurrentData(const QStringList &list)
187+{
188+ blockSignals(true);
189+ for (int i = 0; i < count(); ++i)
190+ item(i)->setSelected(list.contains(data(i)));
191+ blockSignals(false);
192+}
193+
194+
195+#include <KLocale>
196+#include <QKeyEvent>
197+
198+DictSearch::DictSearch(DictBrowser *parent)
199+ : QWidget(parent), browser(parent), found(false)
200+{
201+ setupUi(this);
202+
203+ toolbutton->setIcon(KIcon("dialog-close"));
204+ label->setText(i18n("Find:"));
205+ connect(pattern, SIGNAL(textChanged(const QString &)),
206+ SLOT(search(const QString &)));
207+
208+ layout()->setAlignment(Qt::AlignLeft);
209+ layout()->setContentsMargins(4, 0, 4, 0);
210+ setFocusProxy(pattern);
211+}
212+
213+void DictSearch::show()
214+{
215+ QWidget::show();
216+ setFocus();
217+ pattern->selectAll();
218+}
219+
220+void DictSearch::hide()
221+{
222+ browser->setFocus();
223+ QWidget::hide();
224+}
225+
226+void DictSearch::find(QTextDocument::FindFlags backward)
227+{
228+ if (!found) {
229+ show();
230+ search(pattern->text());
231+ return;
232+ }
233+ browser->savePosition();
234+ if (backward && browser->textCursor().atStart())
235+ browser->moveCursor(QTextCursor::End);
236+
237+ if (browser->find(pattern->text(), backward))
238+ message->setText(i18n("Text found"));
239+ else {
240+ browser->clearSelection();
241+ browser->moveCursor(QTextCursor::Start);
242+ browser->restorePosition();
243+ message->setText(i18n("No more matches"));
244+ }
245+}
246+
247+void DictSearch::search(const QString &text)
248+{
249+ browser->savePosition();
250+ if (text.isEmpty()) {
251+ browser->clearSelection();
252+ browser->restorePosition();
253+ clear();
254+ return;
255+ }
256+ browser->moveCursor(QTextCursor::Start);
257+ if (found = browser->find(text))
258+ message->setText(i18n("Text found"));
259+ else {
260+ browser->restorePosition();
261+ message->setText(i18n("Text not found"));
262+ }
263+}
264+
265+void DictSearch::clear()
266+{
267+ if (!isVisible())
268+ pattern->clear();
269+ message->clear();
270+ found = false;
271+}
272+
273+void DictSearch::keyPressEvent(QKeyEvent *event)
274+{
275+ if (event->key() == Qt::Key_Escape)
276+ hide();
277+ else
278+ browser->keyPressEvent(event);
279+}
280+
281+
282+#include <KIconLoader>
283+#include <QPixmap>
284+
285+DictStatus::DictStatus(QWidget *parent)
286+ : QWidget(parent)
287+{
288+ picture = new QLabel(this);
289+ label = new QLabel(this);
290+ QLayout *layout = new QHBoxLayout(this);
291+ layout->addWidget(picture);
292+ layout->addWidget(label);
293+ layout->setContentsMargins(4, 0, 10, 0);
294+}
295+
296+void DictStatus::setStatus(const char *icon, const QString &text, bool enabled)
297+{
298+ QPixmap pix = SmallIcon(icon, KIconLoader::SizeSmall, (enabled) ? KIconLoader::DefaultState : KIconLoader::DisabledState);
299+ picture->setPixmap(pix);
300+ label->setText(text);
301+}
diff -r 000000000000 -r eabf6fad361c dictwidgets.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dictwidgets.h Mon Jan 05 00:54:54 2009 +0000
@@ -0,0 +1,152 @@
1+#ifndef DICTWIDGETS_H
2+#define DICTWIDGETS_H
3+
4+#include "dict.h"
5+
6+#include <KSelectAction>
7+
8+class KComboBox;
9+
10+class DictSelect : public KSelectAction
11+{
12+ Q_OBJECT
13+
14+public:
15+ DictSelect(QObject *parent = 0);
16+ QString currentData() const;
17+ void addData(const QString &text, const QString &data);
18+ void setList(const DictList &list, const QString &selected);
19+ void clear();
20+
21+public Q_SLOTS:
22+ void setCurrentData(const QString &data);
23+
24+private Q_SLOTS:
25+ void actionTriggered(QAction *action);
26+
27+private:
28+ KComboBox *combobox;
29+ QWidget *createWidget(QWidget *parent);
30+};
31+
32+
33+#include <KActionMenu>
34+#include <KMenu>
35+
36+class DictMenu : public KActionMenu
37+{
38+ Q_OBJECT
39+
40+public:
41+ DictMenu(QObject *parent = 0);
42+ QStringList currentData();
43+ void addData(const QString &text, const QString &data);
44+ void setList(const DictList &list, const QStringList &selected);
45+ QString text(const QString &data);
46+ void clear() { menu()->clear(); };
47+
48+public Q_SLOTS:
49+ void setCurrentData(const QStringList &data);
50+
51+Q_SIGNALS:
52+ void selected(const QStringList &);
53+
54+private Q_SLOTS:
55+ void actionTriggered(QAction *action);
56+};
57+
58+
59+#include "dictbrowser.h"
60+
61+class DictHistory : public QMenu
62+{
63+ Q_OBJECT
64+
65+public:
66+ enum Direction { Backward, Forward };
67+ DictHistory(DictBrowser *parent, Direction direction);
68+
69+Q_SIGNALS:
70+ void selected(int);
71+
72+private Q_SLOTS:
73+ void setList(const QStringList &list);
74+ void steps(QAction *action);
75+ void setMenu();
76+
77+private:
78+ Direction direction;
79+ DictBrowser *browser;
80+};
81+
82+
83+#include <QListWidget>
84+
85+class DictView : public QListWidget
86+{
87+ Q_OBJECT
88+public:
89+ DictView(QWidget *parent = 0);
90+ void setList(const DictList &list, const QStringList &selected);
91+
92+Q_SIGNALS:
93+ void selected(const QStringList&);
94+
95+public Q_SLOTS:
96+ void setCurrentData(const QStringList &list);
97+
98+private Q_SLOTS:
99+ void selection();
100+
101+private:
102+ QString data(int index);
103+};
104+
105+
106+#include "ui_searchbar.h"
107+#include <QWidget>
108+
109+class DictSearch : public QWidget, public Ui::Searchbar
110+{
111+ Q_OBJECT
112+
113+public:
114+ DictSearch(DictBrowser *parent);
115+
116+public Q_SLOTS:
117+ void findNext() { find(); };
118+ void findPrev() { find(QTextDocument::FindBackward); };
119+
120+ void show();
121+ void hide();
122+ void clear();
123+
124+private Q_SLOTS:
125+ void find(QTextDocument::FindFlags direction = 0);
126+ void search(const QString &text);
127+
128+private:
129+ DictBrowser *browser;
130+ bool found;
131+
132+ void keyPressEvent(QKeyEvent *event);
133+};
134+
135+
136+#include <KIconLoader>
137+
138+class DictStatus : public QWidget
139+{
140+ Q_OBJECT
141+
142+public:
143+ DictStatus(QWidget *parent);
144+
145+public Q_SLOTS:
146+ void setStatus(const char *icon, const QString &text, bool enabled);
147+
148+private:
149+ QLabel *picture, *label;
150+};
151+
152+#endif
diff -r 000000000000 -r eabf6fad361c dictwindow.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dictwindow.cpp Mon Jan 05 00:54:54 2009 +0000
@@ -0,0 +1,878 @@
1+#include "dictwindow.h"
2+#include "dictbrowser.h"
3+#include "dictwidgets.h"
4+#include "dictpage.h"
5+#include "dictsettings.h"
6+#include "dict.h"
7+
8+#include <KApplication>
9+#include <KAction>
10+#include <KLocale>
11+#include <KActionCollection>
12+#include <KActionMenu>
13+#include <KStandardAction>
14+#include <KSelectAction>
15+#include <KToolBarPopupAction>
16+#include <KStatusBar>
17+#include <KMenuBar>
18+#include <KConfig>
19+#include <KConfigGroup>
20+#include <KPasswordDialog>
21+#include <KToolInvocation>
22+
23+#include <QDebug>
24+#include <QComboBox>
25+#include <QLabel>
26+#include <QUrl>
27+#include <QSplitter>
28+#include <QStackedWidget>
29+
30+DictWindow::DictWindow(QWidget *parent)
31+ : KXmlGuiWindow(parent), settings(0)
32+{
33+ entry = new QComboBox(this);
34+ entry->setEditable(true);
35+ entry->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
36+ entry->lineEdit()->setMaxLength(maxQueryLen);
37+ entry->setCompleter(0);
38+
39+ browser = new DictBrowser(this);
40+ search = new DictSearch(browser);
41+ search->hide();
42+
43+ databaseList = new DictView(this);
44+ matchList = new DictBrowser(this);
45+ matchList->setHistorySize(10);
46+
47+ sidebar = new QStackedWidget(this);
48+ sidebar->addWidget(databaseList);
49+ sidebar->addWidget(matchList);
50+
51+ splitter = new QSplitter(this);
52+ splitter->addWidget(browser);
53+ splitter->addWidget(sidebar);
54+
55+ QWidget *widget = new QWidget(this);
56+ QVBoxLayout *layout = new QVBoxLayout(widget);
57+ layout->setContentsMargins(0, 0, 0, 0);
58+ layout->addWidget(splitter);
59+ layout->addWidget(search);
60+ setCentralWidget(widget);
61+
62+ dict = new Dict();
63+
64+ setupActions();
65+ setupGUI();
66+ setupBrowser();
67+ setupDict();
68+ setupStatusbar();
69+ readConfig();
70+
71+ show();
72+}
73+
74+DictWindow::~DictWindow()
75+{
76+ writeConfig();
77+ config->sync();
78+ delete dict;
79+}
80+
81+void DictWindow::readConfig()
82+{
83+ config = KGlobal::config();
84+ KConfigGroup mainConfig(config, "Dikt");
85+
86+ conf.autoMatch = mainConfig.readEntry("AutoMatch", false);
87+ conf.corrections = mainConfig.readEntry("Corrections", true);
88+ conf.headings = mainConfig.readEntry("Headings", true);
89+ conf.matchFrame = mainConfig.readEntry("MatchFrame", true);
90+
91+ bool yank = mainConfig.readEntry("Yank", false);
92+ actionCollection()->action("yank")->setChecked(yank);
93+// yankMode(yank);
94+ enableMatchList(conf.matchFrame);
95+
96+ QString font = mainConfig.readEntry("Font", "");
97+ if (!font.isEmpty()) {
98+ QFont newfont;
99+ if(newfont.fromString(font));
100+ setFont(newfont);
101+ }
102+ readWidthsConfig();
103+ readServerConfig();
104+}
105+
106+void DictWindow::readServerConfig()
107+{
108+ KConfigGroup serverConfig(config, "Server");
109+ QStringList hosts = serverConfig.readEntry("Hosts", QStringList(Dict::DefaultHost));
110+
111+ int selected = serverConfig.readEntry("Selected", -1);
112+ if (selected < 0) about("about:");
113+ else entry->lineEdit()->setFocus();
114+ selected = qBound(0, selected, hosts.size() - 1);
115+ QString host = hosts[selected];
116+
117+ foreach(QString name, hosts)
118+ hostMenu->addAction(name);
119+
120+ hostMenu->setCurrentItem(selected);
121+ setHost(host);
122+}
123+
124+void DictWindow::hostConfig(const QString &host)
125+{
126+ KConfigGroup hostConfig(config, host);
127+ int port = hostConfig.readEntry("Port", Dict::DefaultPort);
128+ dict->setHost(host, port);
129+
130+ QString username = hostConfig.readEntry("Username", "");
131+ QString password = hostConfig.readEntry("Password", "");
132+ if (!username.isEmpty())
133+ dict->setUser(username, password);
134+}
135+
136+QStringList DictWindow::databaseConfig()
137+{
138+ KConfigGroup hostConfig(config, dict->host());
139+ return hostConfig.readEntry("Database", QStringList());
140+}
141+
142+QString DictWindow::strategyConfig()
143+{
144+ KConfigGroup hostConfig(config, dict->host());
145+ return hostConfig.readEntry("Strategy", QString());
146+}
147+
148+void DictWindow::writeConfig()
149+{
150+ KConfigGroup mainConfig(config, "Dikt");
151+ bool yank = actionCollection()->action("yank")->isChecked();
152+ mainConfig.writeEntry("Yank" , yank);
153+ mainConfig.writeEntry("Splitter", splitter->sizes());
154+ mainConfig.writeEntry("Sidebar", conf.sidebar);
155+ mainConfig.writeEntry("Stack", sidebar->currentIndex());
156+
157+ mainConfig.writeEntry("AutoMatch", conf.autoMatch);
158+ mainConfig.writeEntry("Corrections", conf.corrections);
159+ mainConfig.writeEntry("Headings", conf.headings);
160+ mainConfig.writeEntry("MatchFrame", conf.matchFrame);
161+
162+ mainConfig.writeEntry("Font", font().toString());
163+
164+ writeServerConfig();
165+}
166+
167+void DictWindow::writeServerConfig()
168+{
169+ KConfigGroup serverConfig(config, "Server");
170+ QStringList hosts = hostMenu->items();
171+ serverConfig.writeEntry("Hosts", hosts);
172+ serverConfig.writeEntry("Selected", hostMenu->currentItem());
173+ writeHostConfig();
174+}
175+
176+void DictWindow::writeHostConfig()
177+{
178+ if (!databaseMenu->isEnabled())
179+ return;
180+
181+ QString host = dict->host();
182+ KConfigGroup hostConf(config, host);
183+ hostConf.writeEntry("Database", database());
184+ hostConf.writeEntry("Strategy", strategy());
185+}
186+
187+void DictWindow::readWidthsConfig()
188+{
189+ KConfigGroup mainConfig(config, "Dikt");
190+ int &side = conf.sidebar = mainConfig.readEntry("Sidebar", 0);
191+ if (side) side = 1;
192+ setSidebar(side);
193+
194+ QList<int> sizes, widths;
195+ sizes << 0 << 1;
196+ widths << 100 << 200;
197+ sizes = mainConfig.readEntry("Splitter", sizes);
198+ widths = mainConfig.readEntry("Widths", widths);
199+
200+ splitter->setSizes((sizes[side]) ? sizes: widths);
201+ sidebar->setVisible(sizes[side]);
202+ sidebar->setCurrentIndex(mainConfig.readEntry("Stack", 0));
203+}
204+
205+void DictWindow::writeWidthsConfig()
206+{
207+ KConfigGroup mainConfig(config, "Dikt");
208+ QList<int> sizes = splitter->sizes();
209+ mainConfig.writeEntry("Widths", sizes);
210+}
211+
212+void DictWindow::setupActions()
213+{
214+ KAction *text = new KAction(this);
215+ text->setText(i18n("Page Source"));
216+ text->setCheckable(true);
217+ actionCollection()->addAction("text", text);
218+
219+ connect(text, SIGNAL(toggled(bool)), browser, SLOT(plainText(bool)));
220+
221+ KAction *yank = new KAction(this);
222+ yank->setText(i18n("Yank Selections"));
223+ yank->setCheckable(true);
224+ actionCollection()->addAction("yank", yank);
225+
226+ connect(yank, SIGNAL(toggled(bool)), SLOT(yankMode(bool)));
227+
228+ KAction *sidebar = new KAction(this);
229+ sidebar->setText(i18n("Database List"));
230+// sidebar->setCheckable(true);
231+ actionCollection()->addAction("sidebar", sidebar);
232+
233+ connect(sidebar, SIGNAL(triggered(bool)), SLOT(toggleDatabaseList()));
234+
235+ KAction *matches = new KAction(this);
236+ matches->setText(i18n("Match List"));
237+// matches->setCheckable(true);
238+ actionCollection()->addAction("matches", matches);
239+
240+ connect(matches, SIGNAL(triggered()), SLOT(toggleMatchList()));
241+
242+ KAction *define = new KAction(this);
243+ define->setText(i18n("Define"));
244+ define->setShortcut(Qt::CTRL + Qt::Key_D);
245+ actionCollection()->addAction("define", define);
246+
247+ connect(define, SIGNAL(triggered()), SLOT(define()));
248+
249+ KAction *match = new KAction(this);
250+ match->setText(i18n("Match"));
251+ match->setShortcut(Qt::CTRL + Qt::Key_M);
252+ actionCollection()->addAction("match", match);
253+
254+ connect(match, SIGNAL(triggered()), SLOT(match()));
255+
256+ KAction *clear = new KAction(this);
257+ clear->setText(i18n("Clear History"));
258+ actionCollection()->addAction("clear", clear);
259+// clear->setEnabled(false);
260+
261+ connect(clear, SIGNAL(triggered()), browser, SLOT(clearHistory()));
262+ connect(clear, SIGNAL(triggered()), matchList, SLOT(clearHistory()));
263+
264+ KAction *prev = new KAction(this);
265+ prev->setText(i18n("Previous Match"));
266+ prev->setShortcut(Qt::CTRL + Qt::Key_Left);
267+ actionCollection()->addAction("prev", prev);
268+ prev->setEnabled(false);
269+
270+ connect(prev, SIGNAL(triggered()), matchList, SLOT(backward()));
271+ connect(matchList, SIGNAL(backwardAvailable(bool)),
272+ prev, SLOT(setEnabled(bool)));
273+
274+ KAction *next = new KAction(this);
275+ next->setText(i18n("Next Match"));
276+ next->setShortcut(Qt::CTRL + Qt::Key_Right);
277+ actionCollection()->addAction("next", next);
278+ next->setEnabled(false);
279+
280+ connect(next, SIGNAL(triggered()), matchList, SLOT(forward()));
281+ connect(matchList, SIGNAL(forwardAvailable(bool)),
282+ next, SLOT(setEnabled(bool)));
283+
284+ KActionMenu *info = new KActionMenu(this);
285+ info->setText(i18n("About"));
286+// info->setIcon(KIcon("dialog-information"));
287+ actionCollection()->addAction("info", info);
288+
289+ infoMenu = info->menu();
290+ connect(infoMenu, SIGNAL(triggered(QAction *)), SLOT(info(QAction *)));
291+
292+ QAction *server = new QAction(this);
293+ server->setText(i18n("Server"));
294+ server->setData("server");
295+ infoMenu->addAction(server);
296+
297+ QAction *databases = new QAction(this);
298+ databases->setText(i18n("Databases"));
299+ databases->setData("databases");
300+ infoMenu->addAction(databases);
301+
302+ QAction *strategies = new QAction(this);
303+ strategies->setText(i18n("Strategies"));
304+ strategies->setData("strategies");
305+ infoMenu->addAction(strategies);
306+
307+ hostMenu = new KSelectAction(this);
308+ hostMenu->setText(i18n("Host"));
309+ actionCollection()->addAction("host", hostMenu);
310+
311+ connect(hostMenu, SIGNAL(triggered(const QString &)),
312+ SLOT(setHost(const QString &)));
313+
314+ databaseMenu = new DictMenu(this);
315+ databaseMenu->setText(i18n("Database"));
316+ actionCollection()->addAction("database", databaseMenu);
317+ databaseMenu->setEnabled(false);
318+
319+ connect(databaseMenu, SIGNAL(selected(const QStringList &)),
320+ databaseList, SLOT(setCurrentData(const QStringList &)));
321+ connect(databaseList, SIGNAL(selected(const QStringList &)),
322+ databaseMenu, SLOT(setCurrentData(const QStringList &)));
323+
324+ strategyMenu = new DictSelect(this);
325+ strategyMenu->setText(i18n("Strategy"));
326+ actionCollection()->addAction("strategy", strategyMenu);
327+ strategyMenu->setEnabled(false);
328+
329+ KAction *backward = new KToolBarPopupAction(KIcon("go-previous"),
330+ i18n("Backward"), this);
331+ actionCollection()->addAction("backward", backward);
332+ backward->setShortcut(Qt::ALT + Qt::Key_Left);
333+ backward->setEnabled(false);
334+
335+ connect(backward, SIGNAL(triggered()), browser, SLOT(backward()));
336+ connect(browser, SIGNAL(backwardAvailable(bool)),
337+ backward, SLOT(setEnabled(bool)));
338+ connect(backward, SIGNAL(triggered()), SLOT(cancel()));
339+
340+ backwardMenu = new DictHistory(browser, DictHistory::Backward);
341+ backward->setMenu(backwardMenu);
342+ connect(backwardMenu, SIGNAL(triggered(QAction *)), SLOT(cancel()));
343+
344+ KAction *forward = new KToolBarPopupAction(KIcon("go-next"),
345+ i18n("Forward"), this);
346+ actionCollection()->addAction("forward", forward);
347+ forward->setShortcut(Qt::ALT + Qt::Key_Right);
348+ forward->setEnabled(false);
349+
350+ connect(forward, SIGNAL(triggered()), browser, SLOT(forward()));
351+ connect(browser, SIGNAL(forwardAvailable(bool)),
352+ forward, SLOT(setEnabled(bool)));
353+
354+ connect(forward, SIGNAL(triggered()), SLOT(cancel()));
355+
356+ forwardMenu = new DictHistory(browser, DictHistory::Forward);
357+ forward->setMenu(forwardMenu);
358+ connect(forwardMenu, SIGNAL(triggered(QAction *)), SLOT(cancel()));
359+
360+ stop = new KAction(KIcon("process-stop"), i18n("Stop"), this);
361+ stop->setShortcut(Qt::Key_Escape);
362+ actionCollection()->addAction("stop", stop);
363+ stop->setEnabled(false);
364+
365+ connect(this, SIGNAL(loading(bool)), stop, SLOT(setEnabled(bool)));
366+ connect(this, SIGNAL(loading(bool)), matchList, SLOT(busyCursor(bool)));
367+ connect(this, SIGNAL(loading(bool)), browser, SLOT(busyCursor(bool)));
368+ connect(stop, SIGNAL(triggered()), SLOT(cancel()));
369+
370+ KAction *frame = new KAction(this);
371+ frame->setText(i18n("Next Frame"));
372+ actionCollection()->addAction("frame", frame);
373+
374+ connect(frame, SIGNAL(triggered()), SLOT(nextFrame()));
375+
376+ KAction *auth = new KAction(this);
377+ auth->setText(i18n("Authentication..."));
378+ actionCollection()->addAction("auth", auth);
379+
380+ connect(auth, SIGNAL(triggered()), SLOT(authenticate()));
381+
382+ QLabel *label = new QLabel(this);
383+ label->setText(i18n("Look for:"));
384+ label->setIndent(10);
385+ KAction *action = new KAction(this);
386+ action->setDefaultWidget(label);
387+ action->setText(i18n("Look for"));
388+ actionCollection()->addAction("search", action);
389+
390+ KAction* combo = new KAction(this);
391+ combo->setText(i18n("Query"));
392+ combo->setShortcut(Qt::CTRL + Qt::Key_L);
393+ combo->setDefaultWidget(entry);
394+ actionCollection()->addAction("query", combo);
395+
396+ connect(combo, SIGNAL(triggered()), entry, SLOT(setFocus()));
397+ connect(combo, SIGNAL(triggered()), entry->lineEdit(), SLOT(selectAll()));
398+ connect(entry, SIGNAL(activated(int)), SLOT(define()));
399+
400+ KStandardAction::openNew(this, SLOT(newWindow()), actionCollection());
401+// KStandardAction::save(this, SLOT(save()), actionCollection());
402+// KStandardAction::print(this, SLOT(print()), actionCollection());
403+
404+ KStandardAction::close(this, SLOT(close()), actionCollection());
405+ KStandardAction::quit(kapp, SLOT(closeAllWindows()), actionCollection());
406+
407+ KStandardAction::find(search, SLOT(show()), actionCollection());
408+ KStandardAction::findNext(search, SLOT(findNext()), actionCollection());
409+ KStandardAction::findPrev(search, SLOT(findPrev()), actionCollection());
410+
411+ KStandardAction::showMenubar(this, SLOT(toggleMenubar()), actionCollection());
412+ KStandardAction::preferences(this, SLOT(configure()), actionCollection());
413+}
414+
415+void DictWindow::setupBrowser()
416+{
417+ connect(browser, SIGNAL(historyChanged(const QString &)),
418+ entry, SLOT(setEditText(const QString &)));
419+ connect(browser, SIGNAL(historyChanged(const QString &)),
420+ SLOT(setCaption(const QString &)));
421+
422+ connect(browser, SIGNAL(anchorClicked(const QUrl &)),
423+ SLOT(define(const QUrl &)));
424+ connect(browser, SIGNAL(highlighted(const QString &)),
425+ statusBar(), SLOT(showMessage(const QString &)));
426+
427+ connect(browser, SIGNAL(historyChanged(const QString &)),
428+ search, SLOT(clear()));
429+
430+ connect(matchList, SIGNAL(anchorClicked(const QUrl &)),
431+ SLOT(define(const QUrl &)));
432+ connect(matchList, SIGNAL(highlighted(const QString &)),
433+ statusBar(), SLOT(showMessage(const QString &)));
434+
435+ browser->setStyleSheet(page.stylesheet());
436+ matchList->setStyleSheet(page.stylesheet());
437+}
438+
439+void DictWindow::statusMessage(const QString &message)
440+{
441+ statusBar()->showMessage(message, (message.endsWith("...")) ? 0 : 4000);
442+}
443+
444+void DictWindow::setHostStatus(bool connected)
445+{
446+ hostStatus->setStatus("network-workgroup", dict->host(), connected);
447+}
448+
449+void DictWindow::setUserStatus(bool authenticated)
450+{
451+ if (!userStatus)
452+ userStatus = new DictStatus(statusBar());
453+ if (authenticated) {
454+ if (userStatus->isVisible())
455+ return;
456+ userStatus->setStatus("user-identity", dict->user(), authenticated);
457+ statusBar()->addPermanentWidget(userStatus);
458+ statusBar()->addPermanentWidget(hostStatus);
459+ userStatus->show();
460+ } else
461+ statusBar()->removeWidget(userStatus);
462+}
463+
464+void DictWindow::setupStatusbar()
465+{
466+ hostStatus = new DictStatus(statusBar());
467+ statusBar()->addPermanentWidget(hostStatus);
468+ userStatus = 0;
469+}
470+
471+void DictWindow::setupDict()
472+{
473+// connect(dict, SIGNAL(responseText(const QString &)),
474+// SLOT(response(const QString &)));
475+ connect(dict, SIGNAL(statusMessage(const QString &)),
476+ SLOT(statusMessage(const QString &)));
477+ connect(dict, SIGNAL(errorMessage(const QString &)),
478+ SLOT(error(const QString &)));
479+
480+ connect(dict, SIGNAL(responseProcessed(const DictResponse &)),
481+ SLOT(response(const DictResponse &)));
482+ connect(dict, SIGNAL(authenticated(bool)),
483+ SLOT(setUserStatus(bool)));
484+}
485+
486+void DictWindow::setDatabaseMenu(const DictList &list)
487+{
488+ QStringList selected = database();
489+ if (selected.isEmpty())
490+ selected = databaseConfig();
491+ databaseMenu->setList(list, selected);
492+ databaseList->setList(list, selected);
493+}
494+
495+void DictWindow::setStrategyMenu(const DictList &list)
496+{
497+ QString selected = strategy();
498+ if (selected.isEmpty())
499+ selected = strategyConfig();
500+ strategyMenu->setList(list, selected);
501+}
502+
503+void DictWindow::define(const QString &text)
504+{
505+ if (text.isEmpty()) return;
506+ query = text.simplified();
507+ query.truncate(maxQueryLen);
508+
509+ if (stop->isEnabled())
510+ return;
511+ tracker.clear();
512+ browser->setFocus();
513+ emit loading(true);
514+ if (query.startsWith("about:"))
515+ about(query);
516+ else if (query.startsWith("dict:"))
517+ url(query);
518+ else if (query.startsWith("http:")) {
519+ KToolInvocation::invokeBrowser(text);
520+ emit loading(false);
521+ }
522+ else foreach(QString database, databases())
523+ dict->define(query, database);
524+}
525+
526+void DictWindow::define()
527+{
528+ define(entry->currentText());
529+}
530+
531+void DictWindow::define(const QUrl &link)
532+{
533+ define(link.toString());
534+}
535+
536+void DictWindow::match(const QString &text)
537+{
538+ if (text.isEmpty()) return;
539+ query = text.simplified();
540+ query.truncate(maxQueryLen);
541+
542+ if (query.startsWith("about:"))
543+ return;
544+ else if(query.startsWith("dict:"))
545+ return;
546+ else if (query.startsWith("http:"))
547+ return;
548+
549+ if (stop->isEnabled())
550+ return;
551+ tracker.match = true;
552+ browser->setFocus();
553+ emit loading(true);
554+ foreach(QString database, databases())
555+ dict->match(query, database, strategies());
556+}
557+
558+void DictWindow::match()
559+{
560+ match(entry->currentText());
561+}
562+
563+void DictWindow::about(const QString &query)
564+{
565+ QString text = query.mid(6);
566+ if (text.isEmpty()) {
567+ page.about("Dikt Version 1");
568+ browser->setPage(query, page.htmltext());
569+ emit loading(false);
570+ return;
571+ }
572+ foreach(QAction *action, infoMenu->actions())
573+ if (action->data().toString() == text) {
574+ dict->info(text);
575+ return;
576+ }
577+ foreach(QAction *action, databaseMenu->menu()->actions())
578+ if (action->data().toString() == text) {
579+ dict->info("info " + text);
580+ return;
581+ }
582+ error(i18n("No such database %1", text));
583+}
584+
585+void DictWindow::info(QAction *action)
586+{
587+ QString text = action->data().toString();
588+ query = "about:" + text;
589+ browser->setFocus();
590+ emit loading(true);
591+ dict->info(text);
592+}
593+
594+void DictWindow::response(const QString &text)
595+{
596+ qDebug() << text;
597+}
598+
599+void DictWindow::response(const DictResponse &response)
600+{
601+ DictBrowser *target = browser;
602+ page.set(response);
603+
604+ if (response.type == Words) {
605+ if (conf.headings)
606+ page.heading(response.database);
607+ }
608+ else if (response.type == Matches) {
609+ if (tracker.correct) {
610+ page.suggestions(response.list);
611+ page.heading2(response.database);
612+ if (!tracker.hits)
613+ page.matches(query, true);
614+ } else if (conf.matchFrame) {
615+ target = matchList;
616+ sidebar->show();
617+ sidebar->setCurrentWidget(matchList);
618+ matchList->setFocus();
619+ }
620+ if (conf.headings && !tracker.correct)
621+ page.heading(response.database);
622+ }
623+ else if (response.type == NoMatch) {
624+ if (++tracker.misses < dbcount()) {
625+ if (tracker.count() >= dbcount()) {
626+ tracker.clear();
627+ emit loading(false);
628+ }
629+ return;
630+ } else if (conf.corrections && !tracker.correct) {
631+ tracker.clear();
632+ tracker.correct = true;
633+ emit loading(false);
634+ match(query);
635+ return;
636+ }
637+ page.matches(query, false);
638+ }
639+ else if (response.type == DatabaseList) {
640+ setDatabaseMenu(response.list);
641+ if (tracker.init) {
642+ setHostStatus(true);
643+ return;
644+ }
645+ }
646+ else if (response.type == StrategyList) {
647+ setStrategyMenu(response.list);
648+ if (tracker.init) {
649+// emit loading(false);
650+ tracker.init = false;
651+ return;
652+ }
653+ }
654+ else if (response.type == AuthOK) {
655+ initDatabases();
656+ }
657+
658+ if (!tracker.hits)
659+ target->setPage(query, page.htmltext());
660+ else
661+ target->appendPage(query, page.htmltext());
662+
663+ if (response.type == Words || response.type == Matches) {
664+ ++tracker.hits;
665+ if (tracker.count() >= dbcount()) {
666+ tracker.clear();
667+ emit loading(false);
668+ }
669+ } else {
670+ tracker.clear();
671+ emit loading(false);
672+ }
673+}
674+
675+void DictWindow::error(const QString &text)
676+{
677+ page.error(text, dict->host());
678+ browser->setPage(query, page.htmltext());
679+ browser->setFocus();
680+ emit loading(false);
681+}
682+
683+void DictWindow::cancel()
684+{
685+ if (stop->isEnabled()) {
686+ tracker.clear();
687+ dict->cancel();
688+ emit loading(false);
689+ tracker.init = false;
690+ }
691+}
692+
693+void DictWindow::url(const QString &query)
694+{
695+ QUrl url(query);
696+ QString host = url.host();
697+// int port = url.port();
698+ if (host.isEmpty()) {
699+ error(i18n("Malformed Url"));
700+ return;
701+ }
702+ if (host != dict->host()) {
703+ setHost(host);
704+ int index = hostMenu->items().indexOf(host);
705+ if (index < 0) {
706+ index = hostMenu->items().size();
707+ hostMenu->addAction(host);
708+ }
709+ hostMenu->setCurrentItem(index);
710+ }
711+ QString path = url.path();
712+ emit loading(true);
713+ if (path.size() <= 1)
714+ dict->status();
715+// else dict->define(path.mid(1));
716+ else foreach(QString database, databases())
717+ dict->define(path.mid(1), database);
718+}
719+
720+void DictWindow::setHost(const QString &host)
721+{
722+ cancel();
723+ writeHostConfig();
724+ hostConfig(host);
725+ databaseMenu->clear();
726+ databaseList->clear();
727+ strategyMenu->clear();
728+ databaseMenu->setDisabled(true);
729+ strategyMenu->setDisabled(true);
730+ tracker.clear();
731+ initDatabases();
732+ setHostStatus(false);
733+ if (userStatus)
734+ setUserStatus(false);
735+}
736+
737+void DictWindow::initDatabases()
738+{
739+ tracker.init = true;
740+ dict->info("databases");
741+ dict->info("strategies");
742+// emit loading(true);
743+}
744+
745+void DictWindow::yankMode(bool toggle)
746+{
747+ if (toggle)
748+ connect(kapp->clipboard(), SIGNAL(changed(QClipboard::Mode)),
749+ SLOT(yankClipboard(QClipboard::Mode)));
750+ else
751+ kapp->clipboard()->disconnect(this);
752+}
753+
754+void DictWindow::yankClipboard(QClipboard::Mode mode)
755+{
756+ switch (mode) {
757+ case QClipboard::Clipboard:
758+ match(kapp->clipboard()->text(mode));
759+ break;
760+ case QClipboard::Selection:
761+ define(kapp->clipboard()->text(mode));
762+ break;
763+ case QClipboard::FindBuffer:
764+// find(kapp->clipboard()->text(mode));
765+ break;
766+ }
767+}
768+
769+void DictWindow::authenticate()
770+{
771+ KPasswordDialog auth(this, KPasswordDialog::ShowUsernameLine | KPasswordDialog::ShowKeepPassword);
772+ auth.setCaption(i18n("Dict Authentication"));
773+ auth.setPrompt(i18n("Enter your authentication for host %1", dict->host()));
774+ auth.setUsername(dict->user());
775+ if (auth.exec()) {
776+ dict->auth(auth.username(), auth.password());
777+ query.clear();
778+ }
779+ KConfigGroup hostConf(config, dict->host());
780+ if (auth.keepPassword()) {
781+ hostConf.writeEntry("Username", auth.username());
782+ hostConf.writeEntry("Password", auth.password());
783+ } else {
784+ hostConf.deleteEntry("Username");
785+ hostConf.deleteEntry("Password");
786+ }
787+}
788+
789+void DictWindow::toggleMenubar()
790+{
791+ menuBar()->setVisible(!menuBar()->isVisible());
792+}
793+
794+void DictWindow::setSidebar(QWidget *widget)
795+{
796+ if (sidebar->isVisible())
797+ writeWidthsConfig();
798+ else
799+ widget->setFocus();
800+ sidebar->setVisible(!widget->isVisible());
801+ sidebar->setCurrentWidget(widget);
802+ if (!sidebar->isVisible())
803+ browser->setFocus();
804+}
805+
806+void DictWindow::setSidebar(int side)
807+{
808+ splitter->insertWidget(side, sidebar);
809+}
810+
811+void DictWindow::toggleDatabaseList()
812+{
813+ setSidebar(databaseList);
814+}
815+
816+void DictWindow::toggleMatchList()
817+{
818+ setSidebar(matchList);
819+}
820+
821+void DictWindow::enableMatchList(bool enable)
822+{
823+ actionCollection()->action("matches")->setEnabled(enable);
824+ if (!enable) {
825+ actionCollection()->action("prev")->setEnabled(enable);
826+ actionCollection()->action("next")->setEnabled(enable);
827+ if (matchList->isVisible())
828+ sidebar->hide();
829+ matchList->clearHistory();
830+ }
831+}
832+
833+void DictWindow::nextFrame()
834+{
835+ if (browser->hasFocus())
836+ if (sidebar->isVisible())
837+ sidebar->currentWidget()->setFocus();
838+ else if (search->isVisible())
839+ search->setFocus();
840+ else
841+ entry->setFocus();
842+ else
843+ browser->setFocus();
844+}
845+
846+void DictWindow::configure()
847+{
848+ if (!settings) {
849+ settings = new DictSettings(this);
850+ connect(settings, SIGNAL(accepted()), SLOT(loadSettings()));
851+ }
852+ settings->setHosts(hostMenu->items());
853+ settings->setFont(font());
854+ settings->readConf(conf);
855+ settings->show();
856+}
857+
858+void DictWindow::loadSettings()
859+{
860+ QStringList hosts = settings->hosts();
861+ if (hosts.isEmpty())
862+ hosts << Dict::DefaultHost;
863+ QString host = hostMenu->currentText();
864+ int index = hosts.indexOf(host);
865+ hostMenu->setItems(hosts);
866+ if (index < 0)
867+ index = 0;
868+ hostMenu->setCurrentItem(index);
869+ host = hostMenu->currentText();
870+ if (host != dict->host())
871+ setHost(host);
872+
873+ setFont(settings->font());
874+ settings->writeConf(conf);
875+
876+ setSidebar(conf.sidebar);
877+ enableMatchList(conf.matchFrame);
878+}
diff -r 000000000000 -r eabf6fad361c dictwindow.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dictwindow.h Mon Jan 05 00:54:54 2009 +0000
@@ -0,0 +1,125 @@
1+#ifndef MAINWINDOW_H
2+#define MAINWINDOW_H
3+
4+#include "dict.h"
5+#include "dictpage.h"
6+#include "dictsettings.h"
7+#include "dictwidgets.h"
8+
9+#include <KXmlGuiWindow>
10+#include <QClipboard>
11+
12+class QSplitter;
13+class QStackedWidget;
14+class QComboBox;
15+class QLabel;
16+class KSelectAction;
17+class DictBrowser;
18+
19+class DictWindow : public KXmlGuiWindow
20+{
21+ Q_OBJECT
22+
23+public:
24+ DictWindow(QWidget *parent = 0);
25+ ~DictWindow();
26+
27+public Q_SLOTS:
28+ void define(const QString &query);
29+ void match(const QString &query);
30+ void define();
31+ void match();
32+ void define(const QUrl &link);
33+ void setDatabaseMenu(const DictList &list);
34+ void setStrategyMenu(const DictList &list);
35+ void setHost(const QString &);
36+
37+ void configure();
38+ void authenticate();
39+ void about(const QString &query);
40+ void info(QAction *action);
41+ void response(const QString &text);
42+ void response(const DictResponse &response);
43+ void error(const QString &text);
44+ void cancel();
45+
46+ void newWindow() { new DictWindow(); };
47+ void save() {};
48+ void print() {};
49+
50+Q_SIGNALS:
51+ void loading(bool);
52+
53+private:
54+ static const int maxQueryLen = 120;
55+ QComboBox *entry;
56+ DictBrowser *browser, *matchList;
57+ DictHistory *backwardMenu, *forwardMenu;
58+ QMenu *infoMenu;
59+ KSelectAction *hostMenu;
60+ DictSelect *strategyMenu;
61+ DictMenu *databaseMenu;
62+ DictView *databaseList;
63+ Dict *dict;
64+
65+ KSharedConfigPtr config;
66+ DictSettings *settings;
67+ QString query;
68+ DictSearch *search;
69+ QSplitter *splitter;
70+ QStackedWidget *sidebar;
71+ KAction *stop;
72+ DictStatus *hostStatus, *userStatus;
73+ DictConf conf;
74+ DictPage page;
75+
76+ struct DictTracker {
77+ bool init, match, correct, extra;
78+ int hits, misses;
79+ void clear() { hits = misses = 0;
80+ match = correct = extra = false; };
81+ int count() { return hits + misses; };
82+ } tracker;
83+
84+ void setupActions();
85+ void setupBrowser();
86+ void setupDict();
87+ void setupStatusbar();
88+ void url(const QString &query);
89+
90+ void initDatabases();
91+ int dbcount() { return databases().size(); };
92+ QStringList database() { return databaseMenu->currentData(); };
93+ QString strategy() { return strategyMenu->currentData(); };
94+ QStringList databases() { return (!database().isEmpty()) ? database() : QStringList(Dict::DefaultDatabase); };
95+ QString strategies() { return (!strategy().isEmpty() && !tracker.correct) ? strategy() : Dict::DefaultStrategy; };
96+
97+private Q_SLOTS:
98+ void readConfig();
99+ void writeConfig();
100+ QStringList databaseConfig();
101+ QString strategyConfig();
102+ void hostConfig(const QString &host);
103+ void writeHostConfig();
104+ void readServerConfig();
105+ void writeServerConfig();
106+ void readWidthsConfig();
107+ void writeWidthsConfig();
108+
109+ void loadSettings();
110+ void setHostStatus(bool connected);
111+ void setUserStatus(bool authenticated);
112+
113+ void statusMessage(const QString &message);
114+ void toggleMenubar();
115+ void setSidebar(int side);
116+ void setSidebar(QWidget *widget);
117+ void toggleDatabaseList();
118+ void toggleMatchList();
119+ void enableMatchList(bool enable);
120+ void nextFrame();
121+ void yankMode(bool toggle);
122+ void yankClipboard(QClipboard::Mode);
123+};
124+
125+#endif
diff -r 000000000000 -r eabf6fad361c dikt.desktop
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dikt.desktop Mon Jan 05 00:54:54 2009 +0000
@@ -0,0 +1,9 @@
1+[Desktop Entry]
2+Type=Application
3+Exec=dikt
4+Icon=accessories-dictionary
5+#X-DocPath=dikt/index.html
6+
7+Name=Dikt
8+GenericName=Dictionary
9+Categories=Qt;KDE;Network;
diff -r 000000000000 -r eabf6fad361c diktui.rc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/diktui.rc Mon Jan 05 00:54:54 2009 +0000
@@ -0,0 +1,59 @@
1+<?xml version='1.0' encoding='UTF-8'?>
2+<!DOCTYPE kpartgui SYSTEM 'kpartgui.dtd'>
3+<gui version="1" name="dikt" >
4+ <ToolBar iconText="icononly" fullWidth="true" noMerge="1" name="mainToolBar" >
5+ <text>Main Toolbar</text>
6+ <Action name="backward" />
7+ <Action name="forward" />
8+ <Action name="search" />
9+ <Action name="query" />
10+ <Action name="stop" />
11+ </ToolBar>
12+ <MenuBar>
13+ <Menu name="file" >
14+ <text>File</text>
15+ <Action name="auth" />
16+ </Menu>
17+ <Menu name="edit" >
18+ <text>Edit</text>
19+ <Action name="define" />
20+ <Action name="match" />
21+ <Separator/>
22+ <Action name="edit_find" />
23+ <Action name="edit_find_next" />
24+ <Action name="edit_find_prev" />
25+ </Menu>
26+ <Menu name="view" >
27+ <text>View</text>
28+ <Action name="frame" />
29+ <Action name="sidebar" />
30+ <Action name="matches" />
31+ </Menu>
32+ <Menu name="hist" >
33+ <text>History</text>
34+ <Action name="backward" />
35+ <Action name="forward" />
36+ <Action name="clear" />
37+ <Action name="prev" />
38+ <Action name="next" />
39+ </Menu>
40+ <Menu name="server" >
41+ <text>Dictionary</text>
42+ <Action name="host" />
43+ <Action name="database" />
44+ <Action name="strategy" />
45+ <Action name="info" />
46+ </Menu>
47+ <Menu name="settings" >
48+ <text>Settings</text>
49+ <Action name="yank" />
50+ <Action name="options_show_menubar" />
51+ </Menu>
52+ </MenuBar>
53+ <ActionProperties>
54+ <Action shortcut="F6" name="frame" />
55+ <Action shortcut="F9" name="sidebar" />
56+ <Action shortcut="F12" name="matches" />
57+ <Action shortcut="F10" name="options_show_menubar" />
58+ </ActionProperties>
59+</gui>
diff -r 000000000000 -r eabf6fad361c main.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp Mon Jan 05 00:54:54 2009 +0000
@@ -0,0 +1,20 @@
1+#include "dictwindow.h"
2+
3+#include <KApplication>
4+#include <KAboutData>
5+#include <KCmdLineArgs>
6+
7+int main(int argc, char *argv[])
8+{
9+ KAboutData aboutData("dikt", 0,
10+ ki18n("DiKt"), "1",
11+ ki18n("Dictionary for Kde"),
12+ KAboutData::License_BSD,
13+ ki18n("Copyright 2008 by Goran Tal"));
14+ aboutData.setProgramIconName("accessories-dictionary");
15+ KCmdLineArgs::init(argc, argv, &aboutData);
16+ KApplication app;
17+
18+ new DictWindow();
19+ return app.exec();
20+}
diff -r 000000000000 -r eabf6fad361c searchbar.ui
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/searchbar.ui Mon Jan 05 00:54:54 2009 +0000
@@ -0,0 +1,80 @@
1+<ui version="4.0" >
2+ <class>Searchbar</class>
3+ <widget class="QWidget" name="Searchbar" >
4+ <property name="geometry" >
5+ <rect>
6+ <x>0</x>
7+ <y>0</y>
8+ <width>360</width>
9+ <height>40</height>
10+ </rect>
11+ </property>
12+ <property name="sizePolicy" >
13+ <sizepolicy vsizetype="Fixed" hsizetype="Minimum" >
14+ <horstretch>0</horstretch>
15+ <verstretch>0</verstretch>
16+ </sizepolicy>
17+ </property>
18+ <property name="windowTitle" >
19+ <string>Searchbar</string>
20+ </property>
21+ <layout class="QHBoxLayout" name="horizontalLayout" >
22+ <item>
23+ <widget class="QToolButton" name="toolbutton" >
24+ <property name="focusPolicy" >
25+ <enum>Qt::NoFocus</enum>
26+ </property>
27+ <property name="text" >
28+ <string>...</string>
29+ </property>
30+ <property name="autoRaise" >
31+ <bool>true</bool>
32+ </property>
33+ </widget>
34+ </item>
35+ <item>
36+ <widget class="QLabel" name="label" >
37+ <property name="text" >
38+ <string>Find:</string>
39+ </property>
40+ </widget>
41+ </item>
42+ <item>
43+ <widget class="QLineEdit" name="pattern" >
44+ <property name="sizePolicy" >
45+ <sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
46+ <horstretch>0</horstretch>
47+ <verstretch>0</verstretch>
48+ </sizepolicy>
49+ </property>
50+ </widget>
51+ </item>
52+ <item>
53+ <widget class="QLabel" name="message" >
54+ <property name="text" >
55+ <string/>
56+ </property>
57+ </widget>
58+ </item>
59+ </layout>
60+ </widget>
61+ <resources/>
62+ <connections>
63+ <connection>
64+ <sender>toolbutton</sender>
65+ <signal>clicked()</signal>
66+ <receiver>Searchbar</receiver>
67+ <slot>hide()</slot>
68+ <hints>
69+ <hint type="sourcelabel" >
70+ <x>23</x>
71+ <y>33</y>
72+ </hint>
73+ <hint type="destinationlabel" >
74+ <x>34</x>
75+ <y>39</y>
76+ </hint>
77+ </hints>
78+ </connection>
79+ </connections>
80+</ui>
diff -r 000000000000 -r eabf6fad361c settings.ui
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/settings.ui Mon Jan 05 00:54:54 2009 +0000
@@ -0,0 +1,190 @@
1+<ui version="4.0" >
2+ <class>Settings</class>
3+ <widget class="KDialog" name="Settings" >
4+ <property name="geometry" >
5+ <rect>
6+ <x>0</x>
7+ <y>0</y>
8+ <width>450</width>
9+ <height>340</height>
10+ </rect>
11+ </property>
12+ <property name="windowTitle" >
13+ <string>Settings</string>
14+ </property>
15+ <widget class="KTabWidget" name="tab" >
16+ <property name="geometry" >
17+ <rect>
18+ <x>0</x>
19+ <y>0</y>
20+ <width>435</width>
21+ <height>300</height>
22+ </rect>
23+ </property>
24+ <property name="currentIndex" >
25+ <number>0</number>
26+ </property>
27+ <widget class="QWidget" name="tab_1" >
28+ <attribute name="title" >
29+ <string>Hosts</string>
30+ </attribute>
31+ <layout class="QVBoxLayout" name="verticalLayout" >
32+ <item>
33+ <widget class="KEditListBox" name="listbox" />
34+ </item>
35+ </layout>
36+ </widget>
37+ <widget class="QWidget" name="tab_2" >
38+ <attribute name="title" >
39+ <string>Browser</string>
40+ </attribute>
41+ <widget class="QWidget" name="layoutWidget" >
42+ <property name="geometry" >
43+ <rect>
44+ <x>10</x>
45+ <y>10</y>
46+ <width>401</width>
47+ <height>30</height>
48+ </rect>
49+ </property>
50+ <layout class="QHBoxLayout" name="horizontalLayout" >
51+ <item>
52+ <widget class="QLabel" name="fontlabel" >
53+ <property name="text" >
54+ <string>Font:</string>
55+ </property>
56+ </widget>
57+ </item>
58+ <item>
59+ <widget class="KFontRequester" name="fontrequester" />
60+ </item>
61+ </layout>
62+ </widget>
63+ <widget class="QWidget" name="layoutWidget" >
64+ <property name="geometry" >
65+ <rect>
66+ <x>10</x>
67+ <y>70</y>
68+ <width>401</width>
69+ <height>81</height>
70+ </rect>
71+ </property>
72+ <layout class="QVBoxLayout" name="verticalLayout_2" >
73+ <item>
74+ <widget class="QCheckBox" name="corrections" >
75+ <property name="text" >
76+ <string>Retrieve suggestions when definitons are not found</string>
77+ </property>
78+ </widget>
79+ </item>
80+ <item>
81+ <widget class="QCheckBox" name="headings" >
82+ <property name="text" >
83+ <string>Show headings with database names</string>
84+ </property>
85+ </widget>
86+ </item>
87+ <item>
88+ <widget class="QCheckBox" name="matchFrame" >
89+ <property name="text" >
90+ <string>Display matches in sidebar</string>
91+ </property>
92+ </widget>
93+ </item>
94+ </layout>
95+ </widget>
96+ <widget class="Line" name="line" >
97+ <property name="geometry" >
98+ <rect>
99+ <x>10</x>
100+ <y>155</y>
101+ <width>401</width>
102+ <height>20</height>
103+ </rect>
104+ </property>
105+ <property name="orientation" >
106+ <enum>Qt::Horizontal</enum>
107+ </property>
108+ </widget>
109+ <widget class="Line" name="line_2" >
110+ <property name="geometry" >
111+ <rect>
112+ <x>10</x>
113+ <y>46</y>
114+ <width>401</width>
115+ <height>20</height>
116+ </rect>
117+ </property>
118+ <property name="orientation" >
119+ <enum>Qt::Horizontal</enum>
120+ </property>
121+ </widget>
122+ <widget class="QWidget" name="layoutWidget" >
123+ <property name="geometry" >
124+ <rect>
125+ <x>10</x>
126+ <y>180</y>
127+ <width>167</width>
128+ <height>29</height>
129+ </rect>
130+ </property>
131+ <layout class="QHBoxLayout" name="horizontalLayout_2" >
132+ <item>
133+ <widget class="QLabel" name="label" >
134+ <property name="text" >
135+ <string>Sidebar:</string>
136+ </property>
137+ </widget>
138+ </item>
139+ <item>
140+ <widget class="QComboBox" name="sidebar" >
141+ <property name="sizePolicy" >
142+ <sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
143+ <horstretch>0</horstretch>
144+ <verstretch>0</verstretch>
145+ </sizepolicy>
146+ </property>
147+ <item>
148+ <property name="text" >
149+ <string>on left side</string>
150+ </property>
151+ </item>
152+ <item>
153+ <property name="text" >
154+ <string>on right side</string>
155+ </property>
156+ </item>
157+ </widget>
158+ </item>
159+ </layout>
160+ </widget>
161+ </widget>
162+ </widget>
163+ </widget>
164+ <customwidgets>
165+ <customwidget>
166+ <class>KDialog</class>
167+ <extends>QDialog</extends>
168+ <header>kdialog.h</header>
169+ <container>1</container>
170+ </customwidget>
171+ <customwidget>
172+ <class>KEditListBox</class>
173+ <extends>QGroupBox</extends>
174+ <header>keditlistbox.h</header>
175+ </customwidget>
176+ <customwidget>
177+ <class>KFontRequester</class>
178+ <extends>QWidget</extends>
179+ <header>kfontrequester.h</header>
180+ </customwidget>
181+ <customwidget>
182+ <class>KTabWidget</class>
183+ <extends>QTabWidget</extends>
184+ <header>ktabwidget.h</header>
185+ <container>1</container>
186+ </customwidget>
187+ </customwidgets>
188+ <resources/>
189+ <connections/>
190+</ui>
Show on old repository browser