1 /*
2 * urlobject.cpp - helper class for handling links
3 * Copyright (C) 2003-2006 Michail Pishchagin
4 *
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.
9 *
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.
14 *
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 *
19 */
20
21 #include "urlobject.h"
22 #include "psioptions.h"
23
24 #include <QApplication>
25 #include <QClipboard>
26 #include <QMenu>
27 #include <QSignalMapper>
28 #include <QUrl>
29 #ifdef HAVE_QT5
30 # include <QUrlQuery>
31 #endif
32
33 #include "iconaction.h"
34
35 //! \if _hide_doc_
36 class URLObject::Private : QObject
37 {
38 Q_OBJECT
39 public:
40 QString link;
41 IconAction *act_xmpp, *act_mailto, *act_join_groupchat, *act_send_message, *act_chat, *act_browser, *act_add_to_roster, *act_copy, *act_info;
42 URLObject *urlObject;
43 QSignalMapper xmppActionMapper;
44
connectXmppAction(QAction * action,const QString & query)45 void connectXmppAction(QAction* action, const QString& query)
46 {
47 connect(action, SIGNAL(triggered()), &xmppActionMapper, SLOT(map()));
48 xmppActionMapper.setMapping(action, query);
49 }
50
Private(URLObject * parent)51 Private(URLObject *parent)
52 : QObject(parent)
53 {
54 urlObject = parent;
55 QString tr;
56
57 tr = qApp->translate("URLLabel", "Open");
58 act_xmpp = new IconAction(tr, "psi/jabber", tr, 0, this);
59 connectXmppAction(act_xmpp, "");
60
61 tr = qApp->translate("URLLabel", "Open mail composer");
62 act_mailto = new IconAction(tr, "psi/email", tr, 0, this);
63 connect(act_mailto, SIGNAL(triggered()), SLOT(popupAction()));
64
65 tr = qApp->translate("URLLabel", "Open web browser");
66 act_browser = new IconAction(tr, "psi/www", tr, 0, this);
67 connect(act_browser, SIGNAL(triggered()), SLOT(popupAction()));
68
69 tr = qApp->translate("URLLabel", "Add to Roster");
70 act_add_to_roster = new IconAction(tr, "psi/addContact", tr, 0, this);
71 connectXmppAction(act_add_to_roster, "roster");
72
73 tr = qApp->translate("URLLabel", "Send message to");
74 act_send_message = new IconAction(tr, "psi/message", tr, 0, this);
75 connectXmppAction(act_send_message, "message");
76
77 tr = qApp->translate("URLLabel", "Chat with");
78 act_chat = new IconAction(tr, "psi/chat", tr, 0, this);
79 connectXmppAction(act_chat, "message;type=chat");
80
81 tr = qApp->translate("URLLabel", "Join groupchat");
82 act_join_groupchat = new IconAction(tr, "psi/groupChat", tr, 0, this);
83 connectXmppAction(act_join_groupchat, "join");
84
85 tr = qApp->translate("URLLabel", "Copy location");
86 act_copy = new IconAction(tr, tr, 0, this);
87 connect(act_copy, SIGNAL(triggered()), SLOT(popupCopy()));
88
89 tr = qApp->translate("URLLabel", "User Info");
90 act_info = new IconAction(tr, "psi/vCard", tr, 0, this);
91 connectXmppAction(act_info, "vcard");
92
93 connect(&xmppActionMapper, SIGNAL(mapped(const QString&)), SLOT(xmppAction(const QString&)));
94 }
95
copyString(QString from)96 QString copyString(QString from)
97 {
98 QString l = from;
99
100 int colon = l.indexOf(':');
101 if ( colon == -1 )
102 colon = 0;
103 QString service = l.left( colon );
104
105 if ( service == "mailto" || service == "jabber" || service == "jid" || service == "xmpp" || service == "x-psi-atstyle") {
106 if ( colon > -1 )
107 l = l.mid( colon + 1 );
108
109 while ( l[0] == '/' )
110 l = l.mid( 1 );
111 }
112
113 return l;
114 }
115
116 public slots:
popupAction(QString lnk)117 void popupAction(QString lnk) {
118 if (lnk.startsWith("x-psi-atstyle:")) {
119 lnk.replace(0, 13, "mailto");
120 }
121 emit urlObject->openURL(lnk);
122 }
123
popupAction()124 void popupAction() {
125 popupAction(link);
126 }
127
popupCopy(QString lnk)128 void popupCopy(QString lnk) {
129 QApplication::clipboard()->setText( copyString(lnk), QClipboard::Clipboard );
130 if(QApplication::clipboard()->supportsSelection())
131 QApplication::clipboard()->setText( copyString(lnk), QClipboard::Selection );
132 }
133
popupCopy()134 void popupCopy() {
135 popupCopy(link);
136 }
137
xmppAction(const QString & lnk,const QString & query)138 void xmppAction(const QString& lnk, const QString& query) {
139 QUrl uri(lnk);
140 if (!query.isEmpty()) {
141 QString queryType = query.left(query.indexOf(';'));
142 #ifdef HAVE_QT5
143 QUrlQuery q;
144 q.setQueryDelimiters('=', ';');
145 q.setQuery(uri.query(QUrl::FullyEncoded));
146
147 if (q.queryItems().value(0).first != queryType) {
148 q.setQuery(query);
149 }
150 uri.setQuery(q);
151 #else
152 uri.setQueryDelimiters('=', ';');
153 if (uri.queryItems().value(0).first != queryType) {
154 uri.setEncodedQuery(query.toLatin1());
155 }
156 #endif
157 }
158 uri.setScheme("xmpp");
159 emit urlObject->openURL(uri.toString());
160 }
161
xmppAction(const QString & query)162 void xmppAction(const QString& query) {
163 xmppAction(link, query);
164 }
165 };
166 //! \endif
167
168 /**
169 * \class URLObject
170 * \brief Helper class for handling clicking on URLs
171 */
172
173 /**
174 * Default constructor.
175 */
URLObject()176 URLObject::URLObject()
177 : QObject(qApp)
178 {
179 d = new Private(this);
180 }
181
182 /**
183 * Returns instance of the class, and creates it if necessary.
184 */
getInstance()185 URLObject *URLObject::getInstance()
186 {
187 static URLObject *urlObject = 0;
188 if (!urlObject)
189 urlObject = new URLObject();
190 return urlObject;
191 }
192
193 /**
194 * Creates QMenu with actions corresponding to link's type.
195 * @param lnk link in service:url format
196 */
createPopupMenu(const QString & lnk)197 QMenu *URLObject::createPopupMenu(const QString &lnk)
198 {
199 d->link = lnk;
200 if ( d->link.isEmpty() )
201 return 0;
202
203 int colon = d->link.indexOf(':');
204 if ( colon == -1 )
205 colon = 0;
206 QString service = d->link.left( colon );
207
208 QMenu *m = new QMenu;
209
210 bool needGenericOpen = true;
211 if (service == "mailto" || service == "x-psi-atstyle") {
212 needGenericOpen = false;
213 m->addAction(d->act_mailto);
214 }
215 if (service == "jabber" || service == "jid" || service == "xmpp" || service == "x-psi-atstyle") {
216 needGenericOpen = false;
217 if (service == "x-psi-atstyle") {
218 m->addSeparator();
219 }
220 m->addAction(d->act_info);
221 m->addAction(d->act_xmpp);
222 m->addAction(d->act_chat);
223 m->addAction(d->act_send_message);
224 m->addAction(d->act_join_groupchat);
225 //m->addAction(d->act_add_to_roster);
226 if (service == "x-psi-atstyle") {
227 m->addSeparator();
228 }
229 }
230 if (needGenericOpen) {
231 m->addAction(d->act_browser);
232 }
233
234 m->addAction(d->act_copy);
235 m->setStyleSheet(PsiOptions::instance()->getOption("options.ui.look.css").toString());
236 return m;
237 }
238
239 /**
240 * Simulates default action using the passed URL.
241 * \param lnk URL string
242 */
popupAction(QString lnk)243 void URLObject::popupAction(QString lnk)
244 {
245 d->popupAction(lnk);
246 }
247
248 #include "urlobject.moc"
249