LeechCraft  %{LEECHCRAFT_VERSION}
Modular cross-platform feature rich live environment.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
util.cpp
Go to the documentation of this file.
1 /**********************************************************************
2  * LeechCraft - modular cross-platform feature rich internet client.
3  * Copyright (C) 2006-2013 Georg Rudoy
4  *
5  * Boost Software License - Version 1.0 - August 17th, 2003
6  *
7  * Permission is hereby granted, free of charge, to any person or organization
8  * obtaining a copy of the software and accompanying documentation covered by
9  * this license (the "Software") to use, reproduce, display, distribute,
10  * execute, and transmit the Software, and to prepare derivative works of the
11  * Software, and to permit third-parties to whom the Software is furnished to
12  * do so, all subject to the following:
13  *
14  * The copyright notices in the Software and this entire statement, including
15  * the above license grant, this restriction and the following disclaimer,
16  * must be included in all copies of the Software, in whole or in part, and
17  * all derivative works of the Software, unless such copies or derivative
18  * works are solely in the form of machine-executable object code generated by
19  * a source language processor.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
24  * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
25  * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
26  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27  * DEALINGS IN THE SOFTWARE.
28  **********************************************************************/
29 
30 #include "util.h"
31 #include <functional>
32 #include <stdexcept>
33 #include <QString>
34 #include <QApplication>
35 #include <QTranslator>
36 #include <QLocale>
37 #include <QFile>
38 #include <QDir>
39 #include <QTemporaryFile>
40 #include <QTime>
41 #include <QSettings>
42 #include <QTextCodec>
43 #include <QUrl>
44 #include <QAction>
45 #include <QBuffer>
46 #include <QPainter>
47 #include <QtDebug>
48 
49 Q_DECLARE_METATYPE (QList<QModelIndex>);
50 Q_DECLARE_METATYPE (QVariantList*);
51 
53 
54 QString LeechCraft::Util::GetAsBase64Src (const QImage& pix)
55 {
56  QBuffer buf;
57  buf.open (QIODevice::ReadWrite);
58  pix.save (&buf, "PNG", 100);
59  return QString ("data:image/png;base64,%1")
60  .arg (QString (buf.buffer ().toBase64 ()));
61 }
62 
64 {
65  QString string = QObject::tr ("Too long to show");
66  if (p.Additional_.contains ("UserVisibleName") &&
67  p.Additional_ ["UserVisibleName"].canConvert<QString> ())
68  string = p.Additional_ ["UserVisibleName"].toString ();
69  else if (p.Entity_.canConvert<QByteArray> ())
70  {
71  QByteArray entity = p.Entity_.toByteArray ();
72  if (entity.size () < 100)
73  string = QTextCodec::codecForName ("UTF-8")->toUnicode (entity);
74  }
75  else if (p.Entity_.canConvert<QUrl> ())
76  {
77  string = p.Entity_.toUrl ().toString ();
78  if (string.size () > 100)
79  string = string.left (97) + "...";
80  }
81  else
82  string = QObject::tr ("Binary entity");
83 
84  if (!p.Mime_.isEmpty ())
85  string += QObject::tr ("<br /><br />of type <code>%1</code>").arg (p.Mime_);
86 
87  if (!p.Additional_ ["SourceURL"].toUrl ().isEmpty ())
88  {
89  QString urlStr = p.Additional_ ["SourceURL"].toUrl ().toString ();
90  if (urlStr.size () > 63)
91  urlStr = urlStr.left (60) + "...";
92  string += QObject::tr ("<br />from %1")
93  .arg (urlStr);
94  }
95 
96  return string;
97 }
98 
99 QString LeechCraft::Util::MakePrettySize (qint64 sourcesize)
100 {
101  int strNum = 0;
102  long double size = sourcesize;
103  if (size >= 1024)
104  {
105  strNum = 1;
106  size /= 1024;
107  }
108  if (size >= 1024)
109  {
110  strNum = 2;
111  size /= 1024;
112  }
113  if (size >= 1024)
114  {
115  strNum = 3;
116  size /= 1024;
117  }
118 
119  switch (strNum)
120  {
121  case 0:
122  return QString::number (size, 'f', 1) + QObject::tr (" b");
123  case 1:
124  return QString::number (size, 'f', 1) + QObject::tr (" KiB");
125  case 2:
126  return QString::number (size, 'f', 1) + QObject::tr (" MiB");
127  case 3:
128  return QString::number (size, 'f', 1) + QObject::tr (" GiB");
129  default:
130  return "unknown";
131  }
132 }
133 
135 {
136  int d = time / 86400;
137  time -= d * 86400;
138  QString result;
139  if (d)
140  result += QObject::tr ("%n day(s), ", "", d);
141  result += QTime (0, 0, 0).addSecs (time).toString ();
142  return result;
143 }
144 
145 QTranslator* LeechCraft::Util::InstallTranslator (const QString& baseName,
146  const QString& prefix,
147  const QString& appName)
148 {
149  QString localeName = GetLocaleName ();
150  QString filename = prefix;
151  filename.append ("_");
152  if (!baseName.isEmpty ())
153  filename.append (baseName).append ("_");
154  filename.append (localeName);
155 
156  QTranslator *transl = new QTranslator;
157 #ifdef Q_OS_WIN32
158  if (transl->load (filename, ":/") ||
159  transl->load (filename,
160  QCoreApplication::applicationDirPath () + "/translations"))
161 #elif defined (Q_OS_MAC)
162  if (transl->load (filename, ":/") ||
163  transl->load (filename,
164  QCoreApplication::applicationDirPath () + "/../Resources/translations"))
165 #elif defined (INSTALL_PREFIX)
166  if (transl->load (filename, ":/") ||
167  transl->load (filename,
168  QString (INSTALL_PREFIX "/share/%1/translations").arg (appName)))
169 #else
170  if (transl->load (filename, ":/") ||
171  transl->load (filename,
172  QString ("/usr/local/share/%1/translations").arg (appName)) ||
173  transl->load (filename,
174  QString ("/usr/share/%1/translations").arg (appName)))
175 #endif
176  {
177  qApp->installTranslator (transl);
178  return transl;
179  }
180  delete transl;
181 
182  qWarning () << Q_FUNC_INFO
183  << "could not load translation file for locale"
184  << localeName
185  << filename;
186  return 0;
187 }
188 
190 {
191  QSettings settings (QCoreApplication::organizationName (),
192  QCoreApplication::applicationName ());
193  QString localeName = settings.value ("Language", "system").toString ();
194 
195  if (localeName == "system")
196  {
197  localeName = QString (::getenv ("LANG")).left (5);
198  if (localeName.isEmpty () || localeName.size () != 5)
199  localeName = QLocale::system ().name ();
200  localeName = localeName.left (5);
201  }
202 
203  if (localeName.size () == 2)
204  {
205  QLocale::Language lang = QLocale (localeName).language ();
206  QList<QLocale::Country> cs = QLocale::countriesForLanguage (lang);
207  if (cs.isEmpty ())
208  localeName += "_00";
209  else
210  localeName = QLocale (lang, cs.at (0)).name ();
211  }
212 
213  return localeName;
214 }
215 
216 QString LeechCraft::Util::GetInternetLocaleName (const QLocale& locale)
217 {
218 #if QT_VERSION >= 0x040800
219  if (locale.language () == QLocale::AnyLanguage)
220  return "*";
221 #endif
222 
223  QString locStr = locale.name ();
224  locStr.replace ('_', '-');
225  return locStr;
226 }
227 
229 {
230  return GetLocaleName ().left (2);
231 }
232 
233 QDir LeechCraft::Util::CreateIfNotExists (const QString& opath)
234 {
235  QString path = opath;
236 
237  QDir home = QDir::home ();
238  path.prepend (".leechcraft/");
239 
240  if (!home.exists (path) &&
241  !home.mkpath (path))
242  throw std::runtime_error (qPrintable (QObject::tr ("Could not create %1")
243  .arg (QDir::toNativeSeparators (home.filePath (path)))));
244 
245  if (home.cd (path))
246  return home;
247  else
248  throw std::runtime_error (qPrintable (QObject::tr ("Could not cd into %1")
249  .arg (QDir::toNativeSeparators (home.filePath (path)))));
250 }
251 
252 QDir LeechCraft::Util::GetUserDir (const QString& opath)
253 {
254  QString path = opath;
255  QDir home = QDir::home ();
256  path.prepend (".leechcraft/");
257 
258  if (!home.exists (path))
259  throw std::runtime_error (qPrintable (QString ("The specified path doesn't exist: %1")
260  .arg (QDir::toNativeSeparators (home.filePath (path)))));
261 
262  if (home.cd (path))
263  return home;
264  else
265  throw std::runtime_error (qPrintable (QObject::tr ("Could not cd into %1")
266  .arg (QDir::toNativeSeparators (home.filePath (path)))));
267 }
268 
269 QString LeechCraft::Util::GetTemporaryName (const QString& pattern)
270 {
271  QTemporaryFile file (QDir::tempPath () + "/" + pattern);
272  file.open ();
273  QString name = file.fileName ();
274  file.close ();
275  file.remove ();
276  return name;
277 }
278 
280  const QString& location,
281  LeechCraft::TaskParameters tp,
282  const QString& mime)
283 {
284  Entity result;
285  result.Entity_ = entity;
286  result.Location_ = location;
287  result.Parameters_ = tp;
288  result.Mime_ = mime;
289  return result;
290 }
291 
293  const QString& text, Priority priority)
294 {
295  Entity result = MakeEntity (header,
296  QString (),
298  "x-leechcraft/notification");
299  result.Additional_ ["Text"] = text;
300  result.Additional_ ["Priority"] = priority;
301  return result;
302 }
303 
305 {
306  Entity e = MakeNotification (event.Entity_.toString (), QString (), PInfo_);
307  e.Additional_ ["org.LC.AdvNotifications.SenderID"] = event.Additional_ ["org.LC.AdvNotifications.SenderID"];
308  e.Additional_ ["org.LC.AdvNotifications.EventID"] = event.Additional_ ["org.LC.AdvNotifications.EventID"];
309  e.Additional_ ["org.LC.AdvNotifications.EventCategory"] = "org.LC.AdvNotifications.Cancel";
310  return e;
311 }
312 
313 LeechCraft::Entity LeechCraft::Util::MakeANCancel (const QString& senderId, const QString& eventId)
314 {
315  Entity e = MakeNotification (QString (), QString (), PInfo_);
316  e.Additional_ ["org.LC.AdvNotifications.SenderID"] = senderId;
317  e.Additional_ ["org.LC.AdvNotifications.EventID"] = eventId;
318  e.Additional_ ["org.LC.AdvNotifications.EventCategory"] = "org.LC.AdvNotifications.Cancel";
319  return e;
320 }
321 
322 QModelIndexList LeechCraft::Util::GetSummarySelectedRows (QObject *sender)
323 {
324  QAction *senderAct = qobject_cast<QAction*> (sender);
325  if (!senderAct)
326  {
327  QString debugString;
328  {
329  QDebug d (&debugString);
330  d << "sender is not a QAction*"
331  << sender;
332  }
333  throw std::runtime_error (qPrintable (debugString));
334  }
335 
336  return senderAct->
337  property ("SelectedRows").value<QList<QModelIndex>> ();
338 }
339 
340 QAction* LeechCraft::Util::CreateSeparator (QObject *parent)
341 {
342  QAction *result = new QAction (parent);
343  result->setSeparator (true);
344  return result;
345 }
346 
347 QVariantList LeechCraft::Util::GetPersistentData (const QList<QVariant>& keys,
348  QObject* object)
349 {
350  Entity e = MakeEntity (keys,
351  QString (),
352  Internal,
353  "x-leechcraft/data-persistent-load");
354  QVariantList values;
355  e.Additional_ ["Values"] = QVariant::fromValue<QVariantList*> (&values);
356 
357  QMetaObject::invokeMethod (object,
358  "delegateEntity",
359  Q_ARG (LeechCraft::Entity, e),
360  Q_ARG (int*, 0),
361  Q_ARG (QObject**, 0));
362 
363  return values;
364 }
365 
367  const QString& text, QFont font, const QPen& pen, const QBrush& brush)
368 {
369  const auto& iconSize = px.size ();
370 
371  const auto fontHeight = px.height () * 0.45;
372  font.setPixelSize (std::max (6., fontHeight));
373 
374  const QFontMetrics fm (font);
375  const auto width = fm.width (text) + 2. * px.width () / 10.;
376  const auto height = fm.height () + 2. * px.height () / 10.;
377  const bool tooSmall = width > iconSize.width ();
378 
379  const QRect textRect (iconSize.width () - width, iconSize.height () - height, width, height);
380 
381  QPainter p (&px);
382  p.setBrush (brush);
383  p.setFont (font);
384  p.setPen (pen);
385  p.setRenderHint (QPainter::Antialiasing);
386  p.setRenderHint (QPainter::TextAntialiasing);
387  p.setRenderHint (QPainter::HighQualityAntialiasing);
388  p.drawRoundedRect (textRect, 4, 4);
389  p.drawText (textRect,
390  Qt::AlignCenter,
391  tooSmall ? "#" : text);
392  p.end ();
393 
394  return px;
395 }
UTIL_API QVariantList GetPersistentData(const QList< QVariant > &keys, QObject *object)
Definition: util.cpp:347
static UTIL_API Util::IDPool< qint64 > IDPool_
Definition: structures.h:234
#define UTIL_API
Definition: utilconfig.h:37
UTIL_API QDir GetUserDir(const QString &path)
Returns the path relative to user directory.
Definition: util.cpp:252
UTIL_API QString GetLocaleName()
Returns the current locale name, like en_US.
Definition: util.cpp:189
UTIL_API QString GetTemporaryName(const QString &pattern=QString("lc_temp.XXXXXX"))
Returns a temporary filename.
Definition: util.cpp:269
UTIL_API QString MakePrettySize(qint64)
Makes a formatted size from number.
Definition: util.cpp:99
TaskParameters Parameters_
Parameters of this task.
Definition: structures.h:216
UTIL_API QDir CreateIfNotExists(const QString &path)
Creates a path if it doesn&#39;t exist.
Definition: util.cpp:233
UTIL_API QString GetLanguage()
Returns the current language name.
Definition: util.cpp:228
UTIL_API QString GetInternetLocaleName(const QLocale &)
Definition: util.cpp:216
UTIL_API QTranslator * InstallTranslator(const QString &base, const QString &prefix="leechcraft", const QString &appname="leechcraft")
Loads and installs a translator.
Definition: util.cpp:145
UTIL_API QAction * CreateSeparator(QObject *parent)
Returns the action that is set to act as a separator.
Definition: util.cpp:340
UTIL_API QString GetUserText(const Entity &entity)
Return the user-readable representation of the entity.
Definition: util.cpp:63
UTIL_API QString MakeTimeFromLong(ulong)
Makes a formatted time from number.
Definition: util.cpp:134
UTIL_API QPixmap DrawOverlayText(QPixmap px, const QString &text, QFont font, const QPen &pen, const QBrush &brush)
Definition: util.cpp:366
UTIL_API QString GetAsBase64Src(const QImage &image)
Returns the given image in a Base64-encoded form.
Definition: util.cpp:54
UTIL_API QModelIndexList GetSummarySelectedRows(QObject *sender)
Definition: util.cpp:322
QMap< QString, QVariant > Additional_
Additional parameters.
Definition: structures.h:228
UTIL_API Entity MakeANCancel(const Entity &event)
Makes an event for canceling another Advanced Notifications event.
Definition: util.cpp:304
QString Mime_
MIME type of the entity.
Definition: structures.h:212
UTIL_API Entity MakeEntity(const QVariant &entity, const QString &location, LeechCraft::TaskParameters tp, const QString &mime=QString())
An utility function to make a Entity.
Definition: util.cpp:279
QVariant Entity_
The entity that this object represents.
Definition: structures.h:176
UTIL_API Entity MakeNotification(const QString &header, const QString &text, Priority priority)
An utility function to make a Entity with notification.
Definition: util.cpp:292
Describes parameters of an entity.
Definition: structures.h:157
Q_DECLARE_METATYPE(LeechCraft::IHookProxy_ptr)
QString Location_
Source or destination.
Definition: structures.h:186