1 /*
2 * dxutils.cpp
3 *
4 * Copyright 2014 David Vachulka <arch_dvx@users.sourceforge.net>
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 3 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,
19 * MA 02110-1301, USA.
20 */
21
22 #ifdef WIN32
23 #define WIN32_LEAN_AND_MEAN
24 #include <windows.h>
25 #include <mmsystem.h>
26 #include <ctime>
27 #include <shellapi.h>
28 #endif
29 #include <QApplication>
30 #include <QColor>
31 #include <QBuffer>
32 #include <QFile>
33 #include <QDebug>
34 #include <QTime>
35 #include <QDir>
36 #include <QRegularExpression>
37 #include <QProcessEnvironment>
38 #include <QSettings>
39 #if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
40 #include <QSound>
41 #endif
42 #include <string>
43 #include <random>
44 #include "preferences.h"
45 #include "dxutils.h"
46 #include "notify/notifywindow.h"
47 #include "i18n.h"
48 #ifdef HAVE_ENCHANT
49 #include <enchant++.h>
50 #endif
51 #ifdef Q_OS_DARWIN
52 #include "widgets/macspellcheck.h"
53 #include "notify/macnotify.h"
54 #endif
55
56 #ifdef HAVE_ENCHANT
57 static enchant::Broker *ebroker;
58 typedef std::pair<Checkers*,QStringList*> CheckerPair;
enumerateDicts(const char * const lang_tag,const char * const,const char * const,const char * const,void * user_data)59 void enumerateDicts (const char * const lang_tag,
60 const char * const /*provider_name*/,
61 const char * const /*provider_desc*/,
62 const char * const /*provider_file*/,
63 void * user_data)
64 {
65 CheckerPair *chpair = (CheckerPair*)user_data;
66 const Checkers &checkers = *chpair->first;
67 QStringList &spellLang = *(chpair->second);
68 if(checkers.find(lang_tag) == checkers.end())
69 spellLang.append(lang_tag);
70 }
71 #endif
72
73 #ifdef Q_OS_DARWIN
74 static MacSpellCheck *_instance;
75 #endif
76
caseInsensitiveLessThan(const QString & s1,const QString & s2)77 bool caseInsensitiveLessThan(const QString &s1, const QString &s2)
78 {
79 return s1.toLower() < s2.toLower();
80 }
81
dxutils()82 dxutils::dxutils()
83 {
84 m_notifiesHeight = 0;
85 m_notifyPosition = -1;
86 m_firstNotify = false;
87 m_haveNotify = false;
88 #ifndef WIN32
89 QDir dir;
90 QStringList paths = QString(getenv("PATH")).split(':');
91 foreach(QString path, paths)
92 {
93 if(dir.exists(path+"/notify-send"))
94 {
95 m_haveNotify = true;
96 break;
97 }
98 }
99 #endif // WIN32
100 #ifdef Q_OS_DARWIN
101 m_haveNotify = false; //I think notifywindow is better than native notify
102 #endif
103 #ifdef HAVE_ENCHANT
104 #ifdef HAVE_ENCHANT2
105 ebroker = new enchant::Broker();
106 #else
107 ebroker = enchant::Broker::instance();
108 #endif //HAVE_ENCHANT2
109 #endif //HAVE_ENCHANT
110 }
111
~dxutils()112 dxutils::~dxutils()
113 {
114 #ifdef HAVE_ENCHANT
115 Checkers::const_iterator it = m_checkers.begin();
116 for(; it != m_checkers.end(); it++)
117 {
118 delete (*it).second;
119 }
120 #endif
121 #ifdef HAVE_ENCHANT2
122 delete ebroker;
123 #endif
124 }
125
instance()126 dxutils &dxutils::instance()
127 {
128 static dxutils idxutils;
129 return idxutils;
130 }
131
isBadchar(char c)132 bool dxutils::isBadchar(char c)
133 {
134 switch(c) {
135 case ' ':
136 case ',':
137 case '\0':
138 case '\02':
139 case '\03':
140 case '\017':
141 case '\021':
142 case '\026':
143 case '\035':
144 case '\037':
145 case '\n':
146 case '\r':
147 case '<':
148 case '>':
149 case '"':
150 case '\'':
151 return true;
152 default:
153 return false;
154 }
155 }
156
157 // checks is char nick/word delimiter
isDelimiter(char c)158 bool dxutils::isDelimiter(char c)
159 {
160 switch(c) {
161 case ' ':
162 case '.':
163 case ',':
164 case '/':
165 case '\\':
166 case '`':
167 case '\'':
168 case '!':
169 case '(':
170 case ')':
171 case '{':
172 case '}':
173 case '|':
174 case '[':
175 case ']':
176 case '\"':
177 case ':':
178 case ';':
179 case '<':
180 case '>':
181 case '?':
182 return true;
183 default:
184 return false;
185 }
186 }
187
188 //Return file size in human readable form
getFileSize(quint64 size)189 QString dxutils::getFileSize(quint64 size)
190 {
191 double fsize = 0.0;
192 if(size > 1000000000)
193 {
194 fsize = size/1073741824.0;
195 return QString("%1 %2").arg(fsize, 0, 'f', 2).arg(_("GB"));
196 }
197 if(size > 100000)
198 {
199 fsize = size/1048576.0;
200 return QString("%1 %2").arg(fsize, 0, 'f', 2).arg(_("MB"));
201 }
202 if(size > 1000)
203 {
204 fsize = size/1024.0;
205 return QString("%1 %2").arg(fsize, 0, 'f', 2).arg(_("KB"));
206 }
207 return QString("%1 %2").arg(size).arg(_("bytes"));
208 }
209
getFileSize(const QString & ssize)210 QString dxutils::getFileSize(const QString& ssize)
211 {
212 return getFileSize(ssize.toLongLong());
213 }
214
215 //std::string to QString
fromStdString(const std::string & str)216 QString dxutils::fromStdString(const std::string &str)
217 {
218 return QString::fromUtf8(str.c_str());
219 }
220
221 //QString to std::string
toStdString(const QString & str)222 std::string dxutils::toStdString(const QString &str)
223 {
224 return str.toUtf8().constData();
225 }
226
getNickColor(const QString & nick)227 QString dxutils::getNickColor(const QString &nick)
228 {
229 int len = nick.length();
230 quint32 h = 0;
231 for(int i=0; i<len; i++)
232 h = ((h << 5) + h) ^ nick[i].toLatin1();
233 switch(h%8)
234 {
235 case 0: return QColor(196,160,0).name();
236 case 1: return QColor(206,92,0).name();
237 case 2: return QColor(143,89,2).name();
238 case 3: return QColor(78,154,6).name();
239 case 4: return QColor(32,74,135).name();
240 case 5: return QColor(117,80,123).name();
241 case 6: return QColor(164,0,0).name();
242 default: return QColor(85,87,83).name();
243 }
244 }
245
246 /*Return download/send speed in human readable form
247 * speed = difference between two position during 1 second
248 */
getSpeed(quint64 speed)249 QString dxutils::getSpeed(quint64 speed)
250 {
251 double fspeed = 0.0;
252 if(speed > 100000)
253 {
254 fspeed = speed/(1048576.0);
255 return _("%1 MB/s").arg(fspeed, 0, 'f', 2);
256 }
257 fspeed = speed/(1024.0);
258 return _("%1 KB/s").arg(fspeed, 0, 'f', 2);
259 }
260
261 //Return remaining time of download/send
getRemaining(quint64 size,quint64 speed)262 QString dxutils::getRemaining(quint64 size, quint64 speed)
263 {
264 if(!speed) return "?";
265 quint64 remainingTime = size/speed;
266 if(remainingTime <= 0 || remainingTime > 54000) return "?";
267 else
268 {
269 quint64 secs = remainingTime;
270 quint64 hours = remainingTime/3600;
271 secs -= hours*3600;
272 quint64 mins = secs/60;
273 secs -= mins*60;
274 return QString("%1:%2:%3").arg(hours).arg(mins, 2, 10, QLatin1Char('0')).arg(secs, 2, 10, QLatin1Char('0'));
275 }
276 }
277
278 #ifdef Q_OS_DARWIN
showNotify(QString text,int position)279 void dxutils::showNotify(QString text, int position)
280 {
281 //I think notifywindow is better than native notify
282 // MacNotify::instance()->showNotify(text);
283 text.replace("\n", "<br>");
284 if(!m_firstNotify || position!=m_notifyPosition)
285 {
286 m_firstNotify = true;
287 m_notifiesHeight = 0;
288 m_notifyPosition = position;
289 }
290 NotifyWindow *notify = new NotifyWindow(text, m_notifiesHeight, 5);
291 notify->showNotify(position);
292 m_notifiesHeight += notify->height()+4;
293 }
294 #else
showNotify(QString text,int position)295 void dxutils::showNotify(QString text, int position)
296 {
297 if(m_haveNotify)
298 {
299 QString exec = QString("notify-send -i %1 dxirc '%2'").arg(dxutils::getDataPath()+"/icons/big_dxirc.png").arg(text);
300 system(exec.toUtf8().constData());
301 }
302 else
303 {
304 text.replace("\n", "<br>");
305 if(!m_firstNotify || position!=m_notifyPosition)
306 {
307 m_firstNotify = true;
308 m_notifiesHeight = 0;
309 m_notifyPosition = position;
310 }
311 NotifyWindow *notify = new NotifyWindow(text, m_notifiesHeight, 5);
312 notify->showNotify(position);
313 m_notifiesHeight += notify->height()+4;
314 }
315 }
316 #endif
317
removeNotify()318 void dxutils::removeNotify()
319 {
320 if(m_firstNotify)
321 m_firstNotify = !m_firstNotify;
322 }
323
debugLine(const QString & line)324 void dxutils::debugLine(const QString &line)
325 {
326 #ifdef DEBUG
327 qDebug() << QTime::currentTime().toString("[hh:mm:ss] ") << line;
328 #endif
329 }
330
331 //is file with name on path right dxirc log file?
isRightLogFile(const QString & path,const QString & name)332 bool dxutils::isRightLogFile(const QString& path, const QString& name)
333 {
334 if(QRegularExpression("^\\d\\d\\d\\d-\\d\\d-\\d\\d+$").match(name).hasMatch())
335 {
336 QFile file(path);
337 if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
338 return false;
339 char buf[22];
340 qint64 lineLength = file.readLine(buf, sizeof(buf));
341 if(lineLength != -1)
342 {
343 QRegularExpression ex("^\\[\\d\\d:\\d\\d:\\d\\d\\] ");
344 if(ex.match(QString(buf)).hasMatch())
345 return true;
346 else
347 return false;
348 }
349 else
350 return false;
351 }
352 return false;
353 }
354
355 //get month string
getMonth(int month)356 QString dxutils::getMonth(int month)
357 {
358 switch(month) {
359 case 1: return _("January");
360 case 2: return _("February");
361 case 3: return _("March");
362 case 4: return _("April");
363 case 5: return _("May");
364 case 6: return _("June");
365 case 7: return _("July");
366 case 8: return _("August");
367 case 9: return _("September");
368 case 10: return _("October");
369 case 11: return _("November");
370 case 12: return _("December");
371 default: return "Rok ma jen 12 mesicu:)";
372 }
373 }
374
375 //get month string-number for name
getMonthNumber(const QString & month)376 QString dxutils::getMonthNumber(const QString& month)
377 {
378 if(month==_("January")) return "01";
379 else if(month==_("February")) return "02";
380 else if(month==_("March")) return "03";
381 else if(month==_("April")) return "04";
382 else if(month==_("May")) return "05";
383 else if(month==_("June")) return "06";
384 else if(month==_("July")) return "07";
385 else if(month==_("August")) return "08";
386 else if(month==_("September")) return "09";
387 else if(month==_("October")) return "10";
388 else if(month==_("November")) return "11";
389 else if(month==_("December")) return "12";
390 return "00";
391 }
392
playFile(const QString & file)393 void dxutils::playFile(const QString &file)
394 {
395 QDir dir;
396 if(dir.exists(file))
397 {
398 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
399 #ifdef _WIN32
400 PlaySoundA((LPCSTR)file.toUtf8().constData(), NULL, SND_FILENAME | SND_ASYNC);
401 #else
402 static const char * players[]={"aplay","play","esdplay","artsplay","ossplay",NULL};
403 QString exec;
404 QStringList paths = QString(getenv("PATH")).split(':');
405 foreach(QString path, paths)
406 {
407 for(int i=0; players[i]!=NULL; i++)
408 {
409 if(dir.exists(path+"/"+players[i]))
410 {
411 exec = path+"/"+players[i];
412 break;
413 }
414 }
415 }
416 if(exec.isEmpty()) return;
417 if(exec.contains("aplay")) exec += " -q";
418 exec += " "+enquote(file)+" &";
419 system(exec.toUtf8().constData());
420 #endif
421 #else
422 QSound::play(file);
423 #endif
424 }
425 }
426
createSmileys(QString text)427 QString dxutils::createSmileys(QString text)
428 {
429 for(QMap<QString,QString>::const_iterator it=preferences.m_smileysMap.constBegin(); it!=preferences.m_smileysMap.constEnd(); it++)
430 {
431 if(text.contains(it.key()))
432 {
433 text.replace(it.key(), "<img src='"+it.value()+"'>");
434 }
435 }
436 return text;
437 }
438
439 //check path for nick icons
checkThemePath(const QString & path)440 QString dxutils::checkThemePath(const QString &path)
441 {
442 if(path == "internal") return path;
443 QString themeDefaultPath = "internal";
444 if(QFileInfo(path+"/irc_normal.png").exists()) return path;
445 return themeDefaultPath;
446 }
447
448 //check path list for nick icons
checkThemesList(const QString & list)449 QString dxutils::checkThemesList(const QString &list)
450 {
451 QString themeDefaultPath = "internal;";
452 QString themes;
453 #if QT_VERSION < QT_VERSION_CHECK(5,15,0)
454 QStringList pathes = list.split(';', QString::SkipEmptyParts);
455 #else
456 QStringList pathes = list.split(';', Qt::SkipEmptyParts);
457 #endif
458 for(int i=0; i<pathes.size(); ++i)
459 {
460 if(QFileInfo(pathes[i]+"/irc_normal.png").exists()) themes.append(pathes[i]+";");
461 }
462 if(!themes.contains(themeDefaultPath)) themes.prepend(themeDefaultPath);
463 if(!themes.isEmpty()) return themes;
464 return themeDefaultPath;
465 }
466
haveNotify()467 bool dxutils::haveNotify()
468 {
469 return m_haveNotify;
470 }
471
encrypt(const QString & text)472 QString dxutils::encrypt(const QString &text)
473 {
474 QString result = "";
475 const std::string CHARACTERS = "0123456789!@#$%^&*ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
476 std::random_device random_device;
477 std::mt19937 generator(random_device());
478 std::uniform_int_distribution<> distribution(0, CHARACTERS.size() - 1);
479 for(int i=0; i<text.length(); i++)
480 {
481 result += text[i];
482 result += CHARACTERS[distribution(generator)];
483 }
484 return result;
485 }
486
decrypt(const QString & text)487 QString dxutils::decrypt(const QString &text)
488 {
489 QString result = "";
490 for(int i=0; i<text.length(); i++)
491 {
492 if((i+1)%2) result += text[i];
493 }
494 return result;
495 }
496
getParam(QString toParse,int n,bool toEnd)497 QString dxutils::getParam(QString toParse, int n, bool toEnd)
498 {
499 return getParam(toParse, n, toEnd, ' ');
500 }
501
getParam(QString toParse,int n,bool toEnd,const char & separator)502 QString dxutils::getParam(QString toParse, int n, bool toEnd, const char &separator)
503 {
504 if(toEnd)
505 {
506 return toParse.section(separator, n-1);
507 }
508 else
509 {
510 QString result = toParse.section(separator, n-1, n-1);
511 if(result.isEmpty()) return toParse.section(separator, -1);
512 else return result;
513 }
514 }
515
removeSpaces(const QString & text)516 QString dxutils::removeSpaces(const QString &text)
517 {
518 if(text.contains(' '))
519 {
520 QString removed;
521 for(int i=0; i<=text.length(); i++)
522 {
523 if(text[i].toLatin1() != 32)
524 removed += text[i];
525 }
526 return removed;
527 }
528 else
529 return text;
530 }
531
removeNonalphanumeric(const QString & text)532 QString dxutils::removeNonalphanumeric(const QString &text)
533 {
534 QString result;
535 for(int i=0; i<text.length(); i++)
536 {
537 if((47<text[i].toLatin1()&&text[i].toLatin1()<58) ||
538 (64<text[i].toLatin1()&&text[i].toLatin1()<91) ||
539 (96<text[i].toLatin1()&&text[i].toLatin1()<123))
540 result += text[i];
541 else
542 result += '0';
543 }
544 return result;
545 }
546
createModes(char sign,char mode,QString nicks)547 QString dxutils::createModes(char sign, char mode, QString nicks)
548 {
549 QString modes;
550 modes += sign;
551 QString tomode;
552 if(!nicks.contains(' ')) return modes+mode+" "+nicks;
553 if(nicks.right(1) != " ") nicks.append(" ");
554 while(nicks.contains(' '))
555 {
556 modes += mode;
557 tomode += nicks.section(' ',0,0)+" ";
558 nicks = nicks.section(' ',1);
559 }
560 return modes+" "+tomode;
561 }
562
563 //from kde source, thx
isUtf8(const char * buf)564 bool dxutils::isUtf8(const char *buf)
565 {
566 int i, n;
567 unsigned char c;
568 bool gotone = false;
569 if (!buf)
570 return true; // whatever, just don't crash
571
572 #define F 0 /* character never appears in text */
573 #define T 1 /* character appears in plain ASCII text */
574 #define I 2 /* character appears in ISO-8859 text */
575 #define X 3 /* character appears in non-ISO extended ASCII (Mac, IBM PC) */
576
577 static const unsigned char text_chars[256] = {
578 /* BEL BS HT LF FF CR */
579 F, F, F, F, F, F, F, T, T, T, T, F, T, T, F, F, /* 0x0X */
580 /* ESC */
581 F, F, F, F, F, F, F, F, F, F, F, T, F, F, F, F, /* 0x1X */
582 T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x2X */
583 T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x3X */
584 T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x4X */
585 T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x5X */
586 T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x6X */
587 T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, F, /* 0x7X */
588 /* NEL */
589 X, X, X, X, X, T, X, X, X, X, X, X, X, X, X, X, /* 0x8X */
590 X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, /* 0x9X */
591 I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xaX */
592 I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xbX */
593 I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xcX */
594 I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xdX */
595 I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xeX */
596 I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I /* 0xfX */
597 };
598
599 /* *ulen = 0; */
600 for (i = 0; (c = buf[i]); i++)
601 {
602 if ((c & 0x80) == 0) /* 0xxxxxxx is plain ASCII */
603 {
604 /*
605 * Even if the whole file is valid UTF-8 sequences,
606 * still reject it if it uses weird control characters.
607 */
608
609 if (text_chars[c] != T)
610 return false;
611
612 }
613 else if ((c & 0x40) == 0) /* 10xxxxxx never 1st byte */
614 {
615 return false;
616 }
617 else /* 11xxxxxx begins UTF-8 */
618 {
619 int following;
620
621 if ((c & 0x20) == 0) { /* 110xxxxx */
622 following = 1;
623 }
624 else if ((c & 0x10) == 0) { /* 1110xxxx */
625 following = 2;
626 }
627 else if ((c & 0x08) == 0) { /* 11110xxx */
628 following = 3;
629 }
630 else if ((c & 0x04) == 0) { /* 111110xx */
631 following = 4;
632 }
633 else if ((c & 0x02) == 0) { /* 1111110x */
634 following = 5;
635 }
636 else
637 return false;
638
639 for (n = 0; n < following; n++) {
640 i++;
641 if (!(c = buf[i]))
642 goto done;
643
644 if ((c & 0x80) == 0 || (c & 0x40))
645 return false;
646 }
647 gotone = true;
648 }
649 }
650 done:
651 return gotone; /* don't claim it's UTF-8 if it's all 7-bit */
652 }
653
654 //get default spellchecking language
655 #ifdef HAVE_ENCHANT
getDefaultLang()656 QString dxutils::getDefaultLang()
657 {
658 if(m_locale.isEmpty()) getLocale();
659 if(m_checkers.find(m_locale) != m_checkers.end())
660 return m_locale;
661 Checkers::const_iterator it = m_checkers.begin();
662 QString language = m_locale.section('_',0,0);
663 for(; it != m_checkers.end(); it++)
664 {
665 if(QString::compare((*it).first.section('_',0,0),language)==0) return language;
666 }
667 if(m_availableSpellLangs.size()) return m_availableSpellLangs[0];
668 else return "";
669 }
670 #else
getDefaultLang()671 QString dxutils::getDefaultLang()
672 {
673 if(m_locale.isEmpty()) getLocale();
674 return m_locale;
675 }
676 #endif
677
678 //return locale, e.g cs_CZ etc.
getLocale()679 QString dxutils::getLocale()
680 {
681 if(!m_locale.isEmpty())
682 return m_locale;
683 #ifdef WIN32
684 LCID lcid = GetUserDefaultLCID();
685 if(lcid!=0)
686 {
687 quint32 localeid = LANGIDFROMLCID(lcid);
688 /* locale code from this page
689 * http://msdn.microsoft.com/en-us/library/dd318693%28v=VS.85%29.aspx
690 * not fully implemented
691 */
692 switch(localeid){
693 case 0x0436: m_locale = "af_ZA";break; // Afrikaans
694 case 0x041c: m_locale = "sq_AL";break; // Albanian
695 case 0x0401: m_locale = "ar_SA";break; // Arabic - Saudi Arabia
696 case 0x0801: m_locale = "ar_IQ";break; // Arabic - Iraq
697 case 0x0c01: m_locale = "ar_EG";break; // Arabic - Egypt
698 case 0x1001: m_locale = "ar_LY";break; // Arabic - Libya
699 case 0x1401: m_locale = "ar_DZ";break; // Arabic - Algeria
700 case 0x1801: m_locale = "ar_MA";break; // Arabic - Morocco
701 case 0x1c01: m_locale = "ar_TN";break; // Arabic - Tunisia
702 case 0x2001: m_locale = "ar_OM";break; // Arabic - Oman
703 case 0x2401: m_locale = "ar_YE";break; // Arabic - Yemen
704 case 0x2801: m_locale = "ar_SY";break; // Arabic - Syria
705 case 0x2c01: m_locale = "ar_JO";break; // Arabic - Jordan
706 case 0x3001: m_locale = "ar_LB";break; // Arabic - Lebanon
707 case 0x3401: m_locale = "ar_KW";break; // Arabic - Kuwait
708 case 0x3801: m_locale = "ar_AE";break; // Arabic - United Arab Emirates
709 case 0x3c01: m_locale = "ar_BH";break; // Arabic - Bahrain
710 case 0x4001: m_locale = "ar_QA";break; // Arabic - Qatar
711 case 0x042b: m_locale = "hy_AM";break; // Armenian
712 case 0x042c: m_locale = "az_AZ";break; // Azeri Latin
713 case 0x082c: m_locale = "az_AZ";break; // Azeri - Cyrillic
714 case 0x042d: m_locale = "eu_ES";break; // Basque
715 case 0x0423: m_locale = "be_BY";break; // Belarusian
716 case 0x0445: m_locale = "bn_IN";break; // Begali
717 case 0x201a: m_locale = "bs_BA";break; // Bosnian
718 case 0x141a: m_locale = "bs_BA";break; // Bosnian - Cyrillic
719 case 0x047e: m_locale = "br_FR";break; // Breton - France
720 case 0x0402: m_locale = "bg_BG";break; // Bulgarian
721 case 0x0403: m_locale = "ca_ES";break; // Catalan
722 case 0x0004: m_locale = "zh_CHS";break; // Chinese - Simplified
723 case 0x0404: m_locale = "zh_TW";break; // Chinese - Taiwan
724 case 0x0804: m_locale = "zh_CN";break; // Chinese - PRC
725 case 0x0c04: m_locale = "zh_HK";break; // Chinese - Hong Kong S.A.R.
726 case 0x1004: m_locale = "zh_SG";break; // Chinese - Singapore
727 case 0x1404: m_locale = "zh_MO";break; // Chinese - Macao S.A.R.
728 case 0x7c04: m_locale = "zh_CHT";break; // Chinese - Traditional
729 case 0x041a: m_locale = "hr_HR";break; // Croatian
730 case 0x101a: m_locale = "hr_BA";break; // Croatian - Bosnia
731 case 0x0405: m_locale = "cs_CZ";break; // Czech
732 case 0x0406: m_locale = "da_DK";break; // Danish
733 case 0x048c: m_locale = "gbz_AF";break; // Dari - Afghanistan
734 case 0x0465: m_locale = "div_MV";break; // Divehi - Maldives
735 case 0x0413: m_locale = "nl_NL";break; // Dutch - The Netherlands
736 case 0x0813: m_locale = "nl_BE";break; // Dutch - Belgium
737 case 0x0409: m_locale = "en_US";break; // English - United States
738 case 0x0809: m_locale = "en_GB";break; // English - United Kingdom
739 case 0x0c09: m_locale = "en_AU";break; // English - Australia
740 case 0x1009: m_locale = "en_CA";break; // English - Canada
741 case 0x1409: m_locale = "en_NZ";break; // English - New Zealand
742 case 0x1809: m_locale = "en_IE";break; // English - Ireland
743 case 0x1c09: m_locale = "en_ZA";break; // English - South Africa
744 case 0x2009: m_locale = "en_JA";break; // English - Jamaica
745 case 0x2409: m_locale = "en_CB";break; // English - Carribbean
746 case 0x2809: m_locale = "en_BZ";break; // English - Belize
747 case 0x2c09: m_locale = "en_TT";break; // English - Trinidad
748 case 0x3009: m_locale = "en_ZW";break; // English - Zimbabwe
749 case 0x3409: m_locale = "en_PH";break; // English - Phillippines
750 case 0x0425: m_locale = "et_EE";break; // Estonian
751 case 0x0438: m_locale = "fo_FO";break; // Faroese
752 case 0x0464: m_locale = "fil_PH";break; // Filipino
753 case 0x040b: m_locale = "fi_FI";break; // Finnish
754 case 0x040c: m_locale = "fr_FR";break; // French - France
755 case 0x080c: m_locale = "fr_BE";break; // French - Belgium
756 case 0x0c0c: m_locale = "fr_CA";break; // French - Canada
757 case 0x100c: m_locale = "fr_CH";break; // French - Switzerland
758 case 0x140c: m_locale = "fr_LU";break; // French - Luxembourg
759 case 0x180c: m_locale = "fr_MC";break; // French - Monaco
760 case 0x0462: m_locale = "fy_NL";break; // Frisian - Netherlands
761 case 0x0456: m_locale = "gl_ES";break; // Galician
762 case 0x0437: m_locale = "ka_GE";break; // Georgian
763 case 0x0407: m_locale = "de_DE";break; // German - Germany
764 case 0x0807: m_locale = "de_CH";break; // German - Switzerland
765 case 0x0c07: m_locale = "de_AT";break; // German - Austria
766 case 0x1007: m_locale = "de_LU";break; // German - Luxembourg
767 case 0x1407: m_locale = "de_LI";break; // German - Liechtenstein
768 case 0x0408: m_locale = "el_GR";break; // Greek
769 case 0x0447: m_locale = "gu_IN";break; // Gujarati
770 case 0x040d: m_locale = "he_IL";break; // Hebrew
771 case 0x0439: m_locale = "hi_IN";break; // Hindi
772 case 0x040e: m_locale = "hu_HU";break; // Hungarian
773 case 0x040f: m_locale = "is_IS";break; // Icelandic
774 case 0x0421: m_locale = "id_ID";break; // Indonesian
775 case 0x045d: m_locale = "iu_CA";break; // Inuktitut
776 case 0x085d: m_locale = "iu_CA";break; // Inuktitut - Latin
777 case 0x083c: m_locale = "ga_IE";break; // Irish - Ireland
778 case 0x0434: m_locale = "xh_ZA";break; // Xhosa - South Africa
779 case 0x0435: m_locale = "zu_ZA";break; // Zulu
780 case 0x0410: m_locale = "it_IT";break; // Italian - Italy
781 case 0x0810: m_locale = "it_CH";break; // Italian - Switzerland
782 case 0x0411: m_locale = "ja_JP";break; // Japanese
783 case 0x044b: m_locale = "kn_IN";break; // Kannada - India
784 case 0x043f: m_locale = "kk_KZ";break; // Kazakh
785 case 0x0457: m_locale = "kok_IN";break; // Konkani
786 case 0x0412: m_locale = "ko_KR";break; // Korean
787 case 0x0440: m_locale = "ky_KG";break; // Kyrgyz
788 case 0x0426: m_locale = "lv_LV";break; // Latvian
789 case 0x0427: m_locale = "lt_LT";break; // Lithuanian
790 case 0x046e: m_locale = "lb_LU";break; // Luxembourgish
791 case 0x042f: m_locale = "mk_MK";break; // FYRO Macedonian
792 case 0x043e: m_locale = "ms_MY";break; // Malay - Malaysia
793 case 0x083e: m_locale = "ms_BN";break; // Malay - Brunei
794 case 0x044c: m_locale = "ml_IN";break; // Malayalam - India
795 case 0x043a: m_locale = "mt_MT";break; // Maltese
796 case 0x0481: m_locale = "mi_NZ";break; // Maori
797 case 0x047a: m_locale = "arn_CL";break; // Mapudungun
798 case 0x044e: m_locale = "mr_IN";break; // Marathi
799 case 0x047c: m_locale = "moh_CA";break; // Mohawk - Canada
800 case 0x0450: m_locale = "mn_MN";break; // Mongolian
801 case 0x0461: m_locale = "ne_NP";break; // Nepali
802 case 0x0414: m_locale = "nb_NO";break; // Norwegian - Bokmal
803 case 0x0814: m_locale = "nn_NO";break; // Norwegian - Nynorsk
804 case 0x0482: m_locale = "oc_FR";break; // Occitan - France
805 case 0x0448: m_locale = "or_IN";break; // Oriya - India
806 case 0x0463: m_locale = "ps_AF";break; // Pashto - Afghanistan
807 case 0x0429: m_locale = "fa_IR";break; // Persian
808 case 0x0415: m_locale = "pl_PL";break; // Polish
809 case 0x0416: m_locale = "pt_BR";break; // Portuguese - Brazil
810 case 0x0816: m_locale = "pt_PT";break; // Portuguese - Portugal
811 case 0x0446: m_locale = "pa_IN";break; // Punjabi
812 case 0x046b: m_locale = "quz_BO";break; // Quechua (Bolivia)
813 case 0x086b: m_locale = "quz_EC";break; // Quechua (Ecuador)
814 case 0x0c6b: m_locale = "quz_PE";break; // Quechua (Peru)
815 case 0x0418: m_locale = "ro_RO";break; // Romanian - Romania
816 case 0x0417: m_locale = "rm_CH";break; // Raeto-Romanese
817 case 0x0419: m_locale = "ru_RU";break; // Russian
818 case 0x243b: m_locale = "smn_FI";break; // Sami Finland
819 case 0x103b: m_locale = "smj_NO";break; // Sami Norway
820 case 0x143b: m_locale = "smj_SE";break; // Sami Sweden
821 case 0x043b: m_locale = "se_NO";break; // Sami Northern Norway
822 case 0x083b: m_locale = "se_SE";break; // Sami Northern Sweden
823 case 0x0c3b: m_locale = "se_FI";break; // Sami Northern Finland
824 case 0x203b: m_locale = "sms_FI";break; // Sami Skolt
825 case 0x183b: m_locale = "sma_NO";break; // Sami Southern Norway
826 case 0x1c3b: m_locale = "sma_SE";break; // Sami Southern Sweden
827 case 0x044f: m_locale = "sa_IN";break; // Sanskrit
828 case 0x0c1a: m_locale = "sr_SP";break; // Serbian - Cyrillic
829 case 0x1c1a: m_locale = "sr_BA";break; // Serbian - Bosnia Cyrillic
830 case 0x081a: m_locale = "sr_SP";break; // Serbian - Latin
831 case 0x181a: m_locale = "sr_BA";break; // Serbian - Bosnia Latin
832 case 0x046c: m_locale = "ns_ZA";break; // Northern Sotho
833 case 0x0432: m_locale = "tn_ZA";break; // Setswana - Southern Africa
834 case 0x041b: m_locale = "sk_SK";break; // Slovak
835 case 0x0424: m_locale = "sl_SI";break; // Slovenian
836 case 0x040a: m_locale = "es_ES";break; // Spanish - Spain
837 case 0x080a: m_locale = "es_MX";break; // Spanish - Mexico
838 case 0x0c0a: m_locale = "es_ES";break; // Spanish - Spain (Modern)
839 case 0x100a: m_locale = "es_GT";break; // Spanish - Guatemala
840 case 0x140a: m_locale = "es_CR";break; // Spanish - Costa Rica
841 case 0x180a: m_locale = "es_PA";break; // Spanish - Panama
842 case 0x1c0a: m_locale = "es_DO";break; // Spanish - Dominican Republic
843 case 0x200a: m_locale = "es_VE";break; // Spanish - Venezuela
844 case 0x240a: m_locale = "es_CO";break; // Spanish - Colombia
845 case 0x280a: m_locale = "es_PE";break; // Spanish - Peru
846 case 0x2c0a: m_locale = "es_AR";break; // Spanish - Argentina
847 case 0x300a: m_locale = "es_EC";break; // Spanish - Ecuador
848 case 0x340a: m_locale = "es_CL";break; // Spanish - Chile
849 case 0x380a: m_locale = "es_UR";break; // Spanish - Uruguay
850 case 0x3c0a: m_locale = "es_PY";break; // Spanish - Paraguay
851 case 0x400a: m_locale = "es_BO";break; // Spanish - Bolivia
852 case 0x440a: m_locale = "es_SV";break; // Spanish - El Salvador
853 case 0x480a: m_locale = "es_HN";break; // Spanish - Honduras
854 case 0x4c0a: m_locale = "es_NI";break; // Spanish - Nicaragua
855 case 0x500a: m_locale = "es_PR";break; // Spanish - Puerto Rico
856 case 0x0441: m_locale = "sw_KE";break; // Swahili
857 case 0x041d: m_locale = "sv_SE";break; // Swedish - Sweden
858 case 0x081d: m_locale = "sv_FI";break; // Swedish - Finland
859 case 0x045a: m_locale = "syr_SY";break; // Syriac
860 case 0x0449: m_locale = "ta_IN";break; // Tamil
861 case 0x0444: m_locale = "tt_RU";break; // Tatar
862 case 0x044a: m_locale = "te_IN";break; // Telugu
863 case 0x041e: m_locale = "th_TH";break; // Thai
864 case 0x041f: m_locale = "tr_TR";break; // Turkish
865 case 0x0422: m_locale = "uk_UA";break; // Ukrainian
866 case 0x0420: m_locale = "ur_PK";break; // Urdu
867 case 0x0820: m_locale = "ur_IN";break; // Urdu - India
868 case 0x0443: m_locale = "uz_UZ";break; // Uzbek - Latin
869 case 0x0843: m_locale = "uz_UZ";break; // Uzbek - Cyrillic
870 case 0x042a: m_locale = "vi_VN";break; // Vietnamese
871 case 0x0452: m_locale = "cy_GB";break; // Welsh
872 default: m_locale = "en_US";
873 }
874 }
875 else m_locale = "en_US";
876 #else
877 if(!QProcessEnvironment::systemEnvironment().value("LANG").isEmpty()) m_locale = QProcessEnvironment::systemEnvironment().value("LANG");
878 else if(!QProcessEnvironment::systemEnvironment().value("LC_ALL").isEmpty()) m_locale = QProcessEnvironment::systemEnvironment().value("LC_ALL");
879 else if(!QProcessEnvironment::systemEnvironment().value("LC_MESSAGES").isEmpty()) m_locale = QProcessEnvironment::systemEnvironment().value("LC_MESSAGES");
880 else m_locale = "en_US";
881 if(m_locale == "C" || m_locale == "POSIX")
882 {
883 m_locale = "en_US";
884 }
885 m_locale = m_locale.section('.',0,0).section('@',0,0);
886 #endif
887 return m_locale;
888 }
889
loadAlias()890 void dxutils::loadAlias()
891 {
892 QSettings set(preferences.getIniFile(), QSettings::IniFormat);
893 set.beginGroup("ALIASES");
894 int num = set.value("number", 0).toInt();
895 m_aliases.clear();
896 if(num)
897 {
898 for(int i=0; i<num; i++)
899 {
900 QString key, value;
901 key = set.value(QString("key%1").arg(i), "").toString();
902 value = set.value(QString("value%1").arg(i), "").toString();
903 if(!key.isEmpty() && !value.isEmpty())
904 m_aliases.insert(key, value);
905 }
906 }
907 set.endGroup();
908 fillCommands();
909 }
910
setAliases(QMap<QString,QString> a)911 void dxutils::setAliases(QMap<QString,QString> a)
912 {
913 m_aliases = a;
914 fillCommands();
915 }
916
getAlias(QString key)917 QString dxutils::getAlias(QString key)
918 {
919 if(m_aliases.count(key.toLower())>0)
920 return m_aliases.find(key).value();
921 return "";
922 }
923
getAliases()924 QMap<QString,QString> dxutils::getAliases()
925 {
926 return m_aliases;
927 }
928
fillCommands()929 void dxutils::fillCommands()
930 {
931 m_commands.clear();
932 m_dcccommands.clear();
933 m_commands.append("ADMIN");
934 m_commands.append("AWAY");
935 m_commands.append("BANLIST");
936 m_commands.append("BOATS");
937 m_commands.append("CONNECT");
938 m_commands.append("COMMANDS");
939 m_dcccommands.append("COMMANDS");
940 m_commands.append("CTCP");
941 m_commands.append("CYCLE");
942 m_commands.append("DCC");
943 m_commands.append("DEOP");
944 m_commands.append("DEVOICE");
945 m_commands.append("DISCONNECT");
946 m_commands.append("EXEC");
947 m_dcccommands.append("EXEC");
948 m_commands.append("HELP");
949 m_dcccommands.append("HELP");
950 m_commands.append("IGNORE");
951 m_commands.append("INVITE");
952 m_commands.append("JOIN");
953 m_commands.append("KICK");
954 m_commands.append("KILL");
955 m_commands.append("LIST");
956 m_commands.append("LOG");
957 m_dcccommands.append("LOG");
958 #ifdef HAVE_LUA
959 m_commands.append("LUA");
960 m_dcccommands.append("LUA");
961 #endif
962 m_commands.append("ME");
963 m_dcccommands.append("ME");
964 m_commands.append("MODE");
965 m_commands.append("MSG");
966 m_commands.append("NAMES");
967 m_commands.append("NICK");
968 m_commands.append("NOTICE");
969 m_commands.append("OP");
970 m_commands.append("OPER");
971 m_commands.append("PART");
972 m_commands.append("QUERY");
973 m_commands.append("QUIT");
974 m_commands.append("QUOTE");
975 m_commands.append("SAY");
976 m_dcccommands.append("SAY");
977 m_commands.append("STATS");
978 m_commands.append("TIME");
979 m_commands.append("TOPIC");
980 m_commands.append("VOICE");
981 m_commands.append("WALLOPS");
982 m_commands.append("WHO");
983 m_commands.append("WHOAMI");
984 m_commands.append("WHOIS");
985 m_commands.append("WHOWAS");
986 QMap<QString,QString>::iterator it;
987 for(it=m_aliases.begin(); it!=m_aliases.end(); it++)
988 {
989 m_commands.append(it.key().section('/',1));
990 }
991 for(int i=0; i<m_scriptCommands.size(); i++)
992 {
993 m_commands.append(m_scriptCommands[i].name);
994 m_dcccommands.append(m_scriptCommands[i].name);
995 }
996 std::sort(m_commands.begin(), m_commands.end(), caseInsensitiveLessThan);
997 std::sort(m_dcccommands.begin(), m_dcccommands.end(), caseInsensitiveLessThan);
998 }
999
commandsNo()1000 int dxutils::commandsNo()
1001 {
1002 return m_commands.size();
1003 }
1004
commandsAt(int i)1005 QString dxutils::commandsAt(int i)
1006 {
1007 return m_commands.at(i);
1008 }
1009
isCommand(const QString & command)1010 bool dxutils::isCommand(const QString &command)
1011 {
1012 if(!m_commands.size()) return false;
1013 for(int i=0; i<m_commands.size(); i++)
1014 {
1015 if(QString::compare(command, m_commands.at(i)) == 0) return true;
1016 }
1017 return false;
1018 }
1019
dcccommandsNo()1020 int dxutils::dcccommandsNo()
1021 {
1022 return m_dcccommands.size();
1023 }
1024
dcccommandsAt(int i)1025 QString dxutils::dcccommandsAt(int i)
1026 {
1027 return m_dcccommands.at(i);
1028 }
1029
isDccCommand(const QString & command)1030 bool dxutils::isDccCommand(const QString &command)
1031 {
1032 if(!m_dcccommands.size()) return false;
1033 for(int i=0; i<m_dcccommands.size(); i++)
1034 {
1035 if(QString::compare(command, m_dcccommands.at(i)) == 0) return true;
1036 }
1037 return false;
1038 }
1039
addScriptCommand(LuaScriptCommand command)1040 void dxutils::addScriptCommand(LuaScriptCommand command)
1041 {
1042 m_scriptCommands.append(command);
1043 fillCommands();
1044 }
1045
1046 //Remove one command for lua script
removeScriptCommand(const QString & command)1047 bool dxutils::removeScriptCommand(const QString &command)
1048 {
1049 for(int i=m_scriptCommands.size()-1; i>-1; i--)
1050 {
1051 if(QString::compare(command, m_scriptCommands[i].name) == 0)
1052 {
1053 m_scriptCommands.removeAt(i);
1054 fillCommands();
1055 return true;
1056 }
1057 }
1058 return false;
1059 }
1060
1061 //Remove all commands for lua script
removeScriptCommands(const QString & script)1062 bool dxutils::removeScriptCommands(const QString& script)
1063 {
1064 bool result = false;
1065 for(int i=m_scriptCommands.size()-1; i>-1; i--)
1066 {
1067 if(QString::compare(script, m_scriptCommands[i].script) == 0)
1068 {
1069 m_scriptCommands.removeAt(i);
1070 result = true;
1071 }
1072 }
1073 fillCommands();
1074 return result;
1075 }
1076
isScriptCommand(const QString & command)1077 bool dxutils::isScriptCommand(const QString &command)
1078 {
1079 for(int i=0; i<m_scriptCommands.size(); i++)
1080 {
1081 if(QString::compare(command, m_scriptCommands[i].name) == 0) return true;
1082 }
1083 return false;
1084 }
1085
availableCommands()1086 QString dxutils::availableCommands()
1087 {
1088 QString commandstr = _("Available commands: ");
1089 for(int i=0; i < m_commands.size(); i++)
1090 {
1091 if(m_commands[i] != "commands") commandstr += m_commands[i].toUpper()+(i != m_commands.size() - 1? ", " : "");
1092 }
1093 return commandstr;
1094 }
1095
availableDccCommands()1096 QString dxutils::availableDccCommands()
1097 {
1098 QString commandstr = _("Available commands: ");
1099 for(int i=0; i < m_dcccommands.size(); i++)
1100 {
1101 if(m_dcccommands[i] != "commands") commandstr += m_dcccommands[i].toUpper()+(i != m_dcccommands.size() - 1? ", " : "");
1102 }
1103 return commandstr;
1104 }
1105
availableScriptsCommands()1106 QString dxutils::availableScriptsCommands()
1107 {
1108 QString commandstr = _("Available commands: ");
1109 for(int i=0; i < m_scriptCommands.size(); i++)
1110 {
1111 commandstr += m_scriptCommands[i].name.toUpper()+(i != m_scriptCommands.size() - 1? ", " : "");
1112 }
1113 return commandstr;
1114 }
1115
availableScriptCommands(const QString & script)1116 QString dxutils::availableScriptCommands(const QString& script)
1117 {
1118 bool result = false;
1119 QString commandstr = _("Script commands: ");
1120 for(int i=m_scriptCommands.size()-1; i>-1; i--)
1121 {
1122 if(QString::compare(script, m_scriptCommands[i].script) == 0)
1123 {
1124 if(result) commandstr += ", ";
1125 commandstr += m_scriptCommands[i].name.toUpper();
1126 result = true;
1127 }
1128 }
1129 if(result) return commandstr;
1130 else return _("Script hasn't commands");
1131 }
1132
getHelpText(const QString & command)1133 QString dxutils::getHelpText(const QString &command)
1134 {
1135 for(int i=0; i<m_scriptCommands.size(); i++)
1136 {
1137 if(QString::compare(command, m_scriptCommands[i].name) == 0) return m_scriptCommands[i].helptext;
1138 }
1139 return _("Command %1 doesn't exists").arg(command);
1140 }
1141
getFuncname(const QString & command)1142 QString dxutils::getFuncname(const QString &command)
1143 {
1144 for(int i=0; i<m_scriptCommands.size(); i++)
1145 {
1146 if(QString::compare(command, m_scriptCommands[i].name) == 0) return m_scriptCommands[i].funcname;
1147 }
1148 return _("Command %1 doesn't exists").arg(command);
1149 }
1150
getScriptName(const QString & command)1151 QString dxutils::getScriptName(const QString &command)
1152 {
1153 for(int i=0; i<m_scriptCommands.size(); i++)
1154 {
1155 if(QString::compare(command, m_scriptCommands[i].name) == 0) return m_scriptCommands[i].script;
1156 }
1157 return _("Command %1 doesn't exists").arg(command);
1158 }
1159
getStringIniEntry(const QString & section,const QString & key,const QString & def)1160 QString dxutils::getStringIniEntry(const QString §ion, const QString &key, const QString &def)
1161 {
1162 QSettings set(preferences.getIniFile(), QSettings::IniFormat);
1163 set.beginGroup(section);
1164 return set.value(key, def).toString();
1165 }
1166
getIntIniEntry(const QString & section,const QString & key,int def)1167 int dxutils::getIntIniEntry(const QString §ion, const QString &key, int def)
1168 {
1169 QSettings set(preferences.getIniFile(), QSettings::IniFormat);
1170 set.beginGroup(section);
1171 return set.value(key, def).toInt();
1172 }
1173
1174 //return bool entry in inifile
getBoolIniEntry(const QString & section,const QString & key,bool def)1175 bool dxutils::getBoolIniEntry(const QString §ion, const QString &key, bool def)
1176 {
1177 QSettings set(preferences.getIniFile(), QSettings::IniFormat);
1178 set.beginGroup(section);
1179 return set.value(key, def).toBool();
1180 }
1181
1182 // return color entry in inifile
getColorIniEntry(const QString & section,const QString & key,QColor def)1183 QColor dxutils::getColorIniEntry(const QString §ion, const QString &key, QColor def)
1184 {
1185 QSettings set(preferences.getIniFile(), QSettings::IniFormat);
1186 set.beginGroup(section);
1187 return set.value(key, def).value<QColor>();
1188 }
1189
1190 //true if word right
1191 #ifdef HAVE_ENCHANT
checkWord(QString word,QString lang)1192 bool dxutils::checkWord(QString word, QString lang)
1193 {
1194 Checkers::const_iterator it = m_checkers.find(lang);
1195 if(it != m_checkers.end())
1196 return (*it).second->check(toStdString(word));
1197 return true;
1198 }
1199 #else
1200 #ifdef Q_OS_DARWIN
checkWord(QString word,QString)1201 bool dxutils::checkWord(QString word, QString)
1202 {
1203 if(_instance) _instance = new MacSpellCheck;
1204 return _instance->checkWord(word);
1205 }
1206 #else
checkWord(QString,QString)1207 bool dxutils::checkWord(QString, QString)
1208 {
1209 return true;
1210 }
1211 #endif //Q_OS_DARWIN
1212 #endif //HAVE_ENCHANT
1213
1214 //fill available langs
1215 #ifdef HAVE_ENCHANT
loadAvailableSpellLangs()1216 void dxutils::loadAvailableSpellLangs()
1217 {
1218 CheckerPair chpair(&m_checkers, &m_availableSpellLangs);
1219 ebroker->list_dicts(enumerateDicts, &chpair);
1220 if(m_availableSpellLangs.size())
1221 {
1222 m_availableSpellLangs.sort();
1223 }
1224 for(int i=0; i<m_availableSpellLangs.size(); i++)
1225 {
1226 if(m_checkers.find(m_availableSpellLangs[i]) != m_checkers.end())
1227 return;
1228 try
1229 {
1230 m_checkers[m_availableSpellLangs[i]] = ebroker->request_dict(toStdString(m_availableSpellLangs[i]));
1231 }
1232 catch(enchant::Exception &/*e*/)
1233 {
1234 }
1235 }
1236 }
1237 #else
loadAvailableSpellLangs()1238 void dxutils::loadAvailableSpellLangs()
1239 {
1240 m_availableSpellLangs.clear();
1241 }
1242 #endif
1243
1244 //get number of spellchecking language
1245 #ifdef HAVE_ENCHANT
getAvailableSpellLangsNum()1246 int dxutils::getAvailableSpellLangsNum()
1247 {
1248 return m_availableSpellLangs.size();
1249 }
1250 #else
getAvailableSpellLangsNum()1251 int dxutils::getAvailableSpellLangsNum()
1252 {
1253 return 0;
1254 }
1255 #endif
1256
1257 //return array of spellchecking language
getAvailableSpellLangs()1258 QStringList dxutils::getAvailableSpellLangs()
1259 {
1260 return m_availableSpellLangs;
1261 }
1262
1263 //time stamp to human readable string
stamp2string(QString datestr,QString timestr)1264 QString dxutils::stamp2string(QString datestr, QString timestr)
1265 {
1266 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
1267 QString format = QLocale::system().dateTimeFormat(QLocale::ShortFormat);
1268 #else
1269 Qt::DateFormat format = Qt::SystemLocaleShortDate;
1270 #endif
1271 return QString("["+QDate(datestr.section('-',0,0).toInt(), datestr.section('-',1,1).toInt(), datestr.section('-',2).toInt()).toString(format)+" "+timestr+"]");
1272 }
1273
1274 //normalize log line
normalizeLogLine(QString datestr,std::string line)1275 QString dxutils::normalizeLogLine(QString datestr, std::string line)
1276 {
1277 QString nline = fromStdString(line);
1278 QString date = stamp2string(datestr, nline.section(']',0,0).section('[',1));
1279 nline = date+nline.section(']',1);
1280 return nline;
1281 }
1282
1283 //Remove ircmark from text
stripColors(const QString & text,const bool stripOther)1284 QString dxutils::stripColors(const QString &text, const bool stripOther)
1285 {
1286 QString newstr;
1287 bool color = false;
1288 int numbers = 0;
1289 for(int i=0; i < text.length(); i++) {
1290 if(text[i] == '\017') //reset
1291 {
1292 color = false;
1293 }
1294 else if(stripOther && text[i] == '\002')
1295 {
1296 //remove bold mark
1297 }
1298 else if(stripOther && text[i] == '\037')
1299 {
1300 //remove underline mark
1301 }
1302 else if(text[i] == '\035')
1303 {
1304 //remove italic mark
1305 }
1306 else if(text[i] == '\021')
1307 {
1308 //remove fixed mark
1309 }
1310 else if(text[i] == '\026')
1311 {
1312 //remove reverse mark
1313 }
1314 else if(text[i] == '\003') //color
1315 {
1316 color = true;
1317 }
1318 else if(text[i] == '\004') //hex color
1319 {
1320 color = true;
1321 }
1322 else if(color && isdigit(text[i].toLatin1()) && numbers < 2)
1323 {
1324 numbers++;
1325 }
1326 else if(color && text[i] == ',' && numbers < 3)
1327 {
1328 numbers = 0;
1329 }
1330 else
1331 {
1332 numbers = 0;
1333 color = false;
1334 newstr += text[i];
1335 }
1336 }
1337 return newstr;
1338 }
1339
1340 //Return color for ircolor code
getIrcColor(int code,bool foreground)1341 QColor dxutils::getIrcColor(int code, bool foreground)
1342 {
1343 switch(code){
1344 case 0:
1345 return QColor("white");
1346 case 1:
1347 return QColor("black");
1348 case 2:
1349 return QColor(0,0,128); //blue
1350 case 3:
1351 return QColor(0,128,0); //green
1352 case 4:
1353 return QColor(255,0,0); //lightred
1354 case 5:
1355 return QColor(128,0,64); //brown
1356 case 6:
1357 return QColor(128,0,128); //purple
1358 case 7:
1359 return QColor(255,128,64); //orange
1360 case 8:
1361 return QColor(255,255,0); //yellow
1362 case 9:
1363 return QColor(128,255,0); //lightgreen
1364 case 10:
1365 return QColor(0,128,128); //cyan
1366 case 11:
1367 return QColor(0,255,255); //lightcyan
1368 case 12:
1369 return QColor(0,0,255); //lightblue
1370 case 13:
1371 return QColor(255,0,255); //pink
1372 case 14:
1373 return QColor(128,128,128); //grey
1374 case 15:
1375 return QColor(192,192,192); //lightgrey
1376 case 16:
1377 return QColor("#470000");
1378 case 17:
1379 return QColor("#472100");
1380 case 18:
1381 return QColor("#474700");
1382 case 19:
1383 return QColor("#324700");
1384 case 20:
1385 return QColor("#004700");
1386 case 21:
1387 return QColor("#00472c");
1388 case 22:
1389 return QColor("#004747");
1390 case 23:
1391 return QColor("#002747");
1392 case 24:
1393 return QColor("#000047");
1394 case 25:
1395 return QColor("#2e0047");
1396 case 26:
1397 return QColor("#470047");
1398 case 27:
1399 return QColor("#47002a");
1400 case 28:
1401 return QColor("#740000");
1402 case 29:
1403 return QColor("#743a00");
1404 case 30:
1405 return QColor("#747400");
1406 case 31:
1407 return QColor("#517400");
1408 case 32:
1409 return QColor("#007400");
1410 case 33:
1411 return QColor("#007449");
1412 case 34:
1413 return QColor("#007474");
1414 case 35:
1415 return QColor("#004074");
1416 case 36:
1417 return QColor("#000074");
1418 case 37:
1419 return QColor("#4b0074");
1420 case 38:
1421 return QColor("#740074");
1422 case 39:
1423 return QColor("#740045");
1424 case 40:
1425 return QColor("#b50000");
1426 case 41:
1427 return QColor("#b56300");
1428 case 42:
1429 return QColor("#b5b500");
1430 case 43:
1431 return QColor("#7db500");
1432 case 44:
1433 return QColor("#00b500");
1434 case 45:
1435 return QColor("#00b571");
1436 case 46:
1437 return QColor("#00b5b5");
1438 case 47:
1439 return QColor("#0063b5");
1440 case 48:
1441 return QColor("#0000b5");
1442 case 49:
1443 return QColor("#7500b5");
1444 case 50:
1445 return QColor("#b500b5");
1446 case 51:
1447 return QColor("#b5006b");
1448 case 52:
1449 return QColor("#ff0000");
1450 case 53:
1451 return QColor("#ff8c00");
1452 case 54:
1453 return QColor("#ffff00");
1454 case 55:
1455 return QColor("#b2ff00");
1456 case 56:
1457 return QColor("#00ff00");
1458 case 57:
1459 return QColor("#00ffa0");
1460 case 58:
1461 return QColor("#00ffff");
1462 case 59:
1463 return QColor("#008cff");
1464 case 60:
1465 return QColor("#0000ff");
1466 case 61:
1467 return QColor("#a500ff");
1468 case 62:
1469 return QColor("#ff00ff");
1470 case 63:
1471 return QColor("#ff0098");
1472 case 64:
1473 return QColor("#ff5959");
1474 case 65:
1475 return QColor("#ffb459");
1476 case 66:
1477 return QColor("#ffff71");
1478 case 67:
1479 return QColor("#cfff60");
1480 case 68:
1481 return QColor("#6fff6f");
1482 case 69:
1483 return QColor("#65ffc9");
1484 case 70:
1485 return QColor("#6dffff");
1486 case 71:
1487 return QColor("#59b4ff");
1488 case 72:
1489 return QColor("#5959ff");
1490 case 73:
1491 return QColor("#c459ff");
1492 case 74:
1493 return QColor("#ff66ff");
1494 case 75:
1495 return QColor("#ff59bc");
1496 case 76:
1497 return QColor("#ff9c9c");
1498 case 77:
1499 return QColor("#ffd39c");
1500 case 78:
1501 return QColor("#ffff9c");
1502 case 79:
1503 return QColor("#e2ff9c");
1504 case 80:
1505 return QColor("#9cff9c");
1506 case 81:
1507 return QColor("#9cffdb");
1508 case 82:
1509 return QColor("#9cffff");
1510 case 83:
1511 return QColor("#9cd3ff");
1512 case 84:
1513 return QColor("#9c9cff");
1514 case 85:
1515 return QColor("#dc9cff");
1516 case 86:
1517 return QColor("#ff9cff");
1518 case 87:
1519 return QColor("#ff94d3");
1520 case 88:
1521 return QColor("#000000");
1522 case 89:
1523 return QColor("#131313");
1524 case 90:
1525 return QColor("#282828");
1526 case 91:
1527 return QColor("#363636");
1528 case 92:
1529 return QColor("#4d4d4d");
1530 case 93:
1531 return QColor("#656565");
1532 case 94:
1533 return QColor("#818181");
1534 case 95:
1535 return QColor("#9f9f9f");
1536 case 96:
1537 return QColor("#bcbcbc");
1538 case 97:
1539 return QColor("#e2e2e2");
1540 case 98:
1541 return QColor("#ffffff");
1542 default:
1543 return foreground?preferences.m_colors.text:preferences.m_colors.back;
1544 }
1545 }
1546
1547 //Remove ircmark from text
stripLogMark(const QString & text)1548 QString dxutils::stripLogMark(const QString &text)
1549 {
1550 QString newstr;
1551 bool mark = false;
1552 int numbers = 0;
1553 int i = 0;
1554 while(text[i] != '\0') {
1555 if(text[i] == '\014') //log mark
1556 {
1557 if(!mark) mark = true; //first mark
1558 else mark = false; //last mark
1559 }
1560 else if(mark && isdigit(text[i].toLatin1()) && numbers < 2)
1561 {
1562 numbers++;
1563 }
1564 else
1565 {
1566 numbers = 0;
1567 mark = false;
1568 newstr += text[i];
1569 }
1570 i++;
1571 }
1572 return newstr;
1573 }
1574
getColorForStyle(int style)1575 QColor dxutils::getColorForStyle(int style)
1576 {
1577 switch (style) {
1578 //gray text - user commands
1579 case 1: return preferences.m_colors.user;
1580 //orange text - Actions
1581 case 2: return preferences.m_colors.action;
1582 //blue text - Notice
1583 case 3: return preferences.m_colors.notice;
1584 //red text - Errors
1585 case 4: return preferences.m_colors.error;
1586 //highlight text
1587 case 8: return preferences.m_colors.hilight;
1588 //mymsg style
1589 case 10: return preferences.m_colors.mymsg;
1590 //log line style
1591 case 11: return preferences.m_colors.log;
1592 default: return preferences.m_colors.text;
1593 }
1594 }
1595
1596 //get spellchecking language for channel
1597 #ifdef HAVE_ENCHANT
getChannelLang(const QString & channel)1598 QString dxutils::getChannelLang(const QString &channel)
1599 {
1600 if(channel.isEmpty()) return getDefaultLang();
1601 QMap<QString,QString>::iterator it = preferences.m_langs.find(channel);
1602 QString lang = "";
1603 if(it != preferences.m_langs.end())
1604 lang = it.value();
1605 if(m_checkers.find(lang) != m_checkers.end())
1606 return lang;
1607 else return getDefaultLang();
1608 }
1609 #else
getChannelLang(const QString &)1610 QString dxutils::getChannelLang(const QString&)
1611 {
1612 return "";
1613 }
1614 #endif
1615
createLinks(const QString & txt,bool removeThan)1616 QString dxutils::createLinks(const QString &txt, bool removeThan)
1617 {
1618 QString line = "";
1619 int i = 0;
1620 int linkLength = 0;
1621 int length = txt.length();
1622 while(i<length)
1623 {
1624 if(txt[i]=='<' && removeThan)
1625 {
1626 line.append("<");
1627 }
1628 else if(txt[i]=='>' && removeThan)
1629 {
1630 line.append(">");
1631 }
1632 else if(txt[i]=='h' && !QString::compare(txt.mid(i,7),"http://",Qt::CaseInsensitive))
1633 {
1634 for(int j=i; j<length; j++)
1635 {
1636 if(isBadchar(txt[j].toLatin1()))
1637 {
1638 break;
1639 }
1640 linkLength++;
1641 }
1642 if(linkLength>7)
1643 line.append(QString("<a href=\"%1\">%1</a>").arg(txt.mid(i, linkLength)));
1644 else
1645 line.append(txt.mid(i, linkLength));
1646 i+=linkLength-1;
1647 linkLength=0;
1648 }
1649 else if(txt[i]=='h' && !QString::compare(txt.mid(i,8),"https://",Qt::CaseInsensitive))
1650 {
1651 for(int j=i; j<length; j++)
1652 {
1653 if(isBadchar(txt[j].toLatin1()))
1654 {
1655 break;
1656 }
1657 linkLength++;
1658 }
1659 if(linkLength>8)
1660 line.append(QString("<a href=\"%1\">%1</a>").arg(txt.mid(i, linkLength)));
1661 else
1662 line.append(txt.mid(i, linkLength));
1663 i+=linkLength-1;
1664 linkLength=0;
1665 }
1666 else if(txt[i]=='f' && !QString::compare(txt.mid(i,6),"ftp://",Qt::CaseInsensitive))
1667 {
1668 for(int j=i; j<length; j++)
1669 {
1670 if(isBadchar(txt[j].toLatin1()))
1671 {
1672 break;
1673 }
1674 linkLength++;
1675 }
1676 if(linkLength>6)
1677 line.append(QString("<a href=\"%1\">%1</a>").arg(txt.mid(i, linkLength)));
1678 else
1679 line.append(txt.mid(i, linkLength));
1680 i+=linkLength-1;
1681 linkLength=0;
1682 }
1683 else if(txt[i]=='w' && !QString::compare(txt.mid(i,4),"www.",Qt::CaseInsensitive))
1684 {
1685 for(int j=i; j<length; j++)
1686 {
1687 if(isBadchar(txt[j].toLatin1()))
1688 {
1689 break;
1690 }
1691 linkLength++;
1692 }
1693 if(linkLength>4)
1694 line.append(QString("<a href=\"%1\">%1</a>").arg(txt.mid(i, linkLength)));
1695 else
1696 line.append(txt.mid(i, linkLength));
1697 i+=linkLength-1;
1698 linkLength=0;
1699 }
1700 else
1701 {
1702 line.append(txt[i]);
1703 }
1704 i++;
1705 }
1706 return line;
1707 }
1708
closeTags(QList<QString> tags)1709 static QString closeTags(QList<QString> tags)
1710 {
1711 QString result;
1712 for(int i=tags.size()-1; i>-1; i--)
1713 {
1714 result.append("</");
1715 if(tags[i].contains(' ')) result.append(tags[i].section('<',1).section(' ',0,0));
1716 else result.append(tags[i].section('<',1).section('>',0,0));
1717 result.append('>');
1718 }
1719 return result;
1720 }
1721
openTags(bool color,QColor foreColor,bool bgcolor,QColor backColor,bool bold,bool under,bool italic)1722 static QList<QString> openTags(bool color, QColor foreColor, bool bgcolor, QColor backColor, bool bold, bool under, bool italic)
1723 {
1724 QList<QString> result;
1725 if(color) result.append(QString("<font color=\"%1\">").arg(foreColor.name()));
1726 if(bgcolor) result.append(QString("<span style=\"background-color:%1\">").arg(backColor.name()));
1727 if(bold) result.append("<b>");
1728 if(under) result.append("<u>");
1729 if(italic) result.append("<i>");
1730 return result;
1731 }
1732
1733 //removeThan is remove < and >
parseText(const QString & txt,int stylenum,bool removeThan)1734 QString dxutils::parseText(const QString &txt, int stylenum, bool removeThan)
1735 {
1736 const QString linked = createLinks(txt, removeThan);
1737 QString line = "";
1738 if(stylenum == 5) //bold text
1739 {
1740 line.prepend("<b>");
1741 }
1742 if(stylenum == 6) //underline style
1743 {
1744 line.prepend("<u>");
1745 }
1746 if(stylenum == 7) //bold & underline
1747 {
1748 line.prepend("<b><u>");
1749 }
1750 int i = 0;
1751 bool bold = false;
1752 bool under = false;
1753 bool italic = false;
1754 bool color = false;
1755 bool bgcolor = false;
1756 int length = linked.length();
1757 QList<QString> tags;
1758 QColor foreColor = dxutils::getColorForStyle(stylenum);
1759 QColor backColor = preferences.m_colors.back;
1760 if(dxutils::getColorForStyle(stylenum)!=preferences.m_colors.text) line.prepend(QString("<font color=\"%1\">").arg(foreColor.name()));
1761 while(i<length)
1762 {
1763 if(linked[i] == '\002') //bold
1764 {
1765 if(!tags.empty())
1766 {
1767 line.append(closeTags(tags));
1768 }
1769 bold = !bold;
1770 tags = openTags(color, foreColor, bgcolor, backColor, bold, under, italic);
1771 foreach(QString tag, tags)
1772 line.append(tag);
1773 }
1774 else if(linked[i] == '\026') //reverse
1775 {
1776 if(!tags.empty())
1777 {
1778 line.append(closeTags(tags));
1779 }
1780 bgcolor = true;
1781 color = true;
1782 QColor tempColor = foreColor;
1783 foreColor = backColor;
1784 backColor = tempColor;
1785 tags = openTags(color, foreColor, bgcolor, backColor, bold, under, italic);
1786 foreach(QString tag, tags)
1787 line.append(tag);
1788 }
1789 else if(linked[i] == '\037') //underline
1790 {
1791 if(!tags.empty())
1792 {
1793 line.append(closeTags(tags));
1794 }
1795 under = !under;
1796 tags = openTags(color, foreColor, bgcolor, backColor, bold, under, italic);
1797 foreach(QString tag, tags)
1798 line.append(tag);
1799 }
1800 else if(linked[i] == '\021') //fixed
1801 {
1802 dxutils::debugLine("Poslan fixed styl");
1803 }
1804 else if(linked[i] == '\035') //italic
1805 {
1806 if(!tags.empty())
1807 {
1808 line.append(closeTags(tags));
1809 }
1810 italic = !italic;
1811 tags = openTags(color, foreColor, bgcolor, backColor, bold, under, italic);
1812 foreach(QString tag, tags)
1813 line.append(tag);
1814 }
1815 else if(linked[i] == '\003') //color
1816 {
1817 if(!tags.empty())
1818 {
1819 line.append(closeTags(tags));
1820 }
1821 int colorLength = 0;
1822 foreColor = preferences.m_colors.text;
1823 backColor = preferences.m_colors.back;
1824 bool isHexColor = false;
1825 if(i+1<length)
1826 {
1827 if(linked[i+1] == '#') isHexColor = true;
1828 }
1829 if(isHexColor)
1830 {
1831 if(QRegularExpression("[0-9a-fA-F]{6}").match(linked.mid(i+2,6)).hasMatch())
1832 {
1833 color = true;
1834 foreColor = QColor(linked.mid(i+1,7));
1835 colorLength +=7;
1836 }
1837 if(i+8 < length && linked[i+8] == ',' && QRegularExpression("[0-9a-fA-F]{6}").match(linked.mid(i+10,6)).hasMatch())
1838 {
1839 bgcolor = true;
1840 backColor = QColor(linked.mid(i+9,7));
1841 colorLength +=8;
1842 }
1843 }
1844 else
1845 {
1846 if(i+2<length)
1847 {
1848 int code = -1;
1849 if(isdigit(linked[i+1].toLatin1()))
1850 {
1851 if(isdigit(linked[i+2].toLatin1()))
1852 {
1853 code = (linked[i+1].toLatin1()-48)*10+linked[i+2].toLatin1()-48;
1854 colorLength +=2;
1855 }
1856 else
1857 {
1858 code = linked[i+1].toLatin1()-48;
1859 colorLength ++;
1860 }
1861 }
1862 if(code!=-1)
1863 {
1864 color = true;
1865 foreColor = dxutils::getIrcColor(code, true);
1866 }
1867 }
1868 if(i+colorLength+1 < length && linked[i+colorLength+1] == ',')
1869 {
1870 int code = -1;
1871 if(isdigit(linked[i+colorLength+2].toLatin1()))
1872 {
1873 if(isdigit(linked[i+colorLength+3].toLatin1()))
1874 {
1875 code = (linked[i+colorLength+2].toLatin1()-48)*10+linked[i+colorLength+3].toLatin1()-48;
1876 colorLength +=3;
1877 }
1878 else
1879 {
1880 code = linked[i+colorLength+2].toLatin1()-48;
1881 colorLength +=2;
1882 }
1883 }
1884 if(code!=-1)
1885 {
1886 bgcolor = true;
1887 backColor = dxutils::getIrcColor(code, false);
1888 }
1889 }
1890 }
1891 tags = openTags(color, foreColor, bgcolor, backColor, bold, under, italic);
1892 foreach(QString tag, tags)
1893 line.append(tag);
1894 i +=colorLength;
1895 }
1896 else if(linked[i] == '\004') //hex color
1897 {
1898 if(!tags.empty())
1899 {
1900 line.append(closeTags(tags));
1901 }
1902 int colorLength = 0;
1903 foreColor = preferences.m_colors.text;
1904 backColor = preferences.m_colors.back;
1905 if(QRegularExpression("[0-9a-fA-F]{6}").match(linked.mid(i+1,6)).hasMatch())
1906 {
1907 color = true;
1908 foreColor = QColor(QString("#")+linked.mid(i+1,6));
1909 colorLength +=6;
1910 }
1911 if(i+7 < length && linked[i+7] == ',' && QRegularExpression("[0-9a-fA-F]{6}").match(linked.mid(i+8,6)).hasMatch())
1912 {
1913 bgcolor = true;
1914 backColor = QColor(QString("#")+linked.mid(i+8,6));
1915 colorLength +=7;
1916 }
1917 tags = openTags(color, foreColor, bgcolor, backColor, bold, under, italic);
1918 foreach(QString tag, tags)
1919 line.append(tag);
1920 i +=colorLength;
1921 }
1922 else if(linked[i] == '\017') //reset
1923 {
1924 if(!tags.empty())
1925 {
1926 line.append(closeTags(tags));
1927 }
1928 bold = false;
1929 under = false;
1930 italic = false;
1931 bgcolor = false;
1932 color = false;
1933 foreColor = preferences.m_colors.text;
1934 backColor = preferences.m_colors.back;
1935 }
1936 else
1937 {
1938 line.append(linked[i]);
1939 }
1940 i++;
1941 }
1942 if(!tags.empty())
1943 {
1944 line.append(closeTags(tags));
1945 }
1946 if(stylenum == 5) //bold text
1947 {
1948 line.append("</b>");
1949 }
1950 if(stylenum == 6) //underline style
1951 {
1952 line.append("</u>");
1953 }
1954 if(stylenum == 7) //bold & underline
1955 {
1956 line.append("</u></b>");
1957 }
1958 if(dxutils::getColorForStyle(stylenum)!=preferences.m_colors.text) line.append("</font>");
1959 if(preferences.m_useSmileys) return createSmileys(line);
1960 return line;
1961 }
1962
1963 //logstyle = true for IrcTabItem::loadLogLines()
parseLogline(const QString & line,bool logstyle)1964 QString dxutils::parseLogline(const QString& line, bool logstyle)
1965 {
1966 if(line.section(']',1)[1].toLatin1()=='\014') //log style mark
1967 {
1968 int style = logstyle?11:line.section('\014',1).section('\014',0,0).toInt();
1969 QString time = line.section('\014',0,0);
1970 if(line.section('\014',2)[0].toLatin1()=='<') //has nick
1971 {
1972 QString nick = line.section('<',1).section('>',0,0);
1973 QString msg = line.section('>',1);
1974 if(logstyle)
1975 {
1976 QString nickStyled = "";
1977 if(preferences.m_coloredNick) nickStyled = QString("<font color=\"%1\">%2: </font>").arg(getNickColor(nick)).arg(nick);
1978 else nickStyled = QString("<b>%1: </b>").arg(nick);
1979 return parseText(time+nickStyled+msg, style, false);
1980 }
1981 else
1982 {
1983 return time+parseText(nick+":"+msg, style);
1984 }
1985 }
1986 else
1987 {
1988 if(logstyle) return parseText(time+line.section('\014',2), style, false);
1989 else return time+parseText(line.section('\014',2), style);
1990 }
1991 }
1992 else
1993 {
1994 if(line.section(']',1)[1].toLatin1()=='<') //line with nick
1995 {
1996 QString time = line.section('<',0,0);
1997 QString nick = line.section('<',1).section('>',0,0);
1998 QString nickStyled = "";
1999 if(preferences.m_coloredNick) nickStyled = QString("<font color=\"%1\">%2: </font>").arg(getNickColor(nick)).arg(nick);
2000 else nickStyled = QString("<b>%1: </b>").arg(nick);
2001 QString msg = line.section('>',1).trimmed();
2002 if(logstyle) return parseText(time+nickStyled+msg, 11, false);
2003 else return time+nickStyled+parseText(msg, 0);
2004 }
2005 else
2006 {
2007 if(logstyle) return parseText(line, 11, false);
2008 else return parseText(line, 0);
2009 }
2010 }
2011 }
2012
2013 //Get away color
makeAwayColor(QColor clr)2014 QColor dxutils::makeAwayColor(QColor clr)
2015 {
2016 int r,g,b;
2017 r=clr.red();
2018 g=clr.green();
2019 b=clr.blue();
2020 if(r==g && r==b && !r)
2021 {
2022 r=255;
2023 g=255;
2024 b=255;
2025 }
2026 r=(50*r)/100;
2027 g=(50*g)/100;
2028 b=(50*b)/100;
2029 return QColor(r,g,b);
2030 }
2031
2032 //UserMode to QIcon
modeToIcon(UserMode mode)2033 QString dxutils::modeToIcon(UserMode mode)
2034 {
2035 switch(mode) {
2036 case OWNER:
2037 {
2038 return preferences.m_themePath+"/irc_owner.png";
2039 }
2040 case ADMIN:
2041 {
2042 return preferences.m_themePath+"/irc_admin.png";
2043 }
2044 case OP:
2045 {
2046 return preferences.m_themePath+"/irc_op.png";
2047 }
2048 case VOICE:
2049 {
2050 return preferences.m_themePath+"/irc_voice.png";
2051 }
2052 case HALFOP:
2053 {
2054 return preferences.m_themePath+"/irc_halfop.png";
2055 }
2056 default:
2057 {
2058 return preferences.m_themePath+"/irc_normal.png";
2059 }
2060 }
2061 }
2062
getUsername()2063 QString dxutils::getUsername()
2064 {
2065 #ifdef Q_OS_WIN
2066 return QProcessEnvironment::systemEnvironment().value("USERNAME");
2067 #else
2068 return QProcessEnvironment::systemEnvironment().value("USER");
2069 #endif
2070 }
2071
getIconForType(TYPE type)2072 QString dxutils::getIconForType(TYPE type)
2073 {
2074 switch(type){
2075 case SERVER: return getDataPath()+"/icons/world.png";
2076 case CHANNEL: return getDataPath()+"/icons/channel.png";
2077 case QUERY: return getDataPath()+"/icons/user.png";
2078 case OTHER: return getDataPath()+"/icons/logs.png";
2079 case DCC: return getDataPath()+"/icons/dcc.png";
2080 case BOATS: return "";
2081 default: return "";
2082 }
2083 }
2084
removeDir(const QString & dirName)2085 bool dxutils::removeDir(const QString &dirName)
2086 {
2087 bool result = true;
2088 QDir dir(dirName);
2089 if(dir.exists(dirName))
2090 {
2091 Q_FOREACH(QFileInfo info, dir.entryInfoList(QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::AllDirs | QDir::Files, QDir::DirsFirst))
2092 {
2093 if(info.isDir())
2094 {
2095 result = removeDir(info.absoluteFilePath());
2096 }
2097 else
2098 {
2099 result = QFile::remove(info.absoluteFilePath());
2100 }
2101 if(!result)
2102 {
2103 return result;
2104 }
2105 }
2106 result = dir.rmdir(dirName);
2107 }
2108 return result;
2109 }
2110
getLocalePath()2111 QString dxutils::getLocalePath()
2112 {
2113 #if defined(Q_OS_WIN)
2114 QString path = QApplication::applicationFilePath();
2115 int ii = path.lastIndexOf('/');
2116 if(ii > 0)
2117 path.remove(ii, path.length());
2118 return path.append("/locale");
2119 #elif defined(Q_OS_DARWIN)
2120 #ifdef ENABLE_OSX_BUNDLE
2121 QString path = QApplication::applicationFilePath();
2122 int ii = path.lastIndexOf('/');
2123 if(ii > 0)
2124 path.remove(ii, path.length());
2125 return path.append("/locale");
2126 #else
2127 return QString(LOCALEDIR);
2128 #endif
2129 #else
2130 return QString(LOCALEDIR);
2131 #endif
2132 }
2133
getDataPath()2134 QString dxutils::getDataPath()
2135 {
2136 #if defined(Q_OS_WIN)
2137 QString path = QApplication::applicationFilePath();
2138 int ii = path.lastIndexOf('/');
2139 if(ii > 0)
2140 path.remove(ii, path.length());
2141 return path;
2142 #elif defined(Q_OS_DARWIN)
2143 #ifdef ENABLE_OSX_BUNDLE
2144 QString path = QApplication::applicationFilePath();
2145 int ii = path.lastIndexOf('/');
2146 if(ii > 0)
2147 path.remove(ii, path.length());
2148 return path.append("/../Resources");
2149 #else
2150 return QString(DXIRC_DATADIR);
2151 #endif
2152 #else
2153 return QString(DXIRC_DATADIR);
2154 #endif
2155 }
2156
getKeybinding(QKeyEvent * e)2157 QKeySequence dxutils::getKeybinding(QKeyEvent *e)
2158 {
2159 int keyInt = e->key();
2160 Qt::Key key = static_cast<Qt::Key>(keyInt);
2161 if(key == Qt::Key_unknown)
2162 {
2163 return QKeySequence(Qt::Key_unknown);
2164 }
2165 // the user have clicked just and only the special keys Ctrl, Shift, Alt, Meta.
2166 if(key == Qt::Key_Control ||
2167 key == Qt::Key_Shift ||
2168 key == Qt::Key_Alt ||
2169 key == Qt::Key_Meta)
2170 {
2171 return QKeySequence(keyInt);
2172 }
2173 // check for a combination of user clicks
2174 Qt::KeyboardModifiers modifiers = e->modifiers();
2175 if(modifiers & Qt::ShiftModifier)
2176 keyInt += Qt::SHIFT;
2177 if(modifiers & Qt::ControlModifier)
2178 keyInt += Qt::CTRL;
2179 if(modifiers & Qt::AltModifier)
2180 keyInt += Qt::ALT;
2181 if(modifiers & Qt::MetaModifier)
2182 keyInt += Qt::META;
2183 return QKeySequence(keyInt);
2184 }
2185
wrapText(QString text,int width,char wrap)2186 QString dxutils::wrapText(QString text, int width, char wrap)
2187 {
2188 QFontMetrics fnt(preferences.m_ircFont);
2189 int tw = 0;
2190 int cw;
2191 int s = -1;
2192 for(int i=0; i<text.length(); i++)
2193 {
2194 #if (QT_VERSION < QT_VERSION_CHECK(5, 11, 0))
2195 cw = fnt.width(text[i]);
2196 #else
2197 cw = fnt.horizontalAdvance(text[i]);
2198 #endif
2199 if(text[i]==wrap) s = i;
2200 if(tw+cw>width)
2201 {
2202 if(s!=-1)
2203 {
2204 text.replace(s,1,'\n');
2205 i=s+1;
2206 s=-1;
2207 }
2208 tw=0;
2209 }
2210 tw+=cw;
2211 }
2212 return text;
2213 }
2214
enquote(const QString & string)2215 QString dxutils::enquote(const QString &string)
2216 {
2217 QString s = string;
2218 return QString("\"%1\"").arg(s.replace(QLatin1Char('\\'),QLatin1String("\\\\"))).replace(QLatin1Char('"'),QLatin1String("\\\""));
2219 }
2220
2221
2222