kexi

kexiquerydesignersqlhistory.cpp

00001 /* This file is part of the KDE project
00002    Copyright (C) 2003 Lucijan Busch <lucijan@kde.org>
00003    Copyright (C) 2004 Jaroslaw Staniek <js@iidea.pl>
00004 
00005    This program is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this program; see the file COPYING.  If not, write to
00017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018  * Boston, MA 02110-1301, USA.
00019 */
00020 
00021 #include <qpainter.h>
00022 #include <qclipboard.h>
00023 #include <qregexp.h>
00024 
00025 #include <kpopupmenu.h>
00026 #include <klocale.h>
00027 #include <kiconloader.h>
00028 #include <kdebug.h>
00029 #include <kglobalsettings.h>
00030 #include <kapplication.h>
00031 
00032 #include "kexiquerydesignersqlhistory.h"
00033 
00034 KexiQueryDesignerSQLHistory::KexiQueryDesignerSQLHistory(QWidget *parent, const char *name)
00035  : QScrollView(parent, name)
00036 {
00037     viewport()->setPaletteBackgroundColor(white);
00038 
00039     m_selected = 0;
00040     m_history = new History();
00041     m_history->setAutoDelete(true);
00042 
00043     m_popup = new KPopupMenu(this);
00044     m_popup->insertItem(SmallIcon("editcopy"), i18n("Copy to Clipboard"), this, SLOT(slotToClipboard()));
00045 }
00046 
00047 KexiQueryDesignerSQLHistory::~KexiQueryDesignerSQLHistory()
00048 {
00049 }
00050 
00051 void
00052 KexiQueryDesignerSQLHistory::drawContents(QPainter *p, int cx, int cy, int cw, int ch)
00053 {
00054     QRect clipping(cx, cy, cw, ch);
00055 
00056     int y = 0;
00057     for(HistoryEntry *it = m_history->first(); it; it = m_history->next())
00058     {
00059 //      it->drawItem(p, visibleWidth());
00060         if(clipping.intersects(it->geometry(y, visibleWidth(), fontMetrics())))
00061         {
00062             p->saveWorldMatrix();
00063             p->translate(0, y);
00064             it->drawItem(p, visibleWidth(), colorGroup());
00065             p->restoreWorldMatrix();
00066         }
00067         y += it->geometry(y, visibleWidth(), fontMetrics()).height() + 5;
00068     }
00069 }
00070 
00071 void
00072 KexiQueryDesignerSQLHistory::contentsMousePressEvent(QMouseEvent * e)
00073 {
00074     int y = 0;
00075     HistoryEntry *popupHistory = 0;
00076     int pos;
00077     for(QPtrListIterator<HistoryEntry> it(*m_history); it.current(); ++it)
00078     {
00079         if(it.current()->isSelected())
00080         {
00081             //clear
00082             it.current()->setSelected(false, colorGroup());
00083             updateContents(it.current()->geometry(y, visibleWidth(), fontMetrics()));
00084         }
00085 
00086         if(it.current()->geometry(y, visibleWidth(), fontMetrics()).contains(e->pos()))
00087         {
00088             popupHistory = it.current();
00089             pos = y;
00090         }
00091         y += it.current()->geometry(y, visibleWidth(), fontMetrics()).height() + 5;
00092     }
00093 
00094     //now do update
00095     if (popupHistory) {
00096             if (m_selected && m_selected != popupHistory) {
00097                 m_selected->setSelected(false, colorGroup());
00098                 updateContents(m_selected->geometry(pos, visibleWidth(), fontMetrics()));
00099             }
00100             m_selected = popupHistory;
00101             m_selected->setSelected(true, colorGroup());
00102             updateContents(m_selected->geometry(pos, visibleWidth(), fontMetrics()));
00103             if(e->button() == RightButton) {
00104                 m_popup->exec(e->globalPos());
00105             }
00106     }
00107 }
00108 
00109 void
00110 KexiQueryDesignerSQLHistory::contentsMouseDoubleClickEvent(QMouseEvent * e)
00111 {
00112     contentsMousePressEvent(e);
00113     if (m_selected)
00114         emit currentItemDoubleClicked();
00115 }
00116 
00117 void
00118 KexiQueryDesignerSQLHistory::addEvent(const QString& q, bool s, const QString &error)
00119 {
00120     HistoryEntry *he=m_history->last();
00121     if (he) {
00122         if (he->statement()==q) {
00123             he->updateTime(QTime::currentTime());
00124             repaint();
00125             return;
00126         }
00127     }
00128     addEntry(new HistoryEntry(s, QTime::currentTime(), q, error));
00129 }
00130 
00131 void
00132 KexiQueryDesignerSQLHistory::addEntry(HistoryEntry *e)
00133 {
00134     m_history->append(e);
00135 //  m_history->prepend(e);
00136 
00137     int y = 0;
00138     for(HistoryEntry *it = m_history->first(); it; it = m_history->next())
00139     {
00140         y += it->geometry(y, visibleWidth(), fontMetrics()).height() + 5;
00141     }
00142 
00143     resizeContents(visibleWidth() - 1, y);
00144     if (m_selected) {
00145         m_selected->setSelected(false, colorGroup());
00146     }
00147     m_selected = e;
00148     m_selected->setSelected(true, colorGroup());
00149     ensureVisible(0,y+5);
00150     updateContents();
00151 /*  ensureVisible(0, 0);
00152     if (m_selected) {
00153         m_selected->setSelected(false, colorGroup());
00154     }
00155     m_selected = e;
00156     m_selected->setSelected(true, colorGroup());
00157 //  updateContents();
00158     updateContents(m_selected->geometry(0, visibleWidth(), fontMetrics()));*/
00159 }
00160 
00161 /*void
00162 KexiQueryDesignerSQLHistory::contextMenu(const QPoint &pos, HistoryEntry *)
00163 {
00164     KPopupMenu p(this);
00165     p.insertItem(SmallIcon("editcopy"), i18n("Copy to Clipboard"), this, SLOT(slotToClipboard()));
00166     
00167 
00168 #ifndef KEXI_NO_UNFINISHED
00169     p.insertSeparator();
00170     p.insertItem(SmallIcon("edit"), i18n("Edit"), this, SLOT(slotEdit()));
00171     p.insertItem(SmallIcon("reload"), i18n("Requery"));
00172 #endif
00173 
00174     p.exec(pos);
00175 }*/
00176 
00177 void
00178 KexiQueryDesignerSQLHistory::slotToClipboard()
00179 {
00180     if(!m_selected)
00181         return;
00182 
00183     QApplication::clipboard()->setText(m_selected->statement(), QClipboard::Clipboard);
00184 }
00185 
00186 void
00187 KexiQueryDesignerSQLHistory::slotEdit()
00188 {
00189     emit editRequested(m_selected->statement());
00190 }
00191 
00192 QString
00193 KexiQueryDesignerSQLHistory::selectedStatement() const
00194 {
00195     return m_selected ? m_selected->statement() : QString::null;
00196 }
00197 
00198 void
00199 KexiQueryDesignerSQLHistory::setHistory(History *h)
00200 {
00201     m_history = h;
00202     update();
00203 }
00204 
00205 void KexiQueryDesignerSQLHistory::clear()
00206 {
00207     m_selected = 0;
00208     m_history->clear();
00209     updateContents();
00210 }
00211 
00212 KPopupMenu* KexiQueryDesignerSQLHistory::popupMenu() const
00213 {
00214     return m_popup;
00215 }
00216 
00217 //==================================
00218 
00219 HistoryEntry::HistoryEntry(bool succeed, const QTime &execTime, const QString &statement, /*int ,*/ const QString &err)
00220 {
00221     m_succeed = succeed;
00222     m_execTime = execTime;
00223     m_statement = statement;
00224     m_error = err;
00225     m_selected = false;
00226     highlight(QColorGroup());
00227 }
00228 
00229 void
00230 HistoryEntry::drawItem(QPainter *p, int width, const QColorGroup &cg)
00231 {
00232     p->setPen(QColor(200, 200, 200));
00233     p->setBrush(QColor(200, 200, 200));
00234     p->drawRect(2, 2, 200, 20);
00235     p->setPen(QColor(0, 0, 0));
00236 
00237     if(m_succeed)
00238         p->drawPixmap(4, 4, SmallIcon("button_ok"));
00239     else
00240         p->drawPixmap(4, 4, SmallIcon("button_cancel"));
00241 
00242     p->drawText(22, 2, 180, 20, Qt::AlignLeft | Qt::AlignVCenter, m_execTime.toString());
00243     p->setPen(QColor(200, 200, 200));
00244     p->setBrush(QColor(255, 255, 255));
00245     m_formated->setWidth(width - 2);
00246     QRect content(2, 21, width - 2, m_formated->height());
00247 //  QRect content = p->fontMetrics().boundingRect(2, 21, width - 2, 0, Qt::WordBreak | Qt::AlignLeft | Qt::AlignVCenter, m_statement);
00248 //  QRect content(2, 21, width - 2, p->fontMetrics().height() + 4);
00249 //  content = QRect(2, 21, width - 2, m_for.height());
00250 
00251     if(m_selected)
00252         p->setBrush(cg.highlight());
00253 
00254     p->drawRect(content);
00255 
00256     if(!m_selected)
00257         p->setPen(cg.text());
00258     else
00259         p->setPen(cg.highlightedText());
00260 
00261     content.setX(content.x() + 2);
00262     content.setWidth(content.width() - 2);
00263 //  p->drawText(content, Qt::WordBreak | Qt::AlignLeft | Qt::AlignVCenter, m_statement);
00264     m_formated->draw(p, content.x(), content.y(), content, cg);
00265 }
00266 
00267 void
00268 HistoryEntry::highlight(const QColorGroup &cg)
00269 {
00270     QString statement;
00271     QString text;
00272     bool quote = false;
00273     bool dblquote = false;
00274 
00275     statement = m_statement;
00276     statement.replace("<", "&lt;");
00277     statement.replace(">", "&gt;");
00278     statement.replace("\r\n", "<br>"); //(js) first win32 specific pair
00279     statement.replace("\n", "<br>"); // now single \n
00280     statement.replace(" ", "&nbsp;");
00281     statement.replace("\t", "&nbsp;&nbsp;&nbsp;");
00282 
00283     // getting quoting...
00284     if(!m_selected)
00285     {
00286         for(int i=0; i < (int)statement.length(); i++)
00287         {
00288             QString beginTag;
00289             QString endTag;
00290             QChar curr = QChar(statement[i]);
00291 
00292             if(curr == "'" && !dblquote && QChar(statement[i-1]) != "\\")
00293             {
00294                 if(!quote)
00295                 {
00296                     quote = true;
00297                     beginTag += "<font color=\"#ff0000\">";
00298                 }
00299                 else
00300                 {
00301                     quote = false;
00302                     endTag += "</font>";
00303                 }
00304             }
00305             if(curr == "\"" && !quote && QChar(statement[i-1]) != "\\")
00306             {
00307                 if(!dblquote)
00308                 {
00309                     dblquote = true;
00310                     beginTag += "<font color=\"#ff0000\">";
00311                 }
00312                 else
00313                 {
00314                     dblquote = false;
00315                     endTag += "</font>";
00316                 }
00317             }
00318             if(QRegExp("[0-9]").exactMatch(QString(curr)) && !quote && !dblquote)
00319             {
00320                 beginTag += "<font color=\"#0000ff\">";
00321                 endTag += "</font>";
00322             }
00323 
00324             text += beginTag + curr + endTag;
00325         }
00326     }
00327     else
00328     {
00329         text = QString("<font color=\"%1\">%2").arg(cg.highlightedText().name()).arg(statement);
00330     }
00331 
00332     QRegExp keywords("\\b(SELECT|UPDATE|INSERT|DELETE|DROP|FROM|WHERE|AND|OR|NOT|NULL|JOIN|LEFT|RIGHT|ON|INTO|TABLE)\\b");
00333     keywords.setCaseSensitive(false);
00334     text = text.replace(keywords, "<b>\\1</b>");
00335 
00336     if(!m_error.isEmpty())
00337 //      text += ("<br>"+i18n("Error: %1").arg(m_error));
00338 //      text += QString("<br><font face=\"") + KGlobalSettings::generalFont().family() + QString("\" size=\"-1\">") + i18n("Error: %1").arg(m_error) + "</font>";
00339         text += QString("<br><font face=\"") + KGlobalSettings::generalFont().family() + QString("\">") + i18n("Error: %1").arg(m_error) + "</font>";
00340 
00341     kdDebug() << "HistoryEntry::highlight() text:" << text << endl;
00342 //  m_formated = new QSimpleRichText(text, QFont("courier", 8));
00343     m_formated = new QSimpleRichText(text, KGlobalSettings::fixedFont());
00344 
00345 }
00346 
00347 void
00348 HistoryEntry::setSelected(bool selected, const QColorGroup &cg)
00349 {
00350     m_selected = selected;
00351     highlight(cg);
00352 }
00353 
00354 QRect
00355 HistoryEntry::geometry(int y, int width, QFontMetrics f)
00356 {
00357     Q_UNUSED( f );
00358 
00359 //  int h = 21 + f.boundingRect(2, 21, width - 2, 0, Qt::WordBreak | Qt::AlignLeft | Qt::AlignVCenter, m_statement).height();
00360 //  return QRect(0, y, width, h);
00361     m_formated->setWidth(width - 2);
00362     return QRect(0, y, width, m_formated->height() + 21);
00363 }
00364 
00365 void HistoryEntry::updateTime(const QTime &execTime) {
00366     m_execTime=execTime;
00367 }
00368 
00369 HistoryEntry::~HistoryEntry()
00370 {
00371 }
00372 
00373 #include "kexiquerydesignersqlhistory.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys