void NotificationPreviewPresenter::updateNotification(uint id)
{
    LipstickNotification *notification = NotificationManager::instance()->notification(id);

    if (notification != 0) {
        notification->setProperty("id", id);
        if (notificationShouldBeShown(notification)) {
            // Add the notification to the queue if not already there or the current notification
            if (currentNotification != notification && !notificationQueue.contains(notification)) {
                notificationQueue.append(notification);

                // Show the notification if no notification currently being shown
                if (currentNotification == 0) {
                    showNextNotification();
                }
            }
        } else {
            // Remove updated notification only from the queue so that a currently visible notification won't suddenly disappear
            emit notificationPresented(id);

            removeNotification(id, true);

            if (currentNotification != notification && notification->hints().value(NotificationManager::HINT_URGENCY).toInt() >= 2) {
                NotificationManager::instance()->CloseNotification(id);
            }
        }
    }
}
void NotificationPreviewPresenter::showNextNotification()
{
    if (!LipstickCompositor::instance() && !notificationQueue.isEmpty()) {
        QTimer::singleShot(0, this, SLOT(showNextNotification()));
        return;
    }

    if (notificationQueue.isEmpty()) {
        // No more notifications to show: hide the notification window if it's visible
        if (window != 0 && window->isVisible()) {
            window->hide();
        }

        setCurrentNotification(0);
    } else {
        LipstickNotification *notification = notificationQueue.takeFirst();

        if (locks->getState(MeeGo::QmLocks::TouchAndKeyboard) == MeeGo::QmLocks::Locked && displayState->get() == MeeGo::QmDisplayState::Off) {
            // Screen locked and off: don't show the notification but just remove it from the queue
            emit notificationPresented(notification->property("id").toUInt());

            setCurrentNotification(0);

            showNextNotification();
        } else {
            // Show the notification window and the first queued notification in it
            if (!window->isVisible()) {
                window->show();
            }

            emit notificationPresented(notification->property("id").toUInt());

            setCurrentNotification(notification);
        }
    }
}
void Manager::Impl::showNotification(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, const QString &msg, bool hideNameAndPhoto, bool hideReplyButton) {
	auto titleText = escapeNotificationText(title);
	auto subtitleText = escapeNotificationText(subtitle);
	auto msgText = escapeNotificationText(msg);
	if (_markupSupported && !subtitleText.isEmpty()) {
		subtitleText = qstr("<b>") + subtitleText + qstr("</b>");
	}
	auto bodyText = subtitleText.isEmpty() ? msgText : (subtitleText + '\n' + msgText);

	QueuedNotification notification;
	notification.peer = peer;
	notification.msgId = msgId;
	notification.title = titleText;
	notification.body = bodyText;
	notification.hideNameAndPhoto = hideNameAndPhoto;
	_queuedNotifications.push_back(notification);

	showNextNotification();
}
void Manager::Impl::showNextNotification() {
	// Show only one notification at a time in Unity / Notify OSD.
	if (_poorSupported) {
		for (auto b = _notifications.begin(); !_notifications.isEmpty() && b->isEmpty();) {
			_notifications.erase(b);
		}
		if (!_notifications.isEmpty()) {
			return;
		}
	}

	QueuedNotification data;
	while (!_queuedNotifications.isEmpty()) {
		data = _queuedNotifications.front();
		_queuedNotifications.pop_front();
		if (data.peer) {
			break;
		}
	}
	if (!data.peer) {
		return;
	}

	auto peerId = data.peer->id;
	auto msgId = data.msgId;
	auto notification = MakeShared<NotificationData>(data.title, data.body, _capabilities, peerId, msgId);
	if (!notification->valid()) {
		return;
	}

	StorageKey key;
	if (data.hideNameAndPhoto) {
		key = StorageKey(0, 0);
	} else {
		key = data.peer->userpicUniqueKey();
	}
	notification->setImage(_cachedUserpics.get(key, data.peer));

	auto i = _notifications.find(peerId);
	if (i != _notifications.cend()) {
		auto j = i->find(msgId);
		if (j != i->cend()) {
			auto oldNotification = j.value();
			i->erase(j);
			oldNotification->close();
			i = _notifications.find(peerId);
		}
	}
	if (i == _notifications.cend()) {
		i = _notifications.insert(peerId, QMap<MsgId, Notification>());
	}
	_notifications[peerId].insert(msgId, notification);
	if (!notification->show()) {
		i = _notifications.find(peerId);
		if (i != _notifications.cend()) {
			i->remove(msgId);
			if (i->isEmpty()) _notifications.erase(i);
		}
		showNextNotification();
	}
}