2
* psitextview.cpp - Icon-aware QTextView subclass widget
3
* Copyright (C) 2003 Michail Pishchagin
5
* This library is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU Lesser General Public
7
* License as published by the Free Software Foundation; either
8
* version 2.1 of the License, or (at your option) any later version.
10
* This library 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
* Lesser General Public License for more details.
15
* You should have received a copy of the GNU Lesser General Public
16
* License along with this library; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
#include "psitextview.h"
23
#include <qpopupmenu.h>
24
#include <qapplication.h>
25
#include <qclipboard.h>
28
#include <qstylesheet.h>
29
#include <private/qrichtext_p.h>
38
//----------------------------------------------------------------------------
39
// URLObject - helper class for handling links
40
//----------------------------------------------------------------------------
42
class URLObject : public QObject
47
URLObject(QObject *parent = 0)
48
: QObject(qApp) { Q_UNUSED(parent); }
50
QPopupMenu *createPopupMenu(const QString &lnk);
55
QString copyString(QString from)
59
int colon = l.find(':');
62
QString service = l.left( colon );
64
if ( service == "mailto" || service == "jabber" || service == "jid" || service == "xmpp" ) {
66
l = l.mid( colon + 1 );
76
void openURL(QString);
79
void popupAction(QString lnk) {
87
void popupCopy(QString lnk) {
88
QApplication::clipboard()->setText( copyString(lnk), QClipboard::Clipboard );
89
if(QApplication::clipboard()->supportsSelection())
90
QApplication::clipboard()->setText( copyString(lnk), QClipboard::Selection );
98
static URLObject *urlObject = 0;
100
QPopupMenu *URLObject::createPopupMenu(const QString &lnk)
103
if ( link.isEmpty() )
106
int colon = link.find(':');
109
QString service = link.left( colon );
111
QString action = "ERROR";
114
if ( service == "mailto" ) {
115
action = URLLabel::tr("Open mail composer");
116
iconName = "psi/email";
118
else if ( service == "jabber" || service == "jid" || service == "xmpp" ) {
119
// TODO: need more actions to jabber item. Ex: "add to roster", "send message"
120
action = URLLabel::tr("Add to Roster");
121
iconName = "psi/add";
123
else { //if ( service == "http" || service == "https" || service.isEmpty() ) {
124
action = URLLabel::tr("Open web browser");
125
iconName = "psi/www";
128
#ifndef WIDGET_PLUGIN
129
const Icon *icon = 0;
130
if ( !iconName.isEmpty() )
131
icon = IconsetFactory::iconPtr( iconName );
134
QPopupMenu *m = new QPopupMenu;
136
#ifndef WIDGET_PLUGIN
138
m->insertItem(/*QIconSet(*/ *icon /*)*/, action, this, SLOT(popupAction()));
141
m->insertItem(action, this, SLOT(popupAction()));
142
m->insertItem(URLLabel::tr("Copy location"), this, SLOT(popupCopy()));
147
//----------------------------------------------------------------------------
148
// TextIcon - helper class for PsiTextView
149
//----------------------------------------------------------------------------
151
class TextIcon : public QObject, public QTextCustomItem
156
TextIcon(QTextDocument *p, const QMap<QString, QString> &attr, const QString &context, QMimeSourceFactory &factory);
159
void adjustToPainter(QPainter *);
160
void draw(QPainter *p, int x, int y, int cx, int cy, int cw, int ch, const QColorGroup &cg, bool selected);
161
QString richText() const;
163
Placement placement() const { return place; }
164
int minimumWidth() const { return width; }
167
void iconUpdated(const QPixmap &);
171
int tmpwidth, tmpheight;
172
QMap<QString, QString> attributes;
177
TextIcon::TextIcon(QTextDocument *p, const QMap<QString, QString> &attr, const QString &context, QMimeSourceFactory &factory)
178
: QObject(0, 0), QTextCustomItem (p)
186
QString iconName = attr["name"];
188
if ( iconName.isEmpty() )
189
iconName = attr["src"];
191
if ( iconName.isEmpty() )
192
iconName = attr["source"];
194
#ifndef WIDGET_PLUGIN
195
if ( !iconName.isEmpty() ) {
196
icon = (Icon *)IconsetFactory::iconPtr( iconName );
198
icon = new Icon(*icon);
202
connect(icon, SIGNAL(pixmapChanged(const QPixmap &)), SLOT(iconUpdated(const QPixmap &)));
204
width = icon->pixmap().width();
205
height = icon->pixmap().height();
210
if ( !icon && (width*height)==0 )
214
if ( attr["align"] == "left" )
216
else if ( attr["align"] == "right" )
225
TextIcon::~TextIcon()
227
#ifndef WIDGET_PLUGIN
235
void TextIcon::adjustToPainter(QPainter *)
237
// FIXME: This class can be incorrectly printed. Check this sometime later.
240
void TextIcon::draw(QPainter *p, int x, int y, int cx, int cy, int cw, int ch, const QColorGroup &cg, bool /*selected*/)
242
if ( placement() != PlaceInline ) {
248
p->fillRect( x, y, width, height, cg.dark() );
252
if ( placement() != PlaceInline && !QRect( xpos, ypos, width, height ).intersects( QRect( cx, cy, cw, ch ) ) )
255
#ifndef WIDGET_PLUGIN
256
if ( placement() == PlaceInline )
257
p->drawPixmap( x , y, icon->pixmap() );
259
p->drawPixmap( cx , cy, icon->pixmap(), cx - x, cy - y, cw, ch );
263
void TextIcon::iconUpdated(const QPixmap &)
265
// TODO: any ideas what it should do? ;-)
268
QString TextIcon::richText() const
272
QMap<QString, QString>::ConstIterator it = attributes.begin();
273
for ( ; it != attributes.end(); ++it ) {
275
if ( (*it).find( ' ' ) != -1 )
276
s += "\"" + *it + "\"" + " ";
284
//----------------------------------------------------------------------------
285
// PsiStyleSheet - helper class for PsiTextView
286
//----------------------------------------------------------------------------
288
class PsiStyleSheet : public QStyleSheet
292
PsiStyleSheet(QObject *parent = 0, const char *name = 0)
293
: QStyleSheet(parent, name)
295
new QStyleSheetItem(this, QString::fromLatin1("icon"));
299
QTextCustomItem *tag(const QString &name, const QMap<QString, QString> &attr,
300
const QString &context,
301
const QMimeSourceFactory &factory,
302
bool emptyTag, QTextDocument *doc ) const
304
const QStyleSheetItem *style = item( name );
305
if ( style && style->name() == "icon" )
306
return new TextIcon( doc, attr, context, (QMimeSourceFactory&)factory );
307
return QStyleSheet::tag(name, attr, context, factory, emptyTag, doc);
310
static PsiStyleSheet *self();
313
static PsiStyleSheet *psiStyleSheet;
316
PsiStyleSheet *PsiStyleSheet::psiStyleSheet = 0;
318
PsiStyleSheet *PsiStyleSheet::self()
320
if ( !psiStyleSheet ) {
321
psiStyleSheet = new PsiStyleSheet();
324
return psiStyleSheet;
327
//----------------------------------------------------------------------------
329
//----------------------------------------------------------------------------
331
class PsiTextView::Private : public QObject
336
Private(QObject *parent)
337
: QObject(parent, "PsiTextView::Private") { }
340
PsiTextView::PsiTextView(QWidget *parent, const char *name)
341
: QTextEdit(parent, name)
343
d = new Private(this);
346
setTextFormat(RichText);
348
setStyleSheet( styleSheet() );
351
QStyleSheet *PsiTextView::styleSheet()
353
return PsiStyleSheet::self();
356
QPopupMenu *PsiTextView::createPopupMenu(const QPoint &pos)
358
QString link = anchorAt(pos);
359
if ( link.isEmpty() )
360
return QTextEdit::createPopupMenu(pos);
363
urlObject = new URLObject();
364
return urlObject->createPopupMenu( link );
367
void PsiTextView::emitHighlighted(const QString &)
371
void PsiTextView::emitLinkClicked(const QString &s)
374
urlObject = new URLObject();
375
urlObject->popupAction( s );
378
//----------------------------------------------------------------------------
380
//----------------------------------------------------------------------------
382
class URLLabel::Private
389
URLLabel::URLLabel(QWidget *parent, const char *name)
390
: QLabel(parent, name)
393
setCursor( pointingHandCursor );
396
URLLabel::~URLLabel()
401
const QString &URLLabel::url() const
406
void URLLabel::setUrl(const QString &url)
412
const QString &URLLabel::title() const
417
void URLLabel::setTitle(const QString &t)
423
void URLLabel::updateText()
425
setText( QString("<a href=\"%1\">%2</a>").arg(d->url).arg(d->title) );
427
if ( d->url != d->title )
428
QToolTip::add(this, d->url);
430
QToolTip::remove(this);
433
void URLLabel::mouseReleaseEvent (QMouseEvent *e)
435
QLabel::mouseReleaseEvent (e);
437
switch ( e->button() ) {
440
urlObject = new URLObject();
441
urlObject->popupAction( url() );
450
urlObject = new URLObject();
451
QPopupMenu *m = urlObject->createPopupMenu( d->url );
454
m->exec( e->globalPos() );
461
; // to supress warnings
465
void URLLabel::enterEvent (QEvent *e)
467
QLabel::enterEvent (e);
470
void URLLabel::leaveEvent (QEvent *e)
472
QLabel::leaveEvent (e);
475
void URLLabel::connectOpenURL(QObject *receiver, const char *slot)
478
urlObject = new URLObject();
480
connect(urlObject, SIGNAL(openURL(QString)), receiver, slot);
483
#include "psitextview.moc"