2
0
mirror of https://github.com/kotatogram/kotatogram-desktop synced 2025-08-31 14:45:14 +00:00

search merged to os x version, fixed some retina render, custom notifies code moved to window module

This commit is contained in:
John Preston
2014-07-06 07:32:21 +04:00
parent 29d6bf46c8
commit 1167117ee0
38 changed files with 743 additions and 3679 deletions

View File

@@ -44,7 +44,7 @@ namespace {
void MacPrivate::activeSpaceChanged() {
if (App::wnd()) {
App::wnd()->psActivateNotifies();
App::wnd()->notifyActivateAll();
}
}
@@ -54,7 +54,7 @@ void MacPrivate::notifyClicked(unsigned long long peer) {
App::wnd()->showFromTray();
App::wnd()->hideSettings();
App::main()->showPeer(history->peer->id, false, true);
App::wnd()->psClearNotify(history);
App::wnd()->notifyClear(history);
}
void MacPrivate::notifyReplied(unsigned long long peer, const char *str) {
@@ -67,8 +67,6 @@ PsMainWindow::PsMainWindow(QWidget *parent) : QMainWindow(parent),
posInited(false), trayIcon(0), trayIconMenu(0), icon256(qsl(":/gui/art/iconround256.png")) {
connect(&psIdleTimer, SIGNAL(timeout()), this, SLOT(psIdleTimeout()));
psIdleTimer.setSingleShot(false);
connect(&notifyWaitTimer, SIGNAL(timeout()), this, SLOT(psNotifyFire()));
notifyWaitTimer.setSingleShot(true);
}
void PsMainWindow::psNotIdle() const {
@@ -287,497 +285,39 @@ void PsMainWindow::psFlash() {
PsMainWindow::~PsMainWindow() {
finished = true;
psClearNotifyFast();
}
void PsMainWindow::psNotify(History *history, MsgId msgId) {
if (App::quiting() || !history->notifyFrom) return;
bool haveSetting = (history->peer->notify != UnknownNotifySettings);
if (haveSetting) {
if (history->peer->notify != EmptyNotifySettings && history->peer->notify->mute > unixtime()) {
history->clearNotifyFrom();
return;
}
} else {
App::wnd()->getNotifySetting(MTP_inputNotifyPeer(history->peer->input));
}
uint64 ms = getms() + NotifyWaitTimeout;
notifyWhenAlerts[history].insert(ms);
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 ? &notifyWaiters : &notifySettingWaiters;
if (addTo->constFind(history) == addTo->cend()) {
addTo->insert(history, NotifyWaiter(msgId, ms));
}
}
if (haveSetting) {
if (!notifyWaitTimer.isActive()) {
notifyWaitTimer.start(NotifyWaitTimeout);
}
}
void PsMainWindow::psClearNotifies(PeerId peerId) {
_private.clearNotifies(peerId);
}
void PsMainWindow::psNotifyFire() {
psShowNextNotify();
}
void PsMainWindow::psNotifySettingGot() {
int32 t = unixtime();
for (NotifyWaiters::iterator i = notifySettingWaiters.begin(); i != notifySettingWaiters.end();) {
History *history = i.key();
if (history->peer->notify == UnknownNotifySettings) {
++i;
} else {
if (history->peer->notify == EmptyNotifySettings || history->peer->notify->mute <= t) {
notifyWaiters.insert(i.key(), i.value());
}
i = notifySettingWaiters.erase(i);
}
}
notifyWaitTimer.stop();
psShowNextNotify();
}
void PsMainWindow::psClearNotify(History *history) {
if (!history) {
for (PsNotifyWindows::const_iterator i = notifyWindows.cbegin(), e = notifyWindows.cend(); i != e; ++i) {
(*i)->unlinkHistory();
}
_private.clearNotifies();
for (NotifyWhenMaps::const_iterator i = notifyWhenMaps.cbegin(), e = notifyWhenMaps.cend(); i != e; ++i) {
i.key()->clearNotifyFrom();
}
notifyWaiters.clear();
notifySettingWaiters.clear();
notifyWhenMaps.clear();
return;
}
notifyWaiters.remove(history);
notifySettingWaiters.remove(history);
for (PsNotifyWindows::const_iterator i = notifyWindows.cbegin(), e = notifyWindows.cend(); i != e; ++i) {
(*i)->unlinkHistory(history);
}
_private.clearNotifies(history->peer->id);
notifyWhenMaps.remove(history);
notifyWhenAlerts.remove(history);
}
void PsMainWindow::psClearNotifyFast() {
notifyWaiters.clear();
notifySettingWaiters.clear();
for (PsNotifyWindows::const_iterator i = notifyWindows.cbegin(), e = notifyWindows.cend(); i != e; ++i) {
(*i)->deleteLater();
}
_private.clearNotifies();
notifyWindows.clear();
notifyWhenMaps.clear();
notifyWhenAlerts.clear();
}
void PsMainWindow::psActivateNotifies() {
if (cCustomNotifies()) {
for (PsNotifyWindows::const_iterator i = notifyWindows.cbegin(), e = notifyWindows.cend(); i != e; ++i) {
_private.activateWnd((*i)->winId());
}
}
void PsMainWindow::psActivateNotify(NotifyWindow *w) {
_private.activateWnd(w->winId());
}
namespace {
QRect _monitorRect;
uint64 _monitorLastGot = 0;
QRect _desktopRect() {
uint64 tnow = getms();
if (tnow > _monitorLastGot + 1000 || tnow < _monitorLastGot) {
_monitorLastGot = tnow;
_monitorRect = QApplication::desktop()->availableGeometry(App::wnd());
}
return _monitorRect;
}
QRect psDesktopRect() {
uint64 tnow = getms();
if (tnow > _monitorLastGot + 1000 || tnow < _monitorLastGot) {
_monitorLastGot = tnow;
_monitorRect = QApplication::desktop()->availableGeometry(App::wnd());
}
return _monitorRect;
}
void PsMainWindow::psShowNextNotify(PsNotifyWindow *remove) {
if (App::quiting()) return;
int32 count = NotifyWindows;
if (remove) {
for (PsNotifyWindows::iterator i = notifyWindows.begin(), e = notifyWindows.end(); i != e; ++i) {
if ((*i) == remove) {
notifyWindows.erase(i);
break;
}
}
}
uint64 ms = getms(), nextAlert = 0;
bool alert = false;
for (NotifyWhenAlerts::iterator i = notifyWhenAlerts.begin(); i != notifyWhenAlerts.end();) {
while (!i.value().isEmpty() && *i.value().begin() <= 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()) {
nextAlert = *i.value().begin();
}
++i;
}
}
if (alert) {
psFlash();
App::playSound();
}
if (cCustomNotifies()) {
for (PsNotifyWindows::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 = _desktopRect();
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->notifyFrom && history->notifyFrom->id != i.value().msg) {
NotifyWhenMaps::iterator j = notifyWhenMaps.find(history);
if (j == notifyWhenMaps.end()) {
history->clearNotifyFrom();
i = notifyWaiters.erase(i);
continue;
}
do {
NotifyWhenMap::const_iterator k = j.value().constFind(history->notifyFrom->id);
if (k != j.value().cend()) {
i.value().msg = k.key();
i.value().when = k.value();
break;
}
history->getNextNotifyFrom();
} while (history->notifyFrom);
}
if (!history->notifyFrom) {
notifyWhenMaps.remove(history);
i = notifyWaiters.erase(i);
continue;
}
uint64 when = i.value().when;
if (!notifyItem || next > when) {
next = when;
notifyItem = history->notifyFrom;
notifyWaiter = i;
}
}
if (notifyItem) {
if (next > ms) {
if (nextAlert && nextAlert < next) {
next = nextAlert;
nextAlert = 0;
}
notifyWaitTimer.start(next - ms);
break;
} else {
if (cCustomNotifies()) {
PsNotifyWindow *notify = new PsNotifyWindow(notifyItem, x, y);
notifyWindows.push_back(notify);
notify->hide();
_private.holdOnTop(notify->winId());
notify->show();
_private.showOverAll(notify->winId());
--count;
} else {
_private.showNotify(notifyItem->history()->peer->id, notifyItem->history()->peer->name, notifyItem->notificationHeader(), notifyItem->notificationText());
}
uint64 ms = getms();
History *history = notifyItem->history();
history->getNextNotifyFrom();
NotifyWhenMaps::iterator j = notifyWhenMaps.find(history);
if (j == notifyWhenMaps.end() || !history->notifyFrom) {
history->clearNotifyFrom();
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->notifyFrom->id);
if (k != j.value().cend()) {
notifyWaiter.value().msg = k.key();
notifyWaiter.value().when = k.value();
break;
}
history->getNextNotifyFrom();
} while (history->notifyFrom);
if (!history->notifyFrom) {
notifyWaiters.erase(notifyWaiter);
notifyWhenMaps.erase(j);
continue;
}
}
} else {
break;
}
}
if (nextAlert) {
notifyWaitTimer.start(nextAlert - ms);
}
count = NotifyWindows - count;
for (PsNotifyWindows::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));
}
void PsMainWindow::psNotifyShown(NotifyWindow *w) {
w->hide();
_private.holdOnTop(w->winId());
w->show();
_private.showOverAll(w->winId());
}
void PsMainWindow::psStopHiding() {
if (cCustomNotifies()) {
for (PsNotifyWindows::const_iterator i = notifyWindows.cbegin(), e = notifyWindows.cend(); i != e; ++i) {
(*i)->stopHiding();
}
}
}
void PsMainWindow::psStartHiding() {
if (cCustomNotifies()) {
for (PsNotifyWindows::const_iterator i = notifyWindows.cbegin(), e = notifyWindows.cend(); i != e; ++i) {
(*i)->startHiding();
}
}
}
void PsMainWindow::psUpdateNotifies() {
if (cCustomNotifies()) {
for (PsNotifyWindows::const_iterator i = notifyWindows.cbegin(), e = notifyWindows.cend(); i != e; ++i) {
(*i)->updatePeerPhoto();
}
}
}
PsNotifyWindow::PsNotifyWindow(HistoryItem *item, int32 x, int32 y) : history(item->history()),// started(GetTickCount()),
close(this, st::notifyClose), alphaDuration(st::notifyFastAnim), posDuration(st::notifyFastAnim), hiding(false), _index(0), aOpacity(0), aOpacityFunc(st::notifyFastAnimFunc), aY(y + st::notifyHeight + st::notifyDeltaY) {
int32 w = st::notifyWidth, h = st::notifyHeight;
QImage img(w * cIntRetinaFactor(), h * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied);
if (cRetina()) img.setDevicePixelRatio(cRetinaFactor());
img.fill(st::notifyBG->c);
{
QPainter p(&img);
p.setPen(st::notifyBorder->p);
p.setBrush(Qt::NoBrush);
p.drawRect(0, 0, w - 1, h - 1);
if (history->peer->photo->loaded()) {
p.drawPixmap(st::notifyPhotoPos.x(), st::notifyPhotoPos.y(), history->peer->photo->pix(st::notifyPhotoSize));
} else {
MTP::clearLoaderPriorities();
peerPhoto = history->peer->photo;
peerPhoto->load(true, true);
}
int32 itemWidth = w - st::notifyPhotoPos.x() - st::notifyPhotoSize - st::notifyTextLeft - st::notifyClosePos.x() - st::notifyClose.width;
QRect rectForName(st::notifyPhotoPos.x() + st::notifyPhotoSize + st::notifyTextLeft, st::notifyTextTop, itemWidth, st::msgNameFont->height);
if (history->peer->chat) {
p.drawPixmap(QPoint(rectForName.left() + st::dlgChatImgLeft, rectForName.top() + st::dlgChatImgTop), App::sprite(), st::dlgChatImg);
rectForName.setLeft(rectForName.left() + st::dlgChatImgSkip);
}
QDateTime now(QDateTime::currentDateTime()), lastTime(item->date);
QDate nowDate(now.date()), lastDate(lastTime.date());
QString dt = lastTime.toString(qsl("hh:mm"));
int32 dtWidth = st::dlgHistFont->m.width(dt);
rectForName.setWidth(rectForName.width() - dtWidth - st::dlgDateSkip);
p.setFont(st::dlgDateFont->f);
p.setPen(st::dlgDateColor->p);
p.drawText(rectForName.left() + rectForName.width() + st::dlgDateSkip, rectForName.top() + st::dlgHistFont->ascent, dt);
const HistoryItem *textCachedFor = 0;
Text itemTextCache(itemWidth);
bool active = false;
item->drawInDialog(p, QRect(st::notifyPhotoPos.x() + st::notifyPhotoSize + st::notifyTextLeft, st::notifyItemTop + st::msgNameFont->height, itemWidth, 2 * st::dlgFont->height), active, textCachedFor, itemTextCache);
p.setPen(st::dlgNameColor->p);
history->nameText.drawElided(p, rectForName.left(), rectForName.top(), rectForName.width());
}
pm = QPixmap::fromImage(img);
hideTimer.setSingleShot(true);
connect(&hideTimer, SIGNAL(timeout()), this, SLOT(hideByTimer()));
inputTimer.setSingleShot(true);
connect(&inputTimer, SIGNAL(timeout()), this, SLOT(checkLastInput()));
connect(&close, SIGNAL(clicked()), this, SLOT(unlinkHistory()));
close.setAcceptBoth(true);
close.move(w - st::notifyClose.width - st::notifyClosePos.x(), st::notifyClosePos.y());
close.show();
aY.start(y);
setGeometry(x, aY.current(), st::notifyWidth, st::notifyHeight);
aOpacity.start(1);
setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint);
setAttribute(Qt::WA_MacAlwaysShowToolWindow);
show();
setWindowOpacity(aOpacity.current());
alphaDuration = posDuration = st::notifyFastAnim;
anim::start(this);
checkLastInput();
}
void PsNotifyWindow::checkLastInput() {
// TODO
if (true) {
hideTimer.start(st::notifyWaitLongHide);
} else {
inputTimer.start(300);
}
}
void PsNotifyWindow::moveTo(int32 x, int32 y, int32 index) {
if (index >= 0) {
_index = index;
}
move(x, aY.current());
aY.start(y);
aOpacity.restart();
posDuration = st::notifyFastAnim;
anim::start(this);
}
void PsNotifyWindow::updatePeerPhoto() {
if (!peerPhoto->isNull() && peerPhoto->loaded()) {
QImage img(pm.toImage());
{
QPainter p(&img);
p.drawPixmap(st::notifyPhotoPos.x(), st::notifyPhotoPos.y(), peerPhoto->pix(st::notifyPhotoSize));
}
peerPhoto = ImagePtr();
pm = QPixmap::fromImage(img);
update();
}
}
void PsNotifyWindow::unlinkHistory(History *hist) {
if (!hist || hist == history) {
animHide(st::notifyFastAnim, st::notifyFastAnimFunc);
history = 0;
App::wnd()->psShowNextNotify();
}
}
void PsNotifyWindow::enterEvent(QEvent */*e*/) {
if (!history) return;
if (App::wnd()) App::wnd()->psStopHiding();
}
void PsNotifyWindow::leaveEvent(QEvent */*e*/) {
if (!history) return;
App::wnd()->psStartHiding();
}
void PsNotifyWindow::startHiding() {
hideTimer.start(st::notifyWaitShortHide);
}
void PsNotifyWindow::mousePressEvent(QMouseEvent *e) {
if (!history) return;
if (e->button() == Qt::RightButton) {
unlinkHistory();
} else if (history) {
App::wnd()->showFromTray();
App::wnd()->hideSettings();
App::main()->showPeer(history->peer->id, false, true);
unlinkHistory();
e->ignore();
}
}
void PsNotifyWindow::paintEvent(QPaintEvent *e) {
QPainter p(this);
p.drawPixmap(0, 0, pm);
}
void PsNotifyWindow::animHide(float64 duration, anim::transition func) {
if (!history) return;
alphaDuration = duration;
aOpacityFunc = func;
aOpacity.start(0);
aY.restart();
hiding = true;
anim::start(this);
}
void PsNotifyWindow::stopHiding() {
if (!history) return;
alphaDuration = st::notifyFastAnim;
aOpacityFunc = st::notifyFastAnimFunc;
aOpacity.start(1);
aY.restart();
hiding = false;
hideTimer.stop();
anim::start(this);
}
void PsNotifyWindow::hideByTimer() {
if (!history) return;
animHide(st::notifySlowHide, st::notifySlowHideFunc);
}
bool PsNotifyWindow::animStep(float64 ms) {
float64 dtAlpha = ms / alphaDuration, dtPos = ms / posDuration;
if (dtAlpha >= 1) {
aOpacity.finish();
if (hiding) {
deleteLater();
}
} else {
aOpacity.update(dtAlpha, aOpacityFunc);
}
setWindowOpacity(aOpacity.current());
if (dtPos >= 1) {
aY.finish();
} else {
aY.update(dtPos, anim::linear);
}
move(x(), aY.current());
update();
return (dtAlpha < 1 || (!hiding && dtPos < 1));
}
PsNotifyWindow::~PsNotifyWindow() {
if (App::wnd()) App::wnd()->psShowNextNotify(this);
void PsMainWindow::psPlatformNotify(HistoryItem *item) {
_private.showNotify(item->history()->peer->id, item->history()->peer->name, item->notificationHeader(), item->notificationText());
}
PsApplication::PsApplication(int &argc, char **argv) : QApplication(argc, argv) {