Akonadi Contacts

textbrowser.cpp
1 /*
2  Copyright (c) 2012-2020 Laurent Montel <[email protected]>
3 
4  This library is free software; you can redistribute it and/or modify it
5  under the terms of the GNU Library General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or (at your
7  option) any later version.
8 
9  This library is distributed in the hope that it will be useful, but WITHOUT
10  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
12  License for more details.
13 
14  You should have received a copy of the GNU Library General Public License
15  along with this library; see the file COPYING.LIB. If not, write to the
16  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  02110-1301, USA.
18 
19 */
20 
21 #include "textbrowser_p.h"
22 #include <KLocalizedString>
23 #include <QUrl>
24 #include <QAction>
25 #include <KStandardAction>
26 #include <KCodecs>
27 
28 #include <QApplication>
29 #include <QContextMenuEvent>
30 #include <QMenu>
31 #include <QClipboard>
32 #include <QTextBlock>
33 
34 using namespace Akonadi;
35 
36 TextBrowser::TextBrowser(QWidget *parent)
37  : QTextBrowser(parent)
38 {
39  setOpenLinks(false);
40 }
41 
42 void TextBrowser::slotCopyData()
43 {
44 #ifndef QT_NO_CLIPBOARD
46  // put the data into the mouse selection and the clipboard
47  if (mDataToCopy.type() == QVariant::Pixmap) {
48  clip->setPixmap(mDataToCopy.value<QPixmap>(), QClipboard::Clipboard);
49  clip->setPixmap(mDataToCopy.value<QPixmap>(), QClipboard::Selection);
50  } else {
51  clip->setText(mDataToCopy.toString(), QClipboard::Clipboard);
52  clip->setText(mDataToCopy.toString(), QClipboard::Selection);
53  }
54 #endif
55 }
56 
57 #ifndef QT_NO_CONTEXTMENU
58 void TextBrowser::contextMenuEvent(QContextMenuEvent *event)
59 {
60 #ifndef QT_NO_CLIPBOARD
61  QMenu popup;
62 
63  QAction *act = KStandardAction::copy(this, &TextBrowser::copy, this);
64  act->setEnabled(!textCursor().selectedText().isEmpty());
65  act->setShortcut(QKeySequence());
66  popup.addAction(act);
67 
68  // Create a new action to correspond with what is under the click
69  act = new QAction(i18nc("@action:inmenu Copy the text of a general item", "Copy Item"), this);
70 
71  mDataToCopy.clear(); // nothing found to copy yet
72 
73  QString link = anchorAt(event->pos());
74  if (!link.isEmpty()) {
75  if (link.startsWith(QLatin1String("mailto:"))) {
76  mDataToCopy = KCodecs::decodeRFC2047String(QUrl(link).path());
77  // Action text matches that used in KMail
78  act->setText(i18nc("@action:inmenu Copy a displayed email address", "Copy Email Address"));
79  } else {
80  // A link, but it could be one of our internal ones. There is
81  // no point in copying these. Internal links are always in the
82  // form "protocol:?argument", whereas valid external links should
83  // be in the form starting with "protocol://".
84  if (!link.contains(QRegExp(QStringLiteral("^\\w+:\\?")))) {
85  mDataToCopy = link;
86  // Action text matches that used in Konqueror
87  act->setText(i18nc("@action:inmenu Copy a link URL", "Copy Link URL"));
88  }
89  }
90  }
91 
92  if (!mDataToCopy.isValid()) { // no link was found above
93  QTextCursor curs = cursorForPosition(event->pos());
94  QString text = curs.block().text(); // try the text under cursor
95 
96  if (!text.isEmpty()) {
97  // curs().block().text() over an image (contact photo or QR code)
98  // returns a string starting with the character 0xFFFC (Unicode
99  // object replacement character). See the documentation for
100  // QTextImageFormat.
101  if (text.startsWith(QChar(0xFFFC))) {
102  QTextCharFormat charFormat = curs.charFormat();
103  if (charFormat.isImageFormat()) {
104  QTextImageFormat imageFormat = charFormat.toImageFormat();
105  QString imageName = imageFormat.name();
106  QVariant imageResource = document()->resource(QTextDocument::ImageResource,
107  QUrl(imageName));
108 
109  QPixmap pix = imageResource.value<QPixmap>();
110  if (!pix.isNull()) {
111  // There may be other images (e.g. contact type icons) that
112  // there is no point in copying.
113  if (imageName == QLatin1String("contact_photo")) {
114  mDataToCopy = pix;
115  act->setText(i18nc("@action:inmenu Copy a contact photo", "Copy Photo"));
116  } else if (imageName == QLatin1String("qrcode")) {
117  mDataToCopy = pix;
118  act->setText(i18nc("@action:inmenu Copy a QR code image", "Copy Code"));
119  }
120  }
121  }
122  } else {
123  // Added by our formatter (but not I18N'ed) for a mobile
124  // telephone number. See
125  // kdepim/kaddressbook/grantlee/grantleecontactformatter.cpp and
126  // kdepimlibs/akonadi/contact/standardcontactformatter.cpp
127  text.remove(QRegExp(QStringLiteral("\\s*\\(SMS\\)$")));
128 
129  // For an item which was formatted with line breaks (as <br>
130  // in HTML), the returned text contains the character 0x2028
131  // (Unicode line separator). Convert any of these back to newlines.
132  text.replace(QChar(0x2028), QLatin1Char('\n'));
133 
134  mDataToCopy = text;
135  }
136  }
137  }
138 
139  if (mDataToCopy.isValid()) {
140  connect(act, &QAction::triggered, this, &TextBrowser::slotCopyData);
141  } else {
142  act->setEnabled(false);
143  }
144 
145  popup.addAction(act);
146  popup.exec(event->globalPos());
147 #endif
148 }
149 
150 #endif
void setText(const QString &text)
void triggered(bool checked)
QTextCharFormat charFormat() const const
KCODECS_EXPORT QString decodeRFC2047String(const QString &text)
T value() const const
const QPoint & globalPos() const const
QAction * addAction(const QString &text)
void setPixmap(const QPixmap &pixmap, QClipboard::Mode mode)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
bool isEmpty() const const
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const const
QAction * copy(const QObject *recvr, const char *slot, QObject *parent)
QAction * exec()
bool isImageFormat() const const
QTextBlock block() const const
bool isNull() const const
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
void setShortcut(const QKeySequence &shortcut)
QString text() const const
const QPoint & pos() const const
KIOCORE_EXPORT CopyJob * link(const QUrl &src, const QUrl &destDir, JobFlags flags=DefaultFlags)
void setText(const QString &text, QClipboard::Mode mode)
QTextImageFormat toImageFormat() const const
QClipboard * clipboard()
void setEnabled(bool)
QString name() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Wed Jul 1 2020 23:06:13 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.