kexiquerydesignersqlhistory.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2003 Lucijan Busch <lucijan@kde.org>
3 Copyright (C) 2004 Jaroslaw Staniek <js@iidea.pl>
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this program; see the file COPYING. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19*/
20
21#include <tqpainter.h>
22#include <tqclipboard.h>
23#include <tqregexp.h>
24
25#include <tdepopupmenu.h>
26#include <tdelocale.h>
27#include <kiconloader.h>
28#include <kdebug.h>
29#include <tdeglobalsettings.h>
30#include <tdeapplication.h>
31
32#include "kexiquerydesignersqlhistory.h"
33
34KexiQueryDesignerSQLHistory::KexiQueryDesignerSQLHistory(TQWidget *parent, const char *name)
35 : TQScrollView(parent, name)
36{
37 viewport()->setPaletteBackgroundColor(white);
38
39 m_selected = 0;
40 m_history = new History();
41 m_history->setAutoDelete(true);
42
43 m_popup = new TDEPopupMenu(this);
44 m_popup->insertItem(SmallIcon("edit-copy"), i18n("Copy to Clipboard"), this, TQ_SLOT(slotToClipboard()));
45}
46
47KexiQueryDesignerSQLHistory::~KexiQueryDesignerSQLHistory()
48{
49}
50
51void
52KexiQueryDesignerSQLHistory::drawContents(TQPainter *p, int cx, int cy, int cw, int ch)
53{
54 TQRect clipping(cx, cy, cw, ch);
55
56 int y = 0;
57 for(HistoryEntry *it = m_history->first(); it; it = m_history->next())
58 {
59// it->drawItem(p, visibleWidth());
60 if(clipping.intersects(it->geometry(y, visibleWidth(), fontMetrics())))
61 {
62 p->saveWorldMatrix();
63 p->translate(0, y);
64 it->drawItem(p, visibleWidth(), colorGroup());
65 p->restoreWorldMatrix();
66 }
67 y += it->geometry(y, visibleWidth(), fontMetrics()).height() + 5;
68 }
69}
70
71void
72KexiQueryDesignerSQLHistory::contentsMousePressEvent(TQMouseEvent * e)
73{
74 int y = 0;
75 HistoryEntry *popupHistory = 0;
76 int pos;
77 for(TQPtrListIterator<HistoryEntry> it(*m_history); it.current(); ++it)
78 {
79 if(it.current()->isSelected())
80 {
81 //clear
82 it.current()->setSelected(false, colorGroup());
83 updateContents(it.current()->geometry(y, visibleWidth(), fontMetrics()));
84 }
85
86 if(it.current()->geometry(y, visibleWidth(), fontMetrics()).contains(e->pos()))
87 {
88 popupHistory = it.current();
89 pos = y;
90 }
91 y += it.current()->geometry(y, visibleWidth(), fontMetrics()).height() + 5;
92 }
93
94 //now do update
95 if (popupHistory) {
96 if (m_selected && m_selected != popupHistory) {
97 m_selected->setSelected(false, colorGroup());
98 updateContents(m_selected->geometry(pos, visibleWidth(), fontMetrics()));
99 }
100 m_selected = popupHistory;
101 m_selected->setSelected(true, colorGroup());
102 updateContents(m_selected->geometry(pos, visibleWidth(), fontMetrics()));
103 if(e->button() == TQt::RightButton) {
104 m_popup->exec(e->globalPos());
105 }
106 }
107}
108
109void
110KexiQueryDesignerSQLHistory::contentsMouseDoubleClickEvent(TQMouseEvent * e)
111{
112 contentsMousePressEvent(e);
113 if (m_selected)
114 emit currentItemDoubleClicked();
115}
116
117void
118KexiQueryDesignerSQLHistory::addEvent(const TQString& q, bool s, const TQString &error)
119{
120 HistoryEntry *he=m_history->last();
121 if (he) {
122 if (he->statement()==q) {
123 he->updateTime(TQTime::currentTime());
124 repaint();
125 return;
126 }
127 }
128 addEntry(new HistoryEntry(s, TQTime::currentTime(), q, error));
129}
130
131void
132KexiQueryDesignerSQLHistory::addEntry(HistoryEntry *e)
133{
134 m_history->append(e);
135// m_history->prepend(e);
136
137 int y = 0;
138 for(HistoryEntry *it = m_history->first(); it; it = m_history->next())
139 {
140 y += it->geometry(y, visibleWidth(), fontMetrics()).height() + 5;
141 }
142
143 resizeContents(visibleWidth() - 1, y);
144 if (m_selected) {
145 m_selected->setSelected(false, colorGroup());
146 }
147 m_selected = e;
148 m_selected->setSelected(true, colorGroup());
149 ensureVisible(0,y+5);
150 updateContents();
151/* ensureVisible(0, 0);
152 if (m_selected) {
153 m_selected->setSelected(false, colorGroup());
154 }
155 m_selected = e;
156 m_selected->setSelected(true, colorGroup());
157// updateContents();
158 updateContents(m_selected->geometry(0, visibleWidth(), fontMetrics()));*/
159}
160
161/*void
162KexiQueryDesignerSQLHistory::contextMenu(const TQPoint &pos, HistoryEntry *)
163{
164 TDEPopupMenu p(this);
165 p.insertItem(SmallIcon("edit-copy"), i18n("Copy to Clipboard"), this, TQ_SLOT(slotToClipboard()));
166
167
168#ifndef KEXI_NO_UNFINISHED
169 p.insertSeparator();
170 p.insertItem(SmallIcon("edit"), i18n("Edit"), this, TQ_SLOT(slotEdit()));
171 p.insertItem(SmallIcon("reload"), i18n("Requery"));
172#endif
173
174 p.exec(pos);
175}*/
176
177void
178KexiQueryDesignerSQLHistory::slotToClipboard()
179{
180 if(!m_selected)
181 return;
182
183 TQApplication::clipboard()->setText(m_selected->statement(), TQClipboard::Clipboard);
184}
185
186void
187KexiQueryDesignerSQLHistory::slotEdit()
188{
189 emit editRequested(m_selected->statement());
190}
191
192TQString
193KexiQueryDesignerSQLHistory::selectedStatement() const
194{
195 return m_selected ? m_selected->statement() : TQString();
196}
197
198void
199KexiQueryDesignerSQLHistory::setHistory(History *h)
200{
201 m_history = h;
202 update();
203}
204
205void KexiQueryDesignerSQLHistory::clear()
206{
207 m_selected = 0;
208 m_history->clear();
209 updateContents();
210}
211
212TDEPopupMenu* KexiQueryDesignerSQLHistory::popupMenu() const
213{
214 return m_popup;
215}
216
217//==================================
218
219HistoryEntry::HistoryEntry(bool succeed, const TQTime &execTime, const TQString &statement, /*int ,*/ const TQString &err)
220{
221 m_succeed = succeed;
222 m_execTime = execTime;
223 m_statement = statement;
224 m_error = err;
225 m_selected = false;
226 highlight(TQColorGroup());
227}
228
229void
230HistoryEntry::drawItem(TQPainter *p, int width, const TQColorGroup &cg)
231{
232 p->setPen(TQColor(200, 200, 200));
233 p->setBrush(TQColor(200, 200, 200));
234 p->drawRect(2, 2, 200, 20);
235 p->setPen(TQColor(0, 0, 0));
236
237 if(m_succeed)
238 p->drawPixmap(4, 4, SmallIcon("button_ok"));
239 else
240 p->drawPixmap(4, 4, SmallIcon("button_cancel"));
241
242 p->drawText(22, 2, 180, 20, TQt::AlignLeft | TQt::AlignVCenter, m_execTime.toString());
243 p->setPen(TQColor(200, 200, 200));
244 p->setBrush(TQColor(255, 255, 255));
245 m_formated->setWidth(width - 2);
246 TQRect content(2, 21, width - 2, m_formated->height());
247// TQRect content = p->fontMetrics().boundingRect(2, 21, width - 2, 0, TQt::WordBreak | TQt::AlignLeft | TQt::AlignVCenter, m_statement);
248// TQRect content(2, 21, width - 2, p->fontMetrics().height() + 4);
249// content = TQRect(2, 21, width - 2, m_for.height());
250
251 if(m_selected)
252 p->setBrush(cg.highlight());
253
254 p->drawRect(content);
255
256 if(!m_selected)
257 p->setPen(cg.text());
258 else
259 p->setPen(cg.highlightedText());
260
261 content.setX(content.x() + 2);
262 content.setWidth(content.width() - 2);
263// p->drawText(content, TQt::WordBreak | TQt::AlignLeft | TQt::AlignVCenter, m_statement);
264 m_formated->draw(p, content.x(), content.y(), content, cg);
265}
266
267void
268HistoryEntry::highlight(const TQColorGroup &cg)
269{
270 TQString statement;
271 TQString text;
272 bool quote = false;
273 bool dblquote = false;
274
275 statement = m_statement;
276 statement.replace("<", "&lt;");
277 statement.replace(">", "&gt;");
278 statement.replace("\r\n", "<br>"); //(js) first win32 specific pair
279 statement.replace("\n", "<br>"); // now single \n
280 statement.replace(" ", "&nbsp;");
281 statement.replace("\t", "&nbsp;&nbsp;&nbsp;");
282
283 // getting quoting...
284 if(!m_selected)
285 {
286 for(int i=0; i < (int)statement.length(); i++)
287 {
288 TQString beginTag;
289 TQString endTag;
290 TQChar curr = TQChar(statement[i]);
291
292 if(TQString(curr) == "'" && !dblquote && TQString(TQChar(statement[i-1])) != "\\")
293 {
294 if(!quote)
295 {
296 quote = true;
297 beginTag += "<font color=\"#ff0000\">";
298 }
299 else
300 {
301 quote = false;
302 endTag += "</font>";
303 }
304 }
305 if(TQString(curr) == "\"" && !quote && TQString(TQChar(statement[i-1])) != "\\")
306 {
307 if(!dblquote)
308 {
309 dblquote = true;
310 beginTag += "<font color=\"#ff0000\">";
311 }
312 else
313 {
314 dblquote = false;
315 endTag += "</font>";
316 }
317 }
318 if(TQRegExp("[0-9]").exactMatch(TQString(curr)) && !quote && !dblquote)
319 {
320 beginTag += "<font color=\"#0000ff\">";
321 endTag += "</font>";
322 }
323
324 text += beginTag + curr + endTag;
325 }
326 }
327 else
328 {
329 text = TQString("<font color=\"%1\">%2").arg(cg.highlightedText().name()).arg(statement);
330 }
331
332 TQRegExp keywords("\\b(SELECT|UPDATE|INSERT|DELETE|DROP|FROM|WHERE|AND|OR|NOT|NULL|JOIN|LEFT|RIGHT|ON|INTO|TABLE)\\b");
333 keywords.setCaseSensitive(false);
334 text = text.replace(keywords, "<b>\\1</b>");
335
336 if(!m_error.isEmpty())
337// text += ("<br>"+i18n("Error: %1").arg(m_error));
338// text += TQString("<br><font face=\"") + TDEGlobalSettings::generalFont().family() + TQString("\" size=\"-1\">") + i18n("Error: %1").arg(m_error) + "</font>";
339 text += TQString("<br><font face=\"") + TDEGlobalSettings::generalFont().family() + TQString("\">") + i18n("Error: %1").arg(m_error) + "</font>";
340
341 kdDebug() << "HistoryEntry::highlight() text:" << text << endl;
342// m_formated = new TQSimpleRichText(text, TQFont("courier", 8));
343 m_formated = new TQSimpleRichText(text, TDEGlobalSettings::fixedFont());
344
345}
346
347void
348HistoryEntry::setSelected(bool selected, const TQColorGroup &cg)
349{
350 m_selected = selected;
351 highlight(cg);
352}
353
354TQRect
355HistoryEntry::geometry(int y, int width, TQFontMetrics f)
356{
357 Q_UNUSED( f );
358
359// int h = 21 + f.boundingRect(2, 21, width - 2, 0, TQt::WordBreak | TQt::AlignLeft | TQt::AlignVCenter, m_statement).height();
360// return TQRect(0, y, width, h);
361 m_formated->setWidth(width - 2);
362 return TQRect(0, y, width, m_formated->height() + 21);
363}
364
365void HistoryEntry::updateTime(const TQTime &execTime) {
366 m_execTime=execTime;
367}
368
369HistoryEntry::~HistoryEntry()
370{
371}
372
373#include "kexiquerydesignersqlhistory.moc"