void Window::notifySchedule(History *history, MsgId msgId) { if (App::quiting() || !history->currentNotification()) return; bool haveSetting = (history->peer->notify != UnknownNotifySettings); if (haveSetting) { if (history->peer->notify != EmptyNotifySettings && history->peer->notify->mute > unixtime()) { history->clearNotifications(); return; } } else { App::wnd()->getNotifySetting(MTP_inputNotifyPeer(history->peer->input)); } uint64 ms = getms(true) + NotifyWaitTimeout; notifyWhenAlerts[history].insert(ms, NullType()); if (cDesktopNotify()) { NotifyWhenMaps::iterator i = notifyWhenMaps.find(history); if (i == notifyWhenMaps.end()) { i = notifyWhenMaps.insert(history, NotifyWhenMap()); } if (i.value().constFind(msgId) == i.value().cend()) { i.value().insert(msgId, ms); } NotifyWaiters *addTo = haveSetting ? ¬ifyWaiters : ¬ifySettingWaiters; if (addTo->constFind(history) == addTo->cend()) { addTo->insert(history, NotifyWaiter(msgId, ms)); } } if (haveSetting) { if (!notifyWaitTimer.isActive()) { notifyWaitTimer.start(NotifyWaitTimeout); } } }
void Window::notifyShowNext(NotifyWindow *remove) { if (App::quiting()) return; int32 count = NotifyWindowsCount; if (remove) { for (NotifyWindows::iterator i = notifyWindows.begin(), e = notifyWindows.end(); i != e; ++i) { if ((*i) == remove) { notifyWindows.erase(i); break; } } } uint64 ms = getms(true), nextAlert = 0; bool alert = false; for (NotifyWhenAlerts::iterator i = notifyWhenAlerts.begin(); i != notifyWhenAlerts.end();) { while (!i.value().isEmpty() && i.value().begin().key() <= ms) { i.value().erase(i.value().begin()); NotifySettingsPtr n = i.key()->peer->notify; if (n == EmptyNotifySettings || (n != UnknownNotifySettings && n->mute <= unixtime())) { alert = true; } } if (i.value().isEmpty()) { i = notifyWhenAlerts.erase(i); } else { if (!nextAlert || nextAlert > i.value().begin().key()) { nextAlert = i.value().begin().key(); } ++i; } } if (alert) { psFlash(); App::playSound(); } if (cCustomNotifies()) { for (NotifyWindows::const_iterator i = notifyWindows.cbegin(), e = notifyWindows.cend(); i != e; ++i) { int32 ind = (*i)->index(); if (ind < 0) continue; --count; } } if (count <= 0 || !cDesktopNotify()) { if (nextAlert) { notifyWaitTimer.start(nextAlert - ms); } return; } QRect r = psDesktopRect(); int32 x = r.x() + r.width() - st::notifyWidth - st::notifyDeltaX, y = r.y() + r.height() - st::notifyHeight - st::notifyDeltaY; while (count > 0) { uint64 next = 0; HistoryItem *notifyItem = 0; NotifyWaiters::iterator notifyWaiter; for (NotifyWaiters::iterator i = notifyWaiters.begin(); i != notifyWaiters.end(); ++i) { History *history = i.key(); if (history->currentNotification() && history->currentNotification()->id != i.value().msg) { NotifyWhenMaps::iterator j = notifyWhenMaps.find(history); if (j == notifyWhenMaps.end()) { history->clearNotifications(); i = notifyWaiters.erase(i); continue; } do { NotifyWhenMap::const_iterator k = j.value().constFind(history->currentNotification()->id); if (k != j.value().cend()) { i.value().msg = k.key(); i.value().when = k.value(); break; } history->skipNotification(); } while (history->currentNotification()); } if (!history->currentNotification()) { notifyWhenMaps.remove(history); i = notifyWaiters.erase(i); continue; } uint64 when = i.value().when; if (!notifyItem || next > when) { next = when; notifyItem = history->currentNotification(); notifyWaiter = i; } } if (notifyItem) { if (next > ms) { if (nextAlert && nextAlert < next) { next = nextAlert; nextAlert = 0; } notifyWaitTimer.start(next - ms); break; } else { if (cCustomNotifies()) { NotifyWindow *notify = new NotifyWindow(notifyItem, x, y); notifyWindows.push_back(notify); psNotifyShown(notify); --count; } else { psPlatformNotify(notifyItem); } uint64 ms = getms(true); History *history = notifyItem->history(); history->skipNotification(); NotifyWhenMaps::iterator j = notifyWhenMaps.find(history); if (j == notifyWhenMaps.end() || !history->currentNotification()) { history->clearNotifications(); notifyWaiters.erase(notifyWaiter); if (j != notifyWhenMaps.end()) notifyWhenMaps.erase(j); continue; } j.value().remove(notifyItem->id); do { NotifyWhenMap::const_iterator k = j.value().constFind(history->currentNotification()->id); if (k != j.value().cend()) { notifyWaiter.value().msg = k.key(); notifyWaiter.value().when = k.value(); break; } history->skipNotification(); } while (history->currentNotification()); if (!history->currentNotification()) { notifyWaiters.erase(notifyWaiter); notifyWhenMaps.erase(j); continue; } } } else { break; } } if (nextAlert) { notifyWaitTimer.start(nextAlert - ms); } count = NotifyWindowsCount - count; for (NotifyWindows::const_iterator i = notifyWindows.cbegin(), e = notifyWindows.cend(); i != e; ++i) { int32 ind = (*i)->index(); if (ind < 0) continue; --count; (*i)->moveTo(x, y - count * (st::notifyHeight + st::notifyDeltaY)); } }
SettingsInner::SettingsInner(Settings *parent) : QWidget(parent), _self(App::self()), // profile _nameCache(_self ? _self->name : QString()), _phoneText(_self ? App::formatPhone(_self->phone) : QString()), _uploadPhoto(this, lang(lng_settings_upload), st::btnSetUpload), _cancelPhoto(this, lang(lng_cancel)), _nameOver(false), _photoOver(false), a_photo(0), // notifications _desktopNotify(this, lang(lng_settings_desktop_notify), cDesktopNotify()), _soundNotify(this, lang(lng_settings_sound_notify), cSoundNotify()), // general _autoUpdate(this, lang(lng_settings_auto_update), cAutoUpdate()), _checkNow(this, lang(lng_settings_check_now)), _restartNow(this, lang(lng_settings_update_now)), _workmodeTray(this, lang(lng_settings_workmode_tray), (cWorkMode() == dbiwmTrayOnly || cWorkMode() == dbiwmWindowAndTray)), _workmodeWindow(this, lang(lng_settings_workmode_window), (cWorkMode() == dbiwmWindowOnly || cWorkMode() == dbiwmWindowAndTray)), _autoStart(this, lang(lng_settings_auto_start), cAutoStart()), _startMinimized(this, lang(lng_settings_start_min), cStartMinimized()), _dpiAutoScale(this, lang(lng_settings_scale_auto).replace(qsl("{cur}"), scaleLabel(cScreenScale())), (cConfigScale() == dbisAuto)), _dpiSlider(this, st::dpiSlider, dbisScaleCount - 1, cEvalScale(cConfigScale()) - 1), _dpiWidth1(st::dpiFont1->m.width(scaleLabel(dbisOne))), _dpiWidth2(st::dpiFont2->m.width(scaleLabel(dbisOneAndQuarter))), _dpiWidth3(st::dpiFont3->m.width(scaleLabel(dbisOneAndHalf))), _dpiWidth4(st::dpiFont4->m.width(scaleLabel(dbisTwo))), // chat options _replaceEmojis(this, lang(lng_settings_replace_emojis), cReplaceEmojis()), _viewEmojis(this, lang(lng_settings_view_emojis)), _enterSend(this, qsl("send_key"), 0, lang(lng_settings_send_enter), !cCtrlEnter()), _ctrlEnterSend(this, qsl("send_key"), 1, lang((cPlatform() == dbipMac) ? lng_settings_send_cmdenter : lng_settings_send_ctrlenter), cCtrlEnter()), _dontAskDownloadPath(this, lang(lng_download_path_dont_ask), !cAskDownloadPath()), _downloadPathWidth(st::linkFont->m.width(lang(lng_download_path_label))), _downloadPathEdit(this, cDownloadPath().isEmpty() ? lang(lng_download_path_temp) : st::linkFont->m.elidedText(QDir::toNativeSeparators(cDownloadPath()), Qt::ElideRight, st::setWidth - st::setVersionLeft - _downloadPathWidth)), _downloadPathClear(this, lang(lng_download_path_clear)), _tempDirClearingWidth(st::linkFont->m.width(lang(lng_download_path_clearing))), _tempDirClearedWidth(st::linkFont->m.width(lang(lng_download_path_cleared))), _tempDirClearFailedWidth(st::linkFont->m.width(lang(lng_download_path_clear_failed))), _catsAndDogs(this, lang(lng_settings_cats_and_dogs), cCatsAndDogs()), _scrollNotActive(this, lang(lng_settings_scroll_not_active), cScrollNotActive()), // advanced _connectionType(this, lang(lng_connection_auto)), _resetSessions(this, lang(lng_settings_reset)), _logOut(this, lang(lng_settings_logout), st::btnLogout), _resetDone(false) { if (_self) { _nameText.setText(st::setNameFont, _nameCache, _textNameOptions); PhotoData *selfPhoto = _self->photoId ? App::photo(_self->photoId) : 0; if (selfPhoto && selfPhoto->date) _photoLink = TextLinkPtr(new PhotoLink(selfPhoto)); MTP::send(MTPusers_GetFullUser(_self->inputUser), rpcDone(&SettingsInner::gotFullSelf)); connect(App::main(), SIGNAL(peerPhotoChanged(PeerData *)), this, SLOT(peerUpdated(PeerData *))); connect(App::main(), SIGNAL(peerNameChanged(PeerData *, const PeerData::Names &, const PeerData::NameFirstChars &)), this, SLOT(peerUpdated(PeerData *))); } // profile connect(&_uploadPhoto, SIGNAL(clicked()), this, SLOT(onUpdatePhoto())); connect(&_cancelPhoto, SIGNAL(clicked()), this, SLOT(onUpdatePhotoCancel())); connect(App::app(), SIGNAL(peerPhotoDone(PeerId)), this, SLOT(onPhotoUpdateDone(PeerId))); connect(App::app(), SIGNAL(peerPhotoFail(PeerId)), this, SLOT(onPhotoUpdateFail(PeerId))); // notifications connect(&_desktopNotify, SIGNAL(changed()), this, SLOT(onDesktopNotify())); connect(&_soundNotify, SIGNAL(changed()), this, SLOT(onSoundNotify())); // general connect(&_autoUpdate, SIGNAL(changed()), this, SLOT(onAutoUpdate())); connect(&_checkNow, SIGNAL(clicked()), this, SLOT(onCheckNow())); connect(&_restartNow, SIGNAL(clicked()), this, SLOT(onRestartNow())); connect(&_workmodeTray, SIGNAL(changed()), this, SLOT(onWorkmodeTray())); connect(&_workmodeWindow, SIGNAL(changed()), this, SLOT(onWorkmodeWindow())); _startMinimized.setDisabled(!_autoStart.checked()); connect(&_autoStart, SIGNAL(changed()), this, SLOT(onAutoStart())); connect(&_startMinimized, SIGNAL(changed()), this, SLOT(onStartMinimized())); connect(&_dpiAutoScale, SIGNAL(changed()), this, SLOT(onScaleAuto())); connect(&_dpiSlider, SIGNAL(changed(int32)), this, SLOT(onScaleChange())); _curVersionText = lang(lng_settings_current_version).replace(qsl("{version}"), QString::fromWCharArray(AppVersionStr)) + ' '; _curVersionWidth = st::linkFont->m.width(_curVersionText); _newVersionText = lang(lng_settings_update_ready) + ' '; _newVersionWidth = st::linkFont->m.width(_newVersionText); connect(App::app(), SIGNAL(updateChecking()), this, SLOT(onUpdateChecking())); connect(App::app(), SIGNAL(updateLatest()), this, SLOT(onUpdateLatest())); connect(App::app(), SIGNAL(updateDownloading(qint64,qint64)), this, SLOT(onUpdateDownloading(qint64,qint64))); connect(App::app(), SIGNAL(updateReady()), this, SLOT(onUpdateReady())); connect(App::app(), SIGNAL(updateFailed()), this, SLOT(onUpdateFailed())); // chat options connect(&_replaceEmojis, SIGNAL(changed()), this, SLOT(onReplaceEmojis())); connect(&_viewEmojis, SIGNAL(clicked()), this, SLOT(onViewEmojis())); connect(&_enterSend, SIGNAL(changed()), this, SLOT(onEnterSend())); connect(&_ctrlEnterSend, SIGNAL(changed()), this, SLOT(onCtrlEnterSend())); connect(&_dontAskDownloadPath, SIGNAL(changed()), this, SLOT(onDontAskDownloadPath())); connect(&_downloadPathEdit, SIGNAL(clicked()), this, SLOT(onDownloadPathEdit())); connect(&_downloadPathClear, SIGNAL(clicked()), this, SLOT(onDownloadPathClear())); switch (App::wnd()->tempDirState()) { case Window::TempDirEmpty: _tempDirClearState = TempDirEmpty; break; case Window::TempDirExists: _tempDirClearState = TempDirExists; break; case Window::TempDirRemoving: _tempDirClearState = TempDirClearing; break; } connect(App::wnd(), SIGNAL(tempDirCleared()), this, SLOT(onTempDirCleared())); connect(App::wnd(), SIGNAL(tempDirClearFailed()), this, SLOT(onTempDirClearFailed())); connect(&_catsAndDogs, SIGNAL(changed()), this, SLOT(onCatsAndDogs())); connect(&_scrollNotActive, SIGNAL(changed()), this, SLOT(onScrollNotActive())); // advanced connect(&_connectionType, SIGNAL(clicked()), this, SLOT(onConnectionType())); connect(&_resetSessions, SIGNAL(clicked()), this, SLOT(onResetSessions())); connect(&_logOut, SIGNAL(clicked()), this, SLOT(onLogout())); _connectionTypeText = lang(lng_connection_type) + ' '; _connectionTypeWidth = st::linkFont->m.width(_connectionTypeText); if (App::main()) { connect(App::main(), SIGNAL(peerUpdated(PeerData*)), this, SLOT(peerUpdated(PeerData*))); } updateOnlineDisplay(); switch (App::app()->updatingState()) { case Application::UpdatingDownload: setUpdatingState(UpdatingDownload, true); setDownloadProgress(App::app()->updatingReady(), App::app()->updatingSize()); break; case Application::UpdatingReady: setUpdatingState(UpdatingReady, true); break; default: setUpdatingState(UpdatingNone, true); break; } updateConnectionType(); setMouseTracking(true); }