File indexing completed on 2025-01-26 04:24:13

0001 /*
0002     SnoreNotify is a Notification Framework based on Qt
0003     Copyright (C) 2013-2015  Hannah von Reth <vonreth@kde.org>
0004 
0005     SnoreNotify is free software: you can redistribute it and/or modify
0006     it under the terms of the GNU Lesser General Public License as published by
0007     the Free Software Foundation, either version 3 of the License, or
0008     (at your option) any later version.
0009 
0010     SnoreNotify is distributed in the hope that it will be useful,
0011     but WITHOUT ANY WARRANTY; without even the implied warranty of
0012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0013     GNU Lesser General Public License for more details.
0014 
0015     You should have received a copy of the GNU Lesser General Public License
0016     along with SnoreNotify.  If not, see <http://www.gnu.org/licenses/>.
0017 */
0018 
0019 #include "snarlnetwork.h"
0020 #include "libsnore/snore.h"
0021 #include "libsnore/notification/notification_p.h"
0022 
0023 #include <QTcpServer>
0024 #include <QTcpSocket>
0025 #include <QPointer>
0026 
0027 #include <iostream>
0028 using namespace Snore;
0029 
0030 SnarlNetworkFrontend::SnarlNetworkFrontend():
0031     parser(new Parser(this))
0032 {
0033     connect(this, &SnarlNetworkFrontend::enabledChanged, [this](bool enabled) {
0034         if (enabled) {
0035             tcpServer = new QTcpServer(this);
0036             if (!tcpServer->listen(QHostAddress::Any, port)) {
0037                 setErrorString(tr("The port is already used by a different application."));
0038                 return;
0039             }
0040             connect(tcpServer, &QTcpServer::newConnection, this, &SnarlNetworkFrontend::handleConnection);
0041         } else {
0042             tcpServer->deleteLater();
0043         }
0044     });
0045 }
0046 
0047 SnarlNetworkFrontend::~SnarlNetworkFrontend()
0048 {
0049     delete parser;
0050 }
0051 
0052 void SnarlNetworkFrontend::slotActionInvoked(Snore::Notification notification)
0053 {
0054     if (notification.isActiveIn(this)) {
0055         qCDebug(SNORE) << notification.closeReason();
0056         callback(notification, QStringLiteral("SNP/1.1/304/Notification acknowledged/"));
0057     }
0058 }
0059 
0060 void SnarlNetworkFrontend::slotNotificationClosed(Snore::Notification notification)
0061 {
0062 
0063     if (notification.removeActiveIn(this)) {
0064         switch (notification.closeReason()) {
0065         case Notification::TimedOut:
0066             callback(notification, QStringLiteral("SNP/1.1/303/Notification timed out/"));
0067             break;
0068         case Notification::Activated:
0069             callback(notification, QStringLiteral("SNP/1.1/307/Notification closed/"));
0070             break;
0071         case Notification::Dismissed:
0072             callback(notification, QStringLiteral("SNP/1.1/302/Notification cancelled/"));
0073             break;
0074         default:
0075             qCWarning(SNORE) << "Unhandled close reason" << notification.closeReason();
0076         }
0077     }
0078 }
0079 
0080 void SnarlNetworkFrontend::handleConnection()
0081 {
0082     QTcpSocket *client = tcpServer->nextPendingConnection();
0083     connect(client, &QTcpSocket::readyRead, this, &SnarlNetworkFrontend::handleMessages);
0084     connect(client, &QTcpSocket::disconnected, client, &QTcpSocket::deleteLater);
0085 }
0086 
0087 void SnarlNetworkFrontend::handleMessages()
0088 {
0089     const QString out(QStringLiteral("SNP/1.1/0/OK"));
0090     QTcpSocket *client = qobject_cast<QTcpSocket *>(sender());
0091 
0092     QStringList messages(QString::fromLatin1(client->readAll()).trimmed().split(QStringLiteral("\r\n")));
0093     foreach(const QString & s, messages) {
0094         if (s.isEmpty()) {
0095             continue;
0096         }
0097         Notification noti;
0098         parser->parse(noti, s, client);
0099         if (noti.isValid()) {
0100             noti.addActiveIn(this);
0101             SnoreCore::instance().broadcastNotification(noti);
0102             write(client, out + QLatin1Char('/') + QString::number(noti.id()) + QLatin1String("\r\n"));
0103         } else {
0104             write(client, out + QLatin1String("\r\n"));
0105         }
0106     }
0107 }
0108 
0109 void SnarlNetworkFrontend::callback(Notification &sn, const QString &msg)
0110 {
0111     if (sn.hints().containsPrivateValue(this, "clientSocket")) {
0112         QTcpSocket *client = sn.hints().privateValue(this, "clientSocket").value<QPointer<QTcpSocket>>();
0113         if (client) {
0114             write(client, msg + QString::number(sn.id()) + QLatin1String("\r\n"));
0115         }
0116     }
0117 }
0118