source: ogBrowser-Git/qtermwidget/src/Filter.cpp @ 9d8d163

jenkinsmain
Last change on this file since 9d8d163 was 050d67a, checked in by adelcastillo <adelcastillo@…>, 16 years ago

Ahora el browser tiene consola en vez del output.
Pasado todo el sistema de compilacion a cmake.

git-svn-id: https://opengnsys.es/svn/trunk@408 a21b9725-9963-47de-94b9-378ad31fedc9

  • Property mode set to 100644
File size: 14.2 KB
Line 
1/*
2    Copyright (C) 2007 by Robert Knight <robertknight@gmail.com>
3
4    Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19    02110-1301  USA.
20*/
21
22// Own
23#include "Filter.h"
24#include "Filter.moc"
25
26
27// System
28#include <iostream>
29
30// Qt
31#include <QtGui/QAction>
32#include <QtGui/QApplication>
33#include <QtGui/QClipboard>
34#include <QtCore/QString>
35
36#include <QtCore/QSharedData>
37#include <QtCore>
38
39// KDE
40//#include <KLocale>
41//#include <KRun>
42
43// Konsole
44#include "TerminalCharacterDecoder.h"
45
46using namespace Konsole;
47
48FilterChain::~FilterChain()
49{
50    QMutableListIterator<Filter*> iter(*this);
51   
52    while ( iter.hasNext() )
53    {
54        Filter* filter = iter.next();
55        iter.remove();
56        delete filter;
57    }
58}
59
60void FilterChain::addFilter(Filter* filter)
61{
62    append(filter);
63}
64void FilterChain::removeFilter(Filter* filter)
65{
66    removeAll(filter);
67}
68bool FilterChain::containsFilter(Filter* filter)
69{
70    return contains(filter);
71}
72void FilterChain::reset()
73{
74    QListIterator<Filter*> iter(*this);
75    while (iter.hasNext())
76        iter.next()->reset();
77}
78void FilterChain::setBuffer(const QString* buffer , const QList<int>* linePositions)
79{
80    QListIterator<Filter*> iter(*this);
81    while (iter.hasNext())
82        iter.next()->setBuffer(buffer,linePositions);
83}
84void FilterChain::process()
85{
86    QListIterator<Filter*> iter(*this);
87    while (iter.hasNext())
88        iter.next()->process();
89}
90void FilterChain::clear()
91{
92    QList<Filter*>::clear();
93}
94Filter::HotSpot* FilterChain::hotSpotAt(int line , int column) const
95{
96    QListIterator<Filter*> iter(*this);
97    while (iter.hasNext())
98    {
99        Filter* filter = iter.next();
100        Filter::HotSpot* spot = filter->hotSpotAt(line,column);
101        if ( spot != 0 )
102        {
103            return spot;
104        }
105    }
106
107    return 0;
108}
109
110QList<Filter::HotSpot*> FilterChain::hotSpots() const
111{
112    QList<Filter::HotSpot*> list;
113    QListIterator<Filter*> iter(*this);
114    while (iter.hasNext())
115    {
116        Filter* filter = iter.next();
117        list << filter->hotSpots();
118    }
119    return list;
120}
121//QList<Filter::HotSpot*> FilterChain::hotSpotsAtLine(int line) const;
122
123TerminalImageFilterChain::TerminalImageFilterChain()
124: _buffer(0)
125, _linePositions(0)
126{
127}
128
129TerminalImageFilterChain::~TerminalImageFilterChain()
130{
131    delete _buffer;
132    delete _linePositions;
133}
134
135void TerminalImageFilterChain::setImage(const Character* const image , int lines , int columns, const QVector<LineProperty>& lineProperties)
136{
137//qDebug("%s %d", __FILE__, __LINE__);
138    if (empty())
139        return;
140//qDebug("%s %d", __FILE__, __LINE__);
141
142    // reset all filters and hotspots
143    reset();
144//qDebug("%s %d", __FILE__, __LINE__);
145
146    PlainTextDecoder decoder;
147    decoder.setTrailingWhitespace(false);
148   
149//qDebug("%s %d", __FILE__, __LINE__);
150    // setup new shared buffers for the filters to process on
151    QString* newBuffer = new QString();
152    QList<int>* newLinePositions = new QList<int>();
153    setBuffer( newBuffer , newLinePositions );
154
155    // free the old buffers
156    delete _buffer;
157    delete _linePositions;
158
159    _buffer = newBuffer;
160    _linePositions = newLinePositions;
161
162    QTextStream lineStream(_buffer);
163    decoder.begin(&lineStream);
164
165    for (int i=0 ; i < lines ; i++)
166    {
167        _linePositions->append(_buffer->length());
168        decoder.decodeLine(image + i*columns,columns,LINE_DEFAULT);
169
170        // pretend that each line ends with a newline character.
171        // this prevents a link that occurs at the end of one line
172        // being treated as part of a link that occurs at the start of the next line
173        //
174        // the downside is that links which are spread over more than one line are not
175        // highlighted. 
176        //
177        // TODO - Use the "line wrapped" attribute associated with lines in a
178        // terminal image to avoid adding this imaginary character for wrapped
179        // lines
180        if ( !(lineProperties.value(i,LINE_DEFAULT) & LINE_WRAPPED) )
181                lineStream << QChar('\n');
182    }
183    decoder.end();
184//    qDebug("%s %d", __FILE__, __LINE__);
185}
186
187Filter::Filter() :
188_linePositions(0),
189_buffer(0)
190{
191}
192
193Filter::~Filter()
194{
195    QListIterator<HotSpot*> iter(_hotspotList);
196    while (iter.hasNext())
197    {
198        delete iter.next();
199    }
200}
201void Filter::reset()
202{
203    _hotspots.clear();
204    _hotspotList.clear();
205}
206
207void Filter::setBuffer(const QString* buffer , const QList<int>* linePositions)
208{
209    _buffer = buffer;
210    _linePositions = linePositions;
211}
212
213void Filter::getLineColumn(int position , int& startLine , int& startColumn)
214{
215    Q_ASSERT( _linePositions );
216    Q_ASSERT( _buffer );
217
218
219    for (int i = 0 ; i < _linePositions->count() ; i++)
220    {
221        //kDebug() << "line position at " << i << " = " << _linePositions[i];
222        int nextLine = 0;
223
224        if ( i == _linePositions->count()-1 )
225        {
226            nextLine = _buffer->length() + 1;
227        }
228        else
229        {
230            nextLine = _linePositions->value(i+1);
231        }
232
233       // kDebug() << "pos - " << position << " line pos(" << i<< ") " << _linePositions->value(i) <<
234       //     " next = " << nextLine << " buffer len = " << _buffer->length();
235
236        if ( _linePositions->value(i) <= position && position < nextLine )
237        {
238            startLine = i;
239            startColumn = position - _linePositions->value(i);
240            return;
241        }
242    }
243}
244   
245
246/*void Filter::addLine(const QString& text)
247{
248    _linePositions << _buffer.length();
249    _buffer.append(text);
250}*/
251
252const QString* Filter::buffer()
253{
254    return _buffer;
255}
256Filter::HotSpot::~HotSpot()
257{
258}
259void Filter::addHotSpot(HotSpot* spot)
260{
261    _hotspotList << spot;
262
263    for (int line = spot->startLine() ; line <= spot->endLine() ; line++)
264    {
265        _hotspots.insert(line,spot);
266    }   
267}
268QList<Filter::HotSpot*> Filter::hotSpots() const
269{
270    return _hotspotList;
271}
272QList<Filter::HotSpot*> Filter::hotSpotsAtLine(int line) const
273{
274    return _hotspots.values(line);
275}
276
277Filter::HotSpot* Filter::hotSpotAt(int line , int column) const
278{
279    QListIterator<HotSpot*> spotIter(_hotspots.values(line));
280
281    while (spotIter.hasNext())
282    {
283        HotSpot* spot = spotIter.next();
284       
285        if ( spot->startLine() == line && spot->startColumn() > column )
286            continue;
287        if ( spot->endLine() == line && spot->endColumn() < column )
288            continue;
289       
290        return spot;
291    }
292
293    return 0;
294}
295
296Filter::HotSpot::HotSpot(int startLine , int startColumn , int endLine , int endColumn)
297    : _startLine(startLine)
298    , _startColumn(startColumn)
299    , _endLine(endLine)
300    , _endColumn(endColumn)
301    , _type(NotSpecified)
302{
303}
304QString Filter::HotSpot::tooltip() const
305{
306    return QString();
307}
308QList<QAction*> Filter::HotSpot::actions()
309{
310    return QList<QAction*>();
311}
312int Filter::HotSpot::startLine() const
313{
314    return _startLine;
315}
316int Filter::HotSpot::endLine() const
317{
318    return _endLine;
319}
320int Filter::HotSpot::startColumn() const
321{
322    return _startColumn;
323}
324int Filter::HotSpot::endColumn() const
325{
326    return _endColumn;
327}
328Filter::HotSpot::Type Filter::HotSpot::type() const
329{
330    return _type;
331}
332void Filter::HotSpot::setType(Type type)
333{
334    _type = type;
335}
336
337RegExpFilter::RegExpFilter()
338{
339}
340
341RegExpFilter::HotSpot::HotSpot(int startLine,int startColumn,int endLine,int endColumn)
342    : Filter::HotSpot(startLine,startColumn,endLine,endColumn)
343{
344    setType(Marker);
345}
346
347void RegExpFilter::HotSpot::activate(QObject*)
348{
349}
350
351void RegExpFilter::HotSpot::setCapturedTexts(const QStringList& texts)
352{
353    _capturedTexts = texts;
354}
355QStringList RegExpFilter::HotSpot::capturedTexts() const
356{
357    return _capturedTexts;
358}
359
360void RegExpFilter::setRegExp(const QRegExp& regExp)
361{
362    _searchText = regExp;
363}
364QRegExp RegExpFilter::regExp() const
365{
366    return _searchText;
367}
368/*void RegExpFilter::reset(int)
369{
370    _buffer = QString();
371}*/
372void RegExpFilter::process()
373{
374    int pos = 0;
375    const QString* text = buffer();
376
377    Q_ASSERT( text );
378
379    // ignore any regular expressions which match an empty string.
380    // otherwise the while loop below will run indefinitely
381    static const QString emptyString("");
382    if ( _searchText.exactMatch(emptyString) )
383        return;
384
385    while(pos >= 0)
386    {
387        pos = _searchText.indexIn(*text,pos);
388
389        if ( pos >= 0 )
390        {
391
392            int startLine = 0;
393            int endLine = 0;
394            int startColumn = 0;
395            int endColumn = 0;
396
397           
398            //kDebug() << "pos from " << pos << " to " << pos + _searchText.matchedLength();
399           
400            getLineColumn(pos,startLine,startColumn);
401            getLineColumn(pos + _searchText.matchedLength(),endLine,endColumn);
402
403            //kDebug() << "start " << startLine << " / " << startColumn;
404            //kDebug() << "end " << endLine << " / " << endColumn;
405
406            RegExpFilter::HotSpot* spot = newHotSpot(startLine,startColumn,
407                                           endLine,endColumn);
408            spot->setCapturedTexts(_searchText.capturedTexts());
409
410            addHotSpot( spot ); 
411            pos += _searchText.matchedLength();
412
413            // if matchedLength == 0, the program will get stuck in an infinite loop
414            Q_ASSERT( _searchText.matchedLength() > 0 );
415        }
416    }   
417}
418
419RegExpFilter::HotSpot* RegExpFilter::newHotSpot(int startLine,int startColumn,
420                                                int endLine,int endColumn)
421{
422    return new RegExpFilter::HotSpot(startLine,startColumn,
423                                                  endLine,endColumn);
424}
425RegExpFilter::HotSpot* UrlFilter::newHotSpot(int startLine,int startColumn,int endLine,
426                                                    int endColumn)
427{
428    return new UrlFilter::HotSpot(startLine,startColumn,
429                                               endLine,endColumn);
430}
431UrlFilter::HotSpot::HotSpot(int startLine,int startColumn,int endLine,int endColumn)
432: RegExpFilter::HotSpot(startLine,startColumn,endLine,endColumn)
433, _urlObject(new FilterObject(this))
434{
435    setType(Link);
436}
437QString UrlFilter::HotSpot::tooltip() const
438{
439    QString url = capturedTexts().first();
440
441    const UrlType kind = urlType();
442
443    if ( kind == StandardUrl )
444        return QString();
445    else if ( kind == Email )
446        return QString();
447    else
448        return QString();
449}
450UrlFilter::HotSpot::UrlType UrlFilter::HotSpot::urlType() const
451{
452    QString url = capturedTexts().first();
453   
454    if ( FullUrlRegExp.exactMatch(url) )
455        return StandardUrl;
456    else if ( EmailAddressRegExp.exactMatch(url) )
457        return Email;
458    else
459        return Unknown;
460}
461
462void UrlFilter::HotSpot::activate(QObject* object)
463{
464    QString url = capturedTexts().first();
465
466    const UrlType kind = urlType();
467
468    const QString& actionName = object ? object->objectName() : QString();
469
470    if ( actionName == "copy-action" )
471    {
472        //kDebug() << "Copying url to clipboard:" << url;
473
474        QApplication::clipboard()->setText(url);
475        return;
476    }
477
478    if ( !object || actionName == "open-action" )
479    {
480        if ( kind == StandardUrl )
481        {
482            // if the URL path does not include the protocol ( eg. "www.kde.org" ) then
483            // prepend http:// ( eg. "www.kde.org" --> "http://www.kde.org" )
484            if (!url.contains("://"))
485            {
486                url.prepend("http://");
487            }
488        }
489        else if ( kind == Email )
490        {
491            url.prepend("mailto:");
492        }
493   
494//        new KRun(url,QApplication::activeWindow());
495    }
496}
497
498// Note:  Altering these regular expressions can have a major effect on the performance of the filters
499// used for finding URLs in the text, especially if they are very general and could match very long
500// pieces of text.
501// Please be careful when altering them.
502
503//regexp matches:
504// full url: 
505// protocolname:// or www. followed by anything other than whitespaces, <, >, ' or ", and ends before whitespaces, <, >, ', ", ], !, comma and dot
506const QRegExp UrlFilter::FullUrlRegExp("(www\\.(?!\\.)|[a-z][a-z0-9+.-]*://)[^\\s<>'\"]+[^!,\\.\\s<>'\"\\]]");
507// email address:
508// [word chars, dots or dashes]@[word chars, dots or dashes].[word chars]
509const QRegExp UrlFilter::EmailAddressRegExp("\\b(\\w|\\.|-)+@(\\w|\\.|-)+\\.\\w+\\b");
510
511// matches full url or email address
512const QRegExp UrlFilter::CompleteUrlRegExp('('+FullUrlRegExp.pattern()+'|'+
513                                            EmailAddressRegExp.pattern()+')');
514
515UrlFilter::UrlFilter()
516{
517    setRegExp( CompleteUrlRegExp );
518}
519UrlFilter::HotSpot::~HotSpot()
520{
521    delete _urlObject;
522}
523void FilterObject::activated()
524{
525    _filter->activate(sender());
526}
527QList<QAction*> UrlFilter::HotSpot::actions()
528{
529    QList<QAction*> list;
530
531    const UrlType kind = urlType();
532
533    QAction* openAction = new QAction(_urlObject);
534    QAction* copyAction = new QAction(_urlObject);;
535
536    Q_ASSERT( kind == StandardUrl || kind == Email );
537
538    if ( kind == StandardUrl )
539    {
540        openAction->setText(("Open Link"));
541        copyAction->setText(("Copy Link Address"));
542    }
543    else if ( kind == Email )
544    {
545        openAction->setText(("Send Email To..."));
546        copyAction->setText(("Copy Email Address"));
547    }
548
549    // object names are set here so that the hotspot performs the
550    // correct action when activated() is called with the triggered
551    // action passed as a parameter.
552    openAction->setObjectName("open-action");
553    copyAction->setObjectName("copy-action");
554
555    QObject::connect( openAction , SIGNAL(triggered()) , _urlObject , SLOT(activated()) );
556    QObject::connect( copyAction , SIGNAL(triggered()) , _urlObject , SLOT(activated()) );
557
558    list << openAction;
559    list << copyAction;
560
561    return list;
562}
563
564//#include "moc_Filter.cpp"
Note: See TracBrowser for help on using the repository browser.