Fix crash on logout
[kdenetwork.git] / ksirc / ksview.cpp
blobed0cc6eb00fc22033184cec5bb38fdda22d1d786
1 /* This file is part of ksirc
2 Copyright (c) 2001 Malte Starostik <malte@kde.org>
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License version 2 as published by the Free Software Foundation.
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
13 You should have received a copy of the GNU Library General Public License
14 along with this library; see the file COPYING.LIB. If not, write to
15 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16 Boston, MA 02110-1301, USA.
19 // $Id$
21 #include <qclipboard.h>
22 #include <qdatetime.h>
23 #include <qregexp.h>
24 #include <q3dragobject.h>
25 #include <q3valuestack.h>
26 #include <q3stylesheet.h>
27 //Added by qt3to4:
28 #include <QMouseEvent>
29 #include <QPixmap>
30 #include <QDragEnterEvent>
31 #include <QDragMoveEvent>
32 #include <QDropEvent>
33 #include <QUrl>
34 #include <QTextDocumentFragment>
35 #include <QScrollBar>
37 #include <kapplication.h>
38 #include <kdebug.h>
39 #include <klocale.h>
40 #include <krun.h>
41 #include <kmenu.h>
42 #include <kstringhandler.h>
43 #include <knotifyclient.h>
44 #include <kfiledialog.h>
45 #include <kio/job.h>
46 #include <k3urldrag.h>
47 #include <kiconloader.h>
48 #include <QTextDocument>
50 #include "ksopts.h"
51 #include "ksview.moc"
52 #include "ksparser.h"
53 #include "nickColourMaker.h"
54 #include "ksircprocess.h"
56 using namespace Qt;
58 KSircView::KSircView(KSircProcess *proc, QWidget *parent, const char *name)
59 : QTextBrowser(parent), m_proc(proc)
61 setObjectName(name);
62 m_acceptFiles = false;
63 m_timestamps = false;
64 clear();
65 setUndoRedoEnabled(false);
66 connect(this, SIGNAL(anchorClicked(const QUrl &)),
67 this, SLOT(activateAnchor(const QUrl &)));
69 QPixmap background = ksopts->backgroundPixmap();
70 if ( !background.isNull() )
71 viewport()->setBackgroundPixmap( background );
73 // ### Qt 4.1
74 //setLinkColor( ksopts->linkColor );
77 KSircView::~KSircView()
81 void KSircView::clear()
83 m_lines = 0;
84 m_timeStamps.clear();
85 QTextBrowser::clear();
88 QString KSircView::makeTimeStamp()
90 QTime now = QTime::currentTime();
91 QString timeStamp = QString::fromLatin1( "[%1:%2:%3] " )
92 .arg( QString::number( now.hour() ).rightJustified( 2, '0' ) )
93 .arg( QString::number( now.minute() ).rightJustified( 2, '0' ) )
94 .arg( QString::number( now.second() ).rightJustified( 2, '0' ) );
95 return timeStamp;
98 void KSircView::saveURL( const QString &url )
100 KUrl kurl( url );
102 KFileDialog *dlg = new KFileDialog( QString::null, QString::null /*filter*/, this /*parent*/);
104 dlg->setKeepLocation( true );
106 dlg->setCaption( i18n( "Save As" ) );
108 if ( !kurl.fileName().isEmpty() )
109 dlg->setSelection( kurl.fileName() );
111 if ( dlg->exec() ) {
112 KUrl destURL( dlg->selectedURL() );
113 if ( destURL.isValid() ) {
114 KIO::Job *job = KIO::copy( kurl, destURL );
115 job->setAutoErrorHandlingEnabled( true );
119 delete dlg;
122 QString KSircView::addLine(const QString &pixmap, const QColor &color, const QString &_text)
124 //kDebug(5008) << "Start Text: " << _text << endl;
126 QString richText( "<font color=\"%1\">" );
127 richText = richText.arg( color.name() );
129 if ( !pixmap.isEmpty() )
130 richText.prepend( QString::fromLatin1( "<img src=\"%1\"></img>" ).arg( pixmap ) );
132 QString timeStamp = QString::fromLatin1( "<font color=\"%1\">%2</font>" )
133 .arg( ksopts->textColor.name() )
134 .arg( makeTimeStamp() );
135 m_timeStamps.append(timeStamp);
136 if ( m_timestamps )
137 richText.prepend( timeStamp );
139 QString text = Qt::escape(_text);
141 // ### a bit of a hack: turn '&lt;nick&gt; message' into
142 // <span>&lt;nick&gt;<span> message' . span itself isn't supported but it
143 // enforces the creation of separate item objects and hence separate
144 // drawing of '<nick>' and 'message' , which is needed for BiDi users,
145 // according to UV Kochavi <uv1st@yahoo.com> , to prevent output like
146 // '<nick message<' , which is supposedly a bug in Qt's reordering. The
147 // same is done for [nick] and >nick< to catch queries.
148 QRegExp bidiRe( "^(&lt;\\S+&gt;)(.+)$" );
149 text.replace( bidiRe, QString::fromLatin1( "<span>\\1</span>\\2" ) );
150 QRegExp bidiRe2( "^(\\[\\S+\\])(.+)$" );
151 text.replace( bidiRe2, QString::fromLatin1( "<span>\\1</span>\\2" ) );
152 QRegExp bidiRe3( "^(&gt;\\S+&lt;)(.+)$" );
153 text.replace( bidiRe3, QString::fromLatin1( "<span>\\1</span>\\2" ) );
155 QRegExp nickCol( "~n(.+)~n" );
156 nickCol.setMinimal(true);
157 int pos;
159 while( (pos = nickCol.search(text)) >= 0 ){
160 //kDebug(5008) << "Found nick: " << nickCol.cap(1) << endl;
161 QString newText = nickCol.cap(1);
162 if( nickCol.cap(1) != m_proc->getNick()){
163 QColor col = nickColourMaker::colourMaker()->findFg(nickCol.cap(1));
165 newText.prepend(QString("<font color=\"%1\">").arg(col.name()));
166 newText.append("</font>");
167 } else {
168 QColor col = ksopts->ownNickColor.name();
169 if( ! col.isValid())
170 nickColourMaker::colourMaker()->findFg(nickCol.cap(1));
171 newText.prepend(QString("<font color=\"%1\">").arg(col.name()));
172 newText.append("</font>");
173 if(ksopts->ownNickBold){
174 newText.prepend("<b>");
175 newText.append("</b>");
177 if(ksopts->ownNickUl){
178 newText.prepend("<u>");
179 newText.append("</u>");
181 if(ksopts->ownNickRev){
182 newText.prepend("<r>");
183 newText.append("</r>");
186 text.replace(pos, nickCol.matchedLength(), newText);
189 //kDebug(5008) << "After Text: " << text << endl;
191 KSParser parser;
192 richText += parser.parse( text );
194 richText += "</font>";
197 //kDebug(5008) << "Text: " << _text << endl;
199 setCurrentCharFormat(QTextCharFormat());
200 richText = KStringHandler::tagURLs( richText );
201 //kDebug(5008) << "Rich text: " << richText << endl;
203 append( richText );
205 m_lines++;
206 if ( ksopts->windowLength && m_lines > ksopts->windowLength )
208 while ( m_lines > ksopts->windowLength )
210 QTextCursor cursor = textCursor();
211 cursor.movePosition(QTextCursor::Start);
212 cursor.movePosition(QTextCursor::NextBlock, QTextCursor::KeepAnchor);
213 cursor.removeSelectedText();
214 m_timeStamps.remove( m_timeStamps.begin() );
215 m_lines--;
219 if (parser.beeped()) {
220 KNotifyClient::event(winId(), QString::fromLatin1("BeepReceived"),
221 i18n("Beep Received"));
224 QTextCursor cursor = textCursor();
225 cursor.movePosition(QTextCursor::End);
226 QString logText = cursor.block().text();
227 // append timestamp if it's not already there
228 if ( ! m_timestamps )
229 logText.prepend( makeTimeStamp() );
231 scrollToBottom();
233 return logText + '\n';
236 void KSircView::addRichText(const QString &_text)
238 //kDebug(5008) << "Start Text: " << _text << endl;
240 QString text = _text;
242 QRegExp re("^(<font color=\"[^\"]+\">\\[[0-9:]+\\] </font>)");
243 QString timeStamp;
245 if(re.search(text) >= 0){
246 timeStamp = re.cap(1);
248 else {
249 timeStamp = QString::fromLatin1( "<font color=\"%1\">%2</font>" )
250 .arg( ksopts->textColor.name() )
251 .arg( makeTimeStamp() );
252 if ( m_timestamps )
253 text.prepend( timeStamp );
255 m_timeStamps.append(timeStamp);
257 setCurrentCharFormat(QTextCharFormat());
258 append( text );
260 m_lines++;
261 if ( ksopts->windowLength && m_lines > ksopts->windowLength )
263 while ( m_lines > ksopts->windowLength )
265 QTextCursor cursor = textCursor();
266 cursor.movePosition(QTextCursor::Start);
267 cursor.movePosition(QTextCursor::NextBlock, QTextCursor::KeepAnchor);
268 cursor.removeSelectedText();
269 m_timeStamps.remove( m_timeStamps.begin() );
270 m_lines--;
274 scrollToBottom();
277 void KSircView::enableTimeStamps(bool enable)
279 if(enable == m_timestamps)
280 return;
281 setUpdatesEnabled( false );
282 m_timestamps = enable;
283 const int timeStampLen = makeTimeStamp().length();
284 QTextCursor cursor = textCursor();
285 cursor.movePosition(QTextCursor::Start);
286 QStringList::ConstIterator timeStampIt = m_timeStamps.begin();
287 for (; timeStampIt != m_timeStamps.end(); ++timeStampIt )
289 if ( enable ) {
290 cursor.insertFragment(QTextDocumentFragment::fromHtml(*timeStampIt));
291 } else {
292 cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, timeStampLen);
293 cursor.removeSelectedText();
295 cursor.movePosition(QTextCursor::NextBlock);
297 setUpdatesEnabled( true );
300 void KSircView::activateAnchor(const QUrl &url)
302 const QString u = url.toString();
303 if (QApplication::keyboardModifiers() & Qt::ShiftModifier)
304 saveURL(u);
305 else
306 openBrowser(u);
309 void KSircView::contextMenuEvent(QContextMenuEvent *e)
311 const QString url = anchorAt(e->pos());
312 if (url.isEmpty())
313 return;
315 // Adding a nice contextmenu
316 KMenu* menu = new KMenu( this );
317 menu->addTitle( i18n( "URL" ) );
318 QAction * openUrl = menu->addAction( i18n("Open URL") );
319 QAction * opendLink = menu->addAction( i18n("Copy Link Address"));
320 QAction *ret = menu->exec( e->globalPos() );
321 if( ret == openUrl)
322 openBrowser( url );
323 else if( ret == opendLink )
324 copyLinkToClipboard( url );
325 delete menu;
328 void KSircView::openBrowser(const QString &url )
330 (void) new KRun( KUrl( url.startsWith("www") ? QString::fromLatin1("http://") + url : url),this);
333 void KSircView::copyLinkToClipboard( const QString &url )
335 QApplication::clipboard()->setText( url, QClipboard::Clipboard );
338 QColor KSircView::ircColor(int code)
340 if (code >= 0 && code < 16)
341 return ksopts->ircColors[code];
342 return QColor();
345 void KSircView::dragEnterEvent(QDragEnterEvent* event)
347 event->accept((Q3TextDrag::canDecode(event) ||
348 (m_acceptFiles && K3URLDrag::canDecode(event))) &&
349 (!event->source() || event->source() != viewport()));
352 void KSircView::dragMoveEvent(QDragMoveEvent* event)
354 event->accept(!event->source() || event->source() != viewport());
357 void KSircView::dropEvent(QDropEvent* event)
359 QStringList urls;
360 QString text;
362 if (m_acceptFiles && K3URLDrag::decodeLocalFiles(event, urls))
363 emit urlsDropped(urls);
364 else if (Q3TextDrag::decode(event, text))
365 emit textDropped(text);
368 QVariant KSircView::loadResource(int type, const QUrl &name)
370 if (type != QTextDocument::ImageResource) {
371 return QTextBrowser::loadResource(type, name);
374 QString icon = name;
375 icon.remove("user|");
376 return UserIcon(icon);
379 void KSircView::scrollToBottom()
381 verticalScrollBar()->setValue(verticalScrollBar()->maximum());
384 void KSircView::resizeEvent(QResizeEvent *e)
386 QTextBrowser::resizeEvent(e);
387 scrollToBottom();
390 // vim: ts=4 sw=4 noet