1 /*
2 Copyright (C) 2014 Aseman
3 http://aseman.co
4
5 This project is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This project 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
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #define UNITY_LIGHT (p->desktop->desktopSession()==AsemanDesktopTools::Unity && !p->desktop->titleBarIsDark())
20 #define UNITY_ICON_PATH(NUM) "/tmp/aseman-telegram-client-trayicon" + QString::number(NUM) + (lowLevelDarkSystemTray()?"-dark":"-light") + ".png"
21 #define SYSTRAY_ICON (lowLevelDarkSystemTray()?":/qml/Cutegram/files/systray-dark.png":":/qml/Cutegram/files/systray.png")
22 #define SYSTRAY_ICON_STATUS QString("General/statusIconStyle_%1").arg(AsemanDesktopTools::desktopSession())
23
24 #include "cutegram.h"
25 #include "asemantools/asemanquickview.h"
26 #include "asemantools/asemancalendarconverter.h"
27 #include "asemantools/asemandesktoptools.h"
28 #include "asemantools/asemandevices.h"
29 #include "asemantools/asemanapplication.h"
30 #include "asemantools/asemanlistrecord.h"
31 #include "emoticonsmodel.h"
32 #include "contributorsmodel.h"
33 #include "themeitem.h"
34 #include "texttohtmlconverter.h"
35 #include "cutegramdialog.h"
36 #include "textemojiwrapper.h"
37 #include "cutegramencrypter.h"
38 #include "stickerfilemanager.h"
39 #include "emojis.h"
40 #include "unitysystemtray.h"
41 #include "pasteanalizer.h"
42 #include "cutegramenums.h"
43 #include "authsaver.h"
44
45 #include <QPointer>
46 #include <QQmlContext>
47 #include <QQmlEngine>
48 #include <QtQml>
49 #include <QDebug>
50 #include <QImageWriter>
51 #include <QTextDocument>
52 #include <QImageReader>
53 #include <QSystemTrayIcon>
54 #include <QGuiApplication>
55 #include <QMenu>
56 #include <QAction>
57 #include <QPainter>
58 #include <QPainterPath>
59 #include <QDesktopServices>
60 #include <QMimeDatabase>
61 #include <QTimer>
62
63 #include <telegramqml.h>
64 #include <core/settings.h>
65 #include <userdata.h>
66
67 #ifdef Q_OS_WIN
68 #include <QtWin>
69 #endif
70
71 class CutegramPrivate
72 {
73 public:
74 QString defaultHostAddress;
75 int defaultHostPort;
76 int defaultHostDcId;
77 int appId;
78 QString appHash;
79
80 QPointer<AsemanQuickView> viewer;
81 int sysTrayCounter;
82 int startupOption;
83 int statusIconStyle;
84 bool notification;
85 bool emojiOnHover;
86 bool minimumDialogs;
87 bool showLastMessage;
88 bool darkSystemTray;
89 bool closingState;
90 bool cutegramSubscribe;
91 bool kWallet;
92 bool nativeTitleBar;
93 bool autoEmojis;
94 bool smoothScroll;
95 bool sendByCtrlEnter;
96
97 QTextDocument *doc;
98
99 QSystemTrayIcon *sysTray;
100 UnitySystemTray *unityTray;
101
102 AsemanDesktopTools *desktop;
103
104 QTranslator *translator;
105 QString translationsPath;
106 QString themesPath;
107 QString emojisThemesPath;
108
109 QHash<QString,QVariant> languages;
110 QHash<QString,QLocale> locales;
111 QString language;
112
113 QString background;
114 QString messageAudio;
115 QString masterColor;
116 QFont font;
117
118 QPalette mainPalette;
119 QColor highlightColor;
120
121 QMimeDatabase mdb;
122
123 QStringList themes;
124 QString theme;
125 QPointer<QQmlComponent> currentThemeComponent;
126 QPointer<ThemeItem> currentTheme;
127
128 QStringList emojisThemes;
129 QString emojisTheme;
130
131 QStringList searchEngines;
132 QString searchEngine;
133
134 CutegramEncrypter encrypter;
135 QTimer *save_timer;
136 };
137
Cutegram(QObject * parent)138 Cutegram::Cutegram(QObject *parent) :
139 QObject(parent)
140 {
141 QFont default_font;
142 int startupOption = StartupAutomatic;
143 #ifdef Q_OS_MACX
144 startupOption = StartupVisible;
145 default_font.setPointSize(9);
146 #endif
147 #ifdef Q_OS_WIN
148 default_font.setPointSize(10);
149 #endif
150
151 p = new CutegramPrivate;
152 p->defaultHostAddress = "149.154.167.50";
153 p->defaultHostPort = 443;
154 p->defaultHostDcId = 2;
155 p->appId = 13682;
156 p->appHash = "de37bcf00f4688de900510f4f87384bb";
157 p->doc = new QTextDocument(this);
158 p->desktop = new AsemanDesktopTools(this);
159 p->sysTray = 0;
160 p->unityTray = 0;
161 p->sysTrayCounter = 0;
162 p->closingState = false;
163 p->highlightColor = AsemanApplication::settings()->value("General/lastHighlightColor", p->mainPalette.highlight().color().name() ).toString();
164 p->startupOption = AsemanApplication::settings()->value("General/startupOption", startupOption).toInt();
165 p->statusIconStyle = AsemanApplication::settings()->value(SYSTRAY_ICON_STATUS, static_cast<int>(StatusIconAutomatic) ).toInt();
166 p->notification = AsemanApplication::settings()->value("General/notification", true ).toBool();
167 p->emojiOnHover = AsemanApplication::settings()->value("General/emojiOnHover", true ).toBool();
168 p->minimumDialogs = AsemanApplication::settings()->value("General/minimumDialogs", false ).toBool();
169 p->showLastMessage = AsemanApplication::settings()->value("General/showLastMessage", false ).toBool();
170 p->cutegramSubscribe = AsemanApplication::settings()->value("General/cutegramSubscribe", true ).toBool();
171 p->kWallet = AsemanApplication::settings()->value("General/kWallet", true ).toBool();
172 p->nativeTitleBar = AsemanApplication::settings()->value("General/nativeTitleBar", allowNativeTitleBar() ).toBool();
173 p->autoEmojis = AsemanApplication::settings()->value("General/autoEmojis", true ).toBool();
174 p->smoothScroll = AsemanApplication::settings()->value("General/smoothScroll", true ).toBool();
175 p->sendByCtrlEnter = AsemanApplication::settings()->value("General/sendByCtrlEnter", false ).toBool();
176 p->darkSystemTray = AsemanApplication::settings()->value("General/darkSystemTray", UNITY_LIGHT ).toBool();
177 p->background = AsemanApplication::settings()->value("General/background").toString();
178 p->masterColor = AsemanApplication::settings()->value("General/masterColor").toString();
179 p->messageAudio = AsemanApplication::settings()->value("General/messageAudio","files/new_msg.ogg").toString();
180 p->font = AsemanApplication::settings()->value("General/font", default_font).value<QFont>();
181 p->translator = new QTranslator(this);
182 p->theme = AsemanApplication::settings()->value("General/theme","Abrisham.qml").toString();
183 p->emojisTheme = AsemanApplication::settings()->value("General/emojisTheme", "twitter").toString();
184 p->searchEngine = AsemanApplication::settings()->value("General/searchEngine","https://duckduckgo.com/?q=").toString();
185
186 p->searchEngines = QStringList() << "https://duckduckgo.com/?q=" << "https://google.com/?q=" << "https://bing.com/?q=";
187
188 #ifdef Q_OS_ANDROID
189 p->translationsPath = "assets:/files/translations";
190 p->themesPath = "assets:/themes";
191 #else
192 p->translationsPath = AsemanDevices::resourcePath() + "/files/translations/";
193 p->themesPath = AsemanDevices::resourcePath() + "/themes/";
194 p->emojisThemesPath = AsemanDevices::resourcePath() + "/emojis/";
195 #endif
196
197 p->save_timer = new QTimer(this);
198 p->save_timer->setSingleShot(true);
199 p->save_timer->setInterval(1000);
200
201 p->themes = QDir(p->themesPath).entryList( QStringList()<<"*.qml" ,QDir::Files, QDir::Name);
202
203 p->emojisThemes = QDir(p->emojisThemesPath).entryList( QStringList() ,QDir::Dirs|QDir::NoDotAndDotDot, QDir::Name);
204
205 QDir().mkpath(personalStickerDirectory());
206
207 qmlRegisterType<StickerFileManager>("Cutegram", 1, 0, "StickerFileManager");
208 qmlRegisterType<ContributorsModel>("Cutegram", 1, 0, "ContributorsModel");
209 qmlRegisterType<CutegramEnums>("Cutegram", 1, 0, "CutegramEnums");
210 qmlRegisterType<ThemeItem>("Cutegram", 1, 0, "CutegramTheme");
211 qmlRegisterType<TextEmojiWrapper>("Cutegram", 1, 0, "TextEmojiWrapper");
212 qmlRegisterType<Emojis>("Cutegram", 1, 0, "Emojis");
213 qmlRegisterType<EmoticonsModel>("Cutegram", 1, 0, "EmoticonsModel");
214 qmlRegisterType<CutegramDialog>("Cutegram", 1, 0, "CutegramDialog");
215 qmlRegisterType<PasteAnalizer>("Cutegram", 1, 0, "PasteAnalizer");
216 qmlRegisterType<TextToHtmlConverter>("Cutegram", 1, 0, "TextToHtmlConverter");
217
218 init_languages();
219
220 connect(p->save_timer, SIGNAL(timeout()), SLOT(savePosition()));
221 }
222
imageSize(const QString & pt)223 QSize Cutegram::imageSize(const QString &pt)
224 {
225 QString path = pt;
226 if(path.left(AsemanDevices::localFilesPrePath().length()) == AsemanDevices::localFilesPrePath())
227 path = path.mid(AsemanDevices::localFilesPrePath().length());
228 if(path.isEmpty())
229 return QSize();
230
231 QImageReader img(path);
232 return img.size();
233 }
234
filsIsImage(const QString & pt)235 bool Cutegram::filsIsImage(const QString &pt)
236 {
237 QString path = pt;
238 if(path.left(AsemanDevices::localFilesPrePath().length()) == AsemanDevices::localFilesPrePath())
239 path = path.mid(AsemanDevices::localFilesPrePath().length());
240 if(path.isEmpty())
241 return false;
242
243 return p->mdb.mimeTypeForFile(path).name().toLower().contains("image");
244 }
245
htmlWidth(const QString & txt)246 qreal Cutegram::htmlWidth(const QString &txt)
247 {
248 p->doc->setHtml(txt);
249 return p->doc->size().width() + 10;
250 }
251
deleteFile(const QString & pt)252 void Cutegram::deleteFile(const QString &pt)
253 {
254 QString path = pt;
255 if(path.left(AsemanDevices::localFilesPrePath().length()) == AsemanDevices::localFilesPrePath())
256 path = path.mid(AsemanDevices::localFilesPrePath().length());
257 if(path.isEmpty())
258 return;
259
260 QFile::remove(path);
261 }
262
storeMessage(const QString & msg)263 QString Cutegram::storeMessage(const QString &msg)
264 {
265 const QString &path = AsemanApplication::tempPath() + "/" + QDateTime::currentDateTime().toString("ddd MMMM d yy - hh mm") + ".txt";
266 QFile file(path);
267 if(!file.open(QFile::WriteOnly))
268 return QString();
269
270 file.write(msg.toUtf8());
271 file.close();
272
273 return path;
274 }
275
getTimeString(const QDateTime & dt)276 QString Cutegram::getTimeString(const QDateTime &dt)
277 {
278 if( QDate::currentDate() == dt.date() ) // TODAY
279 return dt.toString("HH:mm");
280 else
281 if( dt.date().daysTo(QDate::currentDate()) < 7 )
282 return dt.toString("ddd HH:mm");
283 else
284 if( dt.date().year() == QDate::currentDate().year() )
285 return dt.toString("dd MMM");
286 else
287 return dt.toString("dd MMM yy");
288 }
289
showMenu(const QStringList & actions,QPoint point)290 int Cutegram::showMenu(const QStringList &actions, QPoint point)
291 {
292 if( point.isNull() )
293 point = QCursor::pos();
294
295 QMenu menu;
296 QList<QAction*> pointers;
297 for( int i=0; i<actions.count(); i++ )
298 pointers << menu.addAction(actions.value(i));
299
300 QAction *res = menu.exec(point);
301 return pointers.indexOf(res);
302 }
303
setDefaultHostAddress(const QString & host)304 void Cutegram::setDefaultHostAddress(const QString &host)
305 {
306 if(p->defaultHostAddress == host)
307 return;
308
309 p->defaultHostAddress = host;
310 emit defaultHostAddressChanged();
311 }
312
defaultHostAddress() const313 QString Cutegram::defaultHostAddress() const
314 {
315 return p->defaultHostAddress;
316 }
317
setDefaultHostPort(int port)318 void Cutegram::setDefaultHostPort(int port)
319 {
320 if(p->defaultHostPort == port)
321 return;
322
323 p->defaultHostPort = port;
324 emit defaultHostPortChanged();
325 }
326
defaultHostPort() const327 int Cutegram::defaultHostPort() const
328 {
329 return p->defaultHostPort;
330 }
331
setDefaultHostDcId(int dcId)332 void Cutegram::setDefaultHostDcId(int dcId)
333 {
334 if(p->defaultHostDcId == dcId)
335 return;
336
337 p->defaultHostDcId = dcId;
338 emit defaultHostDcIdChanged();
339 }
340
defaultHostDcId() const341 int Cutegram::defaultHostDcId() const
342 {
343 return p->defaultHostDcId;
344 }
345
setAppId(int appId)346 void Cutegram::setAppId(int appId)
347 {
348 if(p->appId == appId)
349 return;
350
351 p->appId = appId;
352 emit appIdChanged();
353 }
354
appId() const355 int Cutegram::appId() const
356 {
357 return p->appId;
358 }
359
setAppHash(const QString & appHash)360 void Cutegram::setAppHash(const QString &appHash)
361 {
362 if(p->appHash == appHash)
363 return;
364
365 p->appHash = appHash;
366 emit appHashChanged();
367 }
368
appHash() const369 QString Cutegram::appHash() const
370 {
371 return p->appHash;
372 }
373
start(bool forceVisible)374 void Cutegram::start(bool forceVisible)
375 {
376 if( p->viewer )
377 return;
378
379 p->viewer = new AsemanQuickView();
380 p->viewer->engine()->rootContext()->setContextProperty( "Cutegram", this );
381 p->viewer->setColor(QColor(0,0,0,0));
382 p->viewer->setFlags(Qt::Window|
383 (nativeTitleBar()?Qt::FramelessWindowHint|Qt::NoDropShadowWindowHint:
384 Qt::Widget)|
385 Qt::WindowTitleHint|
386 Qt::WindowSystemMenuHint|
387 Qt::WindowMinMaxButtonsHint|
388 Qt::WindowCloseButtonHint|
389 Qt::WindowFullscreenButtonHint);
390
391 init_theme();
392
393 p->viewer->setSource(QUrl(QStringLiteral("qrc:/qml/Cutegram/main.qml")));
394
395 QPoint point = AsemanApplication::settings()->value("General/position").toPoint();
396 if(!point.isNull())
397 p->viewer->setPosition(point);
398
399 #ifdef Q_OS_WIN
400 QtWin::extendFrameIntoClientArea(p->viewer,-1,-1,-1,-1);
401 #endif
402
403 switch(startupOption())
404 {
405 case StartupAutomatic:
406 if(AsemanApplication::settings()->value("General/lastWindowState",true).toBool())
407 p->viewer->show();
408 break;
409
410 case StartupVisible:
411 p->viewer->show();
412 break;
413
414 case StartupHide:
415 break;
416 }
417
418 if(forceVisible)
419 p->viewer->show();
420
421 p->viewer->installEventFilter(this);
422 init_systray();
423 }
424
restart()425 void Cutegram::restart()
426 {
427 QProcess::startDetached(QCoreApplication::applicationFilePath(), QStringList()<<"--force");
428 quit();
429 }
430
logout(const QString & phone)431 void Cutegram::logout(const QString &phone)
432 {
433 const QString &home = AsemanApplication::homePath();
434 const QString &ppath = home + "/" + phone;
435 QFile::remove(ppath + "/config");
436 QFile::remove(ppath + "/secret");
437 QFile::remove(ppath + "/database.db");
438 QFile::remove(ppath + "/database.db-journal");
439
440 Settings::clearAuth(home, phone);
441
442 restart();
443 }
444
close()445 void Cutegram::close()
446 {
447 p->viewer->close();
448 }
449
quit()450 void Cutegram::quit()
451 {
452 p->closingState = true;
453 emit closingStateChanged();
454
455 QGuiApplication::quit();
456 }
457
contact()458 void Cutegram::contact()
459 {
460 QDesktopServices::openUrl(QUrl("http://aseman.co/en/contact-us/cutegram/"));
461 }
462
aboutAseman()463 void Cutegram::aboutAseman()
464 {
465 emit aboutAsemanRequest();
466 active();
467 }
468
about()469 void Cutegram::about()
470 {
471 p->viewer->root()->setProperty("aboutMode", true);
472 active();
473 }
474
configure()475 void Cutegram::configure()
476 {
477 emit configureRequest();
478 active();
479 }
480
incomingAppMessage(const QString & msg)481 void Cutegram::incomingAppMessage(const QString &msg)
482 {
483 AsemanListRecord record(msg.toUtf8());
484 const QList<QByteArray> &list = record.toQByteArrayList();
485
486 foreach(const QByteArray &data, list)
487 {
488 QString msgPart = data;
489 if( msgPart == "show" )
490 {
491 active();
492 }
493 else
494 if(msgPart.left(5) == "tg://")
495 {
496 const QString &tgMsg = msgPart.mid(5);
497 const int index = tgMsg.indexOf("?");
498 if(index == -1)
499 {
500 const QString &cmd = tgMsg;
501 Q_UNUSED(cmd)
502 return;
503 }
504
505 const QString &cmd = tgMsg.left(index);
506 const QStringList &args = tgMsg.mid(index+1).split("?", QString::SkipEmptyParts);
507 if(cmd.toLower() == "addstickers")
508 {
509 QString set;
510 foreach(const QString &arg, args)
511 {
512 const int index = arg.indexOf("=");
513 if(index < 0)
514 continue;
515
516 const QString &argName = arg.left(index);
517 if(argName == "set")
518 set = arg.mid(index+1);
519 }
520
521 installSticker(set);
522 }
523
524 }
525 }
526 }
527
active()528 void Cutegram::active()
529 {
530 #ifdef Q_OS_WIN
531 QtWin::extendFrameIntoClientArea(p->viewer,-1,-1,-1,-1);
532 #endif
533 p->viewer->show();
534 p->viewer->requestActivate();
535 }
536
addToPersonal(const QString & src)537 void Cutegram::addToPersonal(const QString &src)
538 {
539 QString file = src;
540 if( file.left(AsemanDevices::localFilesPrePath().length()) == AsemanDevices::localFilesPrePath() )
541 file = file.mid(AsemanDevices::localFilesPrePath().length());
542
543 QFile::copy(file, personalStickerDirectory() + "/" + QFileInfo(src).baseName() + ".webp");
544 }
545
installSticker(const QString & shortName)546 void Cutegram::installSticker(const QString &shortName)
547 {
548 QVariant shortNameVar = shortName;
549 QMetaObject::invokeMethod(p->viewer->root(), "installSticker", Q_ARG(QVariant, shortNameVar));
550 active();
551 }
552
savePosition(bool force)553 void Cutegram::savePosition(bool force)
554 {
555 p->save_timer->stop();
556 if(!force)
557 p->save_timer->start();
558 else
559 if(p->viewer)
560 AsemanApplication::settings()->setValue("General/position", p->viewer->position());
561
562 }
563
setSysTrayCounter(int count,bool force)564 void Cutegram::setSysTrayCounter(int count, bool force)
565 {
566 if( count == p->sysTrayCounter && !force )
567 return;
568
569 const QImage & img = generateIcon( QImage(SYSTRAY_ICON), count );
570 if( p->sysTray )
571 {
572 p->sysTray->setIcon( QPixmap::fromImage(img) );
573 }
574 else
575 if( p->unityTray )
576 {
577 QString path = UNITY_ICON_PATH(count);
578 QFile::remove(path);
579 QImageWriter writer(path);
580 writer.write(img);
581 p->unityTray->setIcon(path);
582 }
583
584 p->sysTrayCounter = count;
585 emit sysTrayCounterChanged();
586 }
587
sysTrayCounter() const588 int Cutegram::sysTrayCounter() const
589 {
590 return p->sysTrayCounter;
591 }
592
eventFilter(QObject * o,QEvent * e)593 bool Cutegram::eventFilter(QObject *o, QEvent *e)
594 {
595 if( o == p->viewer )
596 {
597 switch( static_cast<int>(e->type()) )
598 {
599 case QEvent::Move:
600 savePosition(false);
601 break;
602 }
603 }
604
605 return QObject::eventFilter(o,e);
606 }
607
systray_action(QSystemTrayIcon::ActivationReason act)608 void Cutegram::systray_action(QSystemTrayIcon::ActivationReason act)
609 {
610 switch( static_cast<int>(act) )
611 {
612 case QSystemTrayIcon::Trigger:
613 if( p->viewer->isVisible() && p->viewer->isActive() )
614 p->viewer->hide();
615 else
616 {
617 active();
618 }
619 break;
620 }
621 }
622
init_systray()623 void Cutegram::init_systray()
624 {
625 if( p->desktop->desktopSession() == AsemanDesktopTools::Unity || p->desktop->desktopSession() == AsemanDesktopTools::GnomeFallBack )
626 {
627 QFile::remove(UNITY_ICON_PATH(0));
628 QFile::copy(SYSTRAY_ICON,UNITY_ICON_PATH(0));
629
630 p->unityTray = new UnitySystemTray( QCoreApplication::applicationName(), UNITY_ICON_PATH(0) );
631 if( !p->unityTray->pntr() )
632 QGuiApplication::setQuitOnLastWindowClosed(true);
633
634 p->unityTray->addMenu( tr("Show"), this, "active" );
635 p->unityTray->addMenu( tr("Configure"), this, "configure" );
636 p->unityTray->addMenu( tr("Contact"), this, "contact" );
637 p->unityTray->addMenu( tr("About"), this, "about" );
638 p->unityTray->addMenu( tr("About Aseman"), this, "aboutAseman" );
639 p->unityTray->addMenu( tr("Quit"), this, "quit" );
640 }
641 if( !p->unityTray || !p->unityTray->pntr() )
642 {
643 p->sysTray = new QSystemTrayIcon( QIcon(SYSTRAY_ICON), this );
644 p->sysTray->setContextMenu(contextMenu());
645 #if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0))
646 p->sysTray->setToolTip(tr("Cutegram"));
647 #endif
648 #ifndef Q_OS_MAC
649 p->sysTray->show();
650 #endif
651
652 connect( p->sysTray, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), SLOT(systray_action(QSystemTrayIcon::ActivationReason)) );
653 }
654 }
655
contextMenu()656 QMenu *Cutegram::contextMenu()
657 {
658 QMenu *menu = new QMenu();
659 menu->move( QCursor::pos() );
660
661 menu->addAction( tr("Show"), this, SLOT(active()) );
662 menu->addSeparator();
663 menu->addAction( tr("Configure"), this, SLOT(configure()) );
664 menu->addAction( tr("Contact"), this, SLOT(contact()) );
665 menu->addSeparator();
666 menu->addAction( tr("About"), this, SLOT(about()) );
667 menu->addAction( tr("About Aseman"), this, SLOT(aboutAseman()) );
668 menu->addSeparator();
669 menu->addAction( tr("Exit"), this, SLOT(quit()) );
670
671 return menu;
672 }
673
generateIcon(const QImage & img,int count)674 QImage Cutegram::generateIcon(const QImage &img, int count)
675 {
676 QImage res = img;
677 if( count == 0 )
678 return img;
679
680 QRect rct;
681 rct.setX( img.width()/5 );
682 rct.setWidth( 4*img.width()/5 );
683 rct.setY( img.height()-rct.width() );
684 rct.setHeight( rct.width() );
685
686 QPainterPath path;
687 path.addEllipse(rct);
688
689 QPainter painter(&res);
690 painter.setRenderHint( QPainter::Antialiasing , true );
691 painter.fillPath( path, QColor("#ff0000") );
692 painter.setPen("#333333");
693 painter.drawPath( path );
694 painter.setPen("#ffffff");
695 painter.drawText( rct, Qt::AlignCenter | Qt::AlignHCenter, QString::number(count) );
696
697 return res;
698 }
699
languages()700 QStringList Cutegram::languages()
701 {
702 QStringList res = p->languages.keys();
703 res.sort();
704 return res;
705 }
706
setLanguage(const QString & lang)707 void Cutegram::setLanguage(const QString &lang)
708 {
709 if( p->language == lang )
710 return;
711
712 QGuiApplication::removeTranslator(p->translator);
713 p->translator->load(p->languages.value(lang).toString(),"languages");
714 QGuiApplication::installTranslator(p->translator);
715 p->language = lang;
716
717 AsemanApplication::settings()->setValue("General/Language",lang);
718
719 emit languageChanged();
720 emit languageDirectionChanged();
721 }
722
language() const723 QString Cutegram::language() const
724 {
725 return p->language;
726 }
727
closingState() const728 bool Cutegram::closingState() const
729 {
730 return p->closingState;
731 }
732
setStartupOption(int opt)733 void Cutegram::setStartupOption(int opt)
734 {
735 if(opt == p->startupOption)
736 return;
737
738 p->startupOption = opt;
739 AsemanApplication::settings()->setValue("General/startupOption", opt);
740 emit startupOptionChanged();
741 }
742
startupOption() const743 int Cutegram::startupOption() const
744 {
745 return p->startupOption;
746 }
747
setNotification(bool stt)748 void Cutegram::setNotification(bool stt)
749 {
750 if(p->notification == stt)
751 return;
752
753 p->notification = stt;
754 AsemanApplication::settings()->setValue("General/notification", stt);
755 emit notificationChanged();
756 }
757
notification() const758 bool Cutegram::notification() const
759 {
760 return p->notification;
761 }
762
setEmojiOnHover(bool stt)763 void Cutegram::setEmojiOnHover(bool stt)
764 {
765 if(p->emojiOnHover == stt)
766 return;
767
768 p->emojiOnHover = stt;
769 AsemanApplication::settings()->setValue("General/emojiOnHover", stt);
770 emit emojiOnHoverChanged();
771 }
772
emojiOnHover() const773 bool Cutegram::emojiOnHover() const
774 {
775 return p->emojiOnHover;
776 }
777
setMinimumDialogs(bool stt)778 void Cutegram::setMinimumDialogs(bool stt)
779 {
780 if(p->minimumDialogs == stt)
781 return;
782
783 p->minimumDialogs = stt;
784 AsemanApplication::settings()->setValue("General/minimumDialogs", stt);
785 emit minimumDialogsChanged();
786 }
787
minimumDialogs() const788 bool Cutegram::minimumDialogs() const
789 {
790 return p->minimumDialogs;
791 }
792
setShowLastMessage(bool stt)793 void Cutegram::setShowLastMessage(bool stt)
794 {
795 if(p->showLastMessage == stt)
796 return;
797
798 p->showLastMessage = stt;
799 AsemanApplication::settings()->setValue("General/showLastMessage", stt);
800 emit showLastMessageChanged();
801 }
802
showLastMessage() const803 bool Cutegram::showLastMessage() const
804 {
805 return p->showLastMessage;
806 }
807
setDarkSystemTray(bool stt)808 void Cutegram::setDarkSystemTray(bool stt)
809 {
810 if(p->darkSystemTray == stt)
811 return;
812
813 p->darkSystemTray = stt;
814 AsemanApplication::settings()->setValue("General/darkSystemTray", stt);
815
816 setSysTrayCounter(sysTrayCounter(), true);
817 emit darkSystemTrayChanged();
818 }
819
darkSystemTray() const820 bool Cutegram::darkSystemTray() const
821 {
822 return p->darkSystemTray;
823 }
824
setSmoothScroll(bool stt)825 void Cutegram::setSmoothScroll(bool stt)
826 {
827 if(p->smoothScroll == stt)
828 return;
829
830 p->smoothScroll = stt;
831 AsemanApplication::settings()->setValue("General/smoothScroll", stt);
832
833 emit smoothScrollChanged();
834 }
835
smoothScroll() const836 bool Cutegram::smoothScroll() const
837 {
838 return p->smoothScroll;
839 }
840
setKWallet(bool stt)841 void Cutegram::setKWallet(bool stt)
842 {
843 if(p->kWallet == stt)
844 return;
845
846 p->kWallet = stt;
847 AsemanApplication::settings()->setValue("General/kWallet", stt);
848
849 emit kWalletChanged();
850 }
851
kWallet() const852 bool Cutegram::kWallet() const
853 {
854 return p->kWallet;
855 }
856
setNativeTitleBar(bool stt)857 void Cutegram::setNativeTitleBar(bool stt)
858 {
859 if(p->nativeTitleBar == stt)
860 return;
861
862 p->nativeTitleBar = stt;
863 AsemanApplication::settings()->setValue("General/nativeTitleBar", stt);
864
865 emit nativeTitleBarChanged();
866 }
867
nativeTitleBar() const868 bool Cutegram::nativeTitleBar() const
869 {
870 return p->nativeTitleBar;
871 }
872
allowNativeTitleBar() const873 bool Cutegram::allowNativeTitleBar() const
874 {
875 #ifdef Q_OS_MACX
876 #if (QT_VERSION >= QT_VERSION_CHECK(5, 4, 0))
877 switch(static_cast<int>(QSysInfo::macVersion()))
878 {
879 case QSysInfo::MV_YOSEMITE:
880 case QSysInfo::MV_ELCAPITAN:
881 return true;
882 break;
883 }
884 #endif
885 #endif
886 return false;
887 }
888
setBackground(const QString & background)889 void Cutegram::setBackground(const QString &background)
890 {
891 if(p->background == background)
892 return;
893
894 p->background = background;
895 AsemanApplication::settings()->setValue("General/background", background);
896 emit backgroundChanged();
897 }
898
background() const899 QString Cutegram::background() const
900 {
901 return p->background;
902 }
903
setMessageAudio(const QString & file)904 void Cutegram::setMessageAudio(const QString &file)
905 {
906 if(p->messageAudio == file)
907 return;
908
909 p->messageAudio = file;
910 AsemanApplication::settings()->setValue("General/messageAudio", file);
911 emit messageAudioChanged();
912 }
913
messageAudio() const914 QString Cutegram::messageAudio() const
915 {
916 return p->messageAudio;
917 }
918
setMasterColor(const QString & color)919 void Cutegram::setMasterColor(const QString &color)
920 {
921 if(p->masterColor == color)
922 return;
923
924 p->masterColor = color;
925 AsemanApplication::settings()->setValue("General/masterColor", color);
926
927 emit masterColorChanged();
928 emit highlightColorChanged();
929 }
930
masterColor() const931 QString Cutegram::masterColor() const
932 {
933 return p->masterColor;
934 }
935
highlightColor() const936 QColor Cutegram::highlightColor() const
937 {
938 return p->masterColor.isEmpty()? p->highlightColor : QColor(p->masterColor);
939 }
940
setHighlightColor(const QColor & color)941 void Cutegram::setHighlightColor(const QColor &color)
942 {
943 if(p->highlightColor == color)
944 return;
945
946 p->highlightColor = color;
947 AsemanApplication::settings()->setValue("General/lastHighlightColor", color.name());
948
949 emit highlightColorChanged();
950 }
951
setFont(const QFont & font)952 void Cutegram::setFont(const QFont &font)
953 {
954 if(p->font == font)
955 return;
956
957 p->font = font;
958 AsemanApplication::settings()->setValue("General/font", font);
959 emit fontChanged();
960 }
961
font() const962 QFont Cutegram::font() const
963 {
964 return p->font;
965 }
966
setAsemanSubscribe(bool stt)967 void Cutegram::setAsemanSubscribe(bool stt)
968 {
969 if(p->cutegramSubscribe == stt)
970 return;
971
972 p->cutegramSubscribe = stt;
973 AsemanApplication::settings()->setValue("General/cutegramSubscribe", stt);
974
975 emit cutegramSubscribeChanged();
976 }
977
cutegramSubscribe() const978 bool Cutegram::cutegramSubscribe() const
979 {
980 return p->cutegramSubscribe;
981 }
982
setAutoEmojis(bool stt)983 void Cutegram::setAutoEmojis(bool stt)
984 {
985 if(p->autoEmojis == stt)
986 return;
987
988 p->autoEmojis = stt;
989 AsemanApplication::settings()->setValue("General/autoEmojis", stt);
990
991 emit autoEmojisChanged();
992 }
993
autoEmojis() const994 bool Cutegram::autoEmojis() const
995 {
996 return p->autoEmojis;
997 }
998
setSendByCtrlEnter(bool stt)999 void Cutegram::setSendByCtrlEnter(bool stt)
1000 {
1001 if(p->sendByCtrlEnter == stt)
1002 return;
1003
1004 p->sendByCtrlEnter = stt;
1005 AsemanApplication::settings()->setValue("General/sendByCtrlEnter", stt);
1006
1007 emit sendByCtrlEnterChanged();
1008 }
1009
sendByCtrlEnter() const1010 bool Cutegram::sendByCtrlEnter() const
1011 {
1012 return p->sendByCtrlEnter;
1013 }
1014
setStatusIconStyle(int style)1015 void Cutegram::setStatusIconStyle(int style)
1016 {
1017 if(p->statusIconStyle == style)
1018 return;
1019
1020 p->statusIconStyle = style;
1021 AsemanApplication::settings()->setValue(SYSTRAY_ICON_STATUS, style);
1022
1023 emit cutegramSubscribeChanged();
1024
1025 setSysTrayCounter(sysTrayCounter(), true);
1026 }
1027
statusIconStyle()1028 int Cutegram::statusIconStyle()
1029 {
1030 return p->statusIconStyle;
1031 }
1032
themes() const1033 QStringList Cutegram::themes() const
1034 {
1035 return p->themes;
1036 }
1037
setTheme(const QString & theme)1038 void Cutegram::setTheme(const QString &theme)
1039 {
1040 if(p->theme == theme)
1041 return;
1042
1043 p->theme = theme;
1044 AsemanApplication::settings()->setValue("General/theme",p->theme);
1045 init_theme();
1046
1047 emit themeChanged();
1048 }
1049
theme() const1050 QString Cutegram::theme() const
1051 {
1052 return p->theme;
1053 }
1054
currentTheme()1055 ThemeItem *Cutegram::currentTheme()
1056 {
1057 return p->currentTheme;
1058 }
1059
emojisThemes() const1060 QStringList Cutegram::emojisThemes() const
1061 {
1062 return p->emojisThemes;
1063 }
1064
setEmojisTheme(const QString & theme)1065 void Cutegram::setEmojisTheme(const QString& theme)
1066 {
1067 if (p->emojisTheme == theme)
1068 return;
1069
1070 p->emojisTheme = theme;
1071 AsemanApplication::settings()->setValue("General/emojisTheme", p->emojisTheme);
1072
1073 emit emojisThemeChanged();
1074 }
1075
emojisTheme() const1076 QString Cutegram::emojisTheme() const
1077 {
1078 return p->emojisTheme;
1079 }
1080
searchEngines() const1081 QStringList Cutegram::searchEngines() const
1082 {
1083 return p->searchEngines;
1084 }
1085
setSearchEngine(const QString & se)1086 void Cutegram::setSearchEngine(const QString &se)
1087 {
1088 if(p->searchEngine == se)
1089 return;
1090
1091 p->searchEngine = se;
1092 AsemanApplication::settings()->setValue("General/searchEngine",p->searchEngine);
1093 init_theme();
1094
1095 emit searchEngineChanged();
1096 }
1097
searchEngine() const1098 QString Cutegram::searchEngine() const
1099 {
1100 return p->searchEngine;
1101 }
1102
personalStickerDirectory() const1103 QString Cutegram::personalStickerDirectory() const
1104 {
1105 return AsemanApplication::homePath() + "/stickers/Personal";
1106 }
1107
encrypter()1108 DatabaseAbstractEncryptor *Cutegram::encrypter()
1109 {
1110 return &p->encrypter;
1111 }
1112
setEncrypterKey(const QString & key)1113 void Cutegram::setEncrypterKey(const QString &key)
1114 {
1115 p->encrypter.setKey(key);
1116 }
1117
isLoggedIn(const QString & phone) const1118 bool Cutegram::isLoggedIn(const QString &phone) const
1119 {
1120 const QString &home = AsemanApplication::homePath();
1121 const QString &ppath = home + "/" + phone;
1122 return QFile::exists(ppath + "/auth");
1123 }
1124
normalizeText(const QString & text) const1125 QString Cutegram::normalizeText(const QString &text) const
1126 {
1127 if(text.isEmpty())
1128 return text;
1129
1130 return text[0].toUpper() + text.mid(1);
1131 }
1132
init_languages()1133 void Cutegram::init_languages()
1134 {
1135 QDir dir(p->translationsPath);
1136 QStringList languages = dir.entryList( QDir::Files );
1137 if( !languages.contains("lang-en.qm") )
1138 languages.prepend("lang-en.qm");
1139
1140 for( int i=0 ; i<languages.size() ; i++ )
1141 {
1142 QString locale_str = languages[i];
1143 locale_str.truncate( locale_str.lastIndexOf('.') );
1144 locale_str.remove( 0, locale_str.indexOf('-') + 1 );
1145
1146 QLocale locale(locale_str);
1147
1148 QString lang = QString("%1 (%2)").arg(QLocale::languageToString(locale.language()), QLocale::countryToString(locale.country()));
1149 QVariant data = p->translationsPath + "/" + languages[i];
1150
1151 p->languages.insert( lang, data );
1152 p->locales.insert( lang , locale );
1153
1154 if( lang == AsemanApplication::settings()->value("General/Language","English (UnitedStates)").toString() )
1155 setLanguage( lang );
1156 }
1157 }
1158
init_theme()1159 void Cutegram::init_theme()
1160 {
1161 if(p->currentThemeComponent)
1162 p->currentThemeComponent->deleteLater();
1163 if(p->currentTheme)
1164 p->currentTheme->deleteLater();
1165
1166 p->currentThemeComponent = new QQmlComponent(p->viewer->engine(), p->themesPath + "/" + p->theme);
1167 p->currentTheme = static_cast<ThemeItem*>(p->currentThemeComponent->create());
1168 if(!p->currentTheme)
1169 qDebug() << p->currentThemeComponent->errorString();
1170
1171 emit currentThemeChanged();
1172 }
1173
lowLevelDarkSystemTray()1174 bool Cutegram::lowLevelDarkSystemTray()
1175 {
1176 switch(p->statusIconStyle)
1177 {
1178 case StatusIconAutomatic:
1179 return darkSystemTray();
1180 break;
1181
1182 case StatusIconDark:
1183 return true;
1184 break;
1185
1186 case StatusIconLight:
1187 return false;
1188 break;
1189 }
1190
1191 return darkSystemTray();
1192 }
1193
intListToVariantList(const QList<qint32> & list)1194 QVariantList Cutegram::intListToVariantList(const QList<qint32> &list)
1195 {
1196 QVariantList res;
1197 foreach(const qint32 u, list)
1198 res << u;
1199
1200 return res;
1201 }
1202
variantListToIntList(const QVariantList & list)1203 QList<qint32> Cutegram::variantListToIntList(const QVariantList &list)
1204 {
1205 QList<qint32> res;
1206 foreach(const QVariant &l, list)
1207 res << l.toInt();
1208
1209 return res;
1210 }
1211
~Cutegram()1212 Cutegram::~Cutegram()
1213 {
1214 delete p;
1215 }
1216