From b754c3409c7dacafdffcb5e483c80da742d294e5 Mon Sep 17 00:00:00 2001 From: chenyong Date: Thu, 13 Oct 2016 23:01:54 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96osx=E4=B8=8B=E7=9A=84?= =?UTF-8?q?=E9=80=9A=E7=9F=A5;=20=E5=88=A0=E9=99=A4=E6=9C=AA=E8=AF=BB?= =?UTF-8?q?=E6=8F=90=E9=86=92=EF=BC=88=E9=B8=A1=E8=82=8B)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- feiq.pro | 8 +-- feiqwin.cpp | 7 --- feiqwin.h | 3 - mainwindow.cpp | 154 +++++++++++++++++++++++++++++++++++------------ mainwindow.h | 32 ++++++++-- osx/notification.h | 7 ++- osx/notification.mm | 40 +++++++++--- osx/notificationimpl.h | 32 ++++++++++ osx/notificationimpl.mm | 61 +++++++++++++++++++ osx/osxplatform.cpp | 10 ++- osx/osxplatform.h | 3 +- platformdepend.cpp | 14 ++++- platformdepend.h | 12 +++- plugin/unreadchecker.cpp | 39 ------------ plugin/unreadchecker.h | 25 -------- 15 files changed, 309 insertions(+), 138 deletions(-) create mode 100644 osx/notificationimpl.h create mode 100644 osx/notificationimpl.mm delete mode 100644 plugin/unreadchecker.cpp delete mode 100644 plugin/unreadchecker.h diff --git a/feiq.pro b/feiq.pro index 3e52950..c36a918 100644 --- a/feiq.pro +++ b/feiq.pro @@ -20,12 +20,14 @@ mac{ LIBS += -framework Foundation - OBJECTIVE_SOURCES += osx/notification.mm + OBJECTIVE_SOURCES += osx/notification.mm\ + osx/notificationimpl.mm SOURCES += osx/osxplatform.cpp HEADERS += osx/notification.h\ - osx/osxplatform.h + osx/osxplatform.h\ + osx/notificationimpl.h } SOURCES += main.cpp\ @@ -54,7 +56,6 @@ SOURCES += main.cpp\ chooseemojiwidget.cpp \ sendtextedit.cpp \ feiqwin.cpp \ - plugin/unreadchecker.cpp \ plugin/iplugin.cpp \ plugin/rankuser.cpp \ settings.cpp @@ -94,7 +95,6 @@ HEADERS += mainwindow.h \ sendtextedit.h \ plugin/iplugin.h \ feiqwin.h \ - plugin/unreadchecker.h \ plugin/rankuser.h \ settings.h diff --git a/feiqwin.cpp b/feiqwin.cpp index c0aecb6..513c9e2 100644 --- a/feiqwin.cpp +++ b/feiqwin.cpp @@ -2,8 +2,6 @@ #include "mainwindow.h" #include "plugin/iplugin.h" -#include "plugin/unreadchecker.h" - FeiqWin::FeiqWin() { @@ -34,11 +32,6 @@ Settings *FeiqWin::settings() return mMainWin->mSettings; } -int FeiqWin::getUnreadCount() -{ - return mMainWin->getUnreadCount(); -} - void FeiqWin::init(MainWindow *mainWin) { mMainWin = mainWin; diff --git a/feiqwin.h b/feiqwin.h index b04a1eb..d592695 100644 --- a/feiqwin.h +++ b/feiqwin.h @@ -27,9 +27,6 @@ public: const FeiqModel* feiqModel(); Settings* settings(); -public: - int getUnreadCount(); - private: void init(MainWindow* mainWin); void unInit(); diff --git a/mainwindow.cpp b/mainwindow.cpp index 31af3c6..2074201 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -80,6 +80,9 @@ MainWindow::MainWindow(QWidget *parent) : connect(ui->actionSendKnock, SIGNAL(triggered(bool)), this, SLOT(sendKnock())); connect(ui->actionSendFile, SIGNAL(triggered(bool)), this, SLOT(sendFile())); + //初始化平台相关特性 + PlatformDepend::instance().setMainWnd(this); + //初始化飞秋引擎 connect(this, SIGNAL(feiqViewEvent(shared_ptr)), this, SLOT(handleFeiqViewEvent(shared_ptr))); @@ -105,13 +108,55 @@ void MainWindow::setFeiqWin(FeiqWin *feiqWin) mFeiqWin->init(this); } +void MainWindow::onNotifyClicked(const QString& fellowIp) +{ + qDebug()<(); + content->text = reply.toStdString(); + + mFeiq.send(fellow, content); + + //设为已回复 + auto msgRepliedTo = findUnshownMessage(notifyId); + if (msgRepliedTo) + { + msgRepliedTo->replied=true; + } + + //将自己的回复放入未显示列表 + auto event = make_shared(); + event->contents.push_back(content); + event->fellow = nullptr; + + auto& msg = addUnshownMessage(fellow.get(), event); + msg.read = true; + + updateUnshownHint(fellow.get()); + } +} + void MainWindow::enterEvent(QEvent *event) { auto fellow = mRecvTextEdit->curFellow(); if (fellow) { - flushUnread(fellow); - updateUnread(fellow); + flushUnshown(fellow); + updateUnshownHint(fellow); } PlatformDepend::instance().hideAllNotify(); @@ -122,8 +167,8 @@ void MainWindow::openChartTo(const Fellow *fellow) mFellowList.top(*fellow); mRecvTextEdit->setCurFellow(fellow); setWindowTitle(mTitle + " - 与"+fellow->getName().c_str()+"会话中"); - flushUnread(fellow); - updateUnread(fellow); + flushUnshown(fellow); + updateUnshownHint(fellow); } shared_ptr MainWindow::checkCurFellow() @@ -150,7 +195,9 @@ void MainWindow::onStateChanged(FileTask *fileTask) if (fileTask->getState()==FileTaskState::Finish) { auto title = QString(fileTask->getTaskTypeDes().c_str())+"完成"; - PlatformDepend::instance().showNotify(title, fileTask->getContent()->filename.c_str()); + PlatformDepend::instance().showNotify(title, + fileTask->getContent()->filename.c_str(), + fileTask->fellow()->getIp().c_str()); } else if (fileTask->getState()==FileTaskState::Error) { @@ -158,7 +205,9 @@ void MainWindow::onStateChanged(FileTask *fileTask) auto content = QString(fileTask->getContent()->filename.c_str()); content += "\n"; content += fileTask->getDetailInfo().c_str(); - PlatformDepend::instance().showNotify(title, content); + PlatformDepend::instance().showNotify(title, + content, + fileTask->fellow()->getIp().c_str()); } if (mDownloadFileDlg->isVisible()) @@ -200,23 +249,15 @@ void MainWindow::handleFeiqViewEvent(shared_ptr event) auto e = static_cast(event.get()); auto fellow = e->fellow.get(); - if (isActiveWindow()) + if (isActiveWindow() && fellow == mRecvTextEdit->curFellow()) {//窗口可见,处理当前用户消息,其他用户消息则放入通知队列 - if (fellow == mRecvTextEdit->curFellow()) - { - readEvent(event.get()); - } - else - { - mUnreadEvents[fellow].push_back(event); - updateUnread(fellow); - } + readEvent(event.get()); } else {//窗口不可见,放入未读队列并通知 - mUnreadEvents[fellow].push_back(event); - updateUnread(fellow); - notifyUnread(event.get()); + auto& umsg = addUnshownMessage(fellow, event); + notifyUnshown(umsg); + updateUnshownHint(fellow); } } } @@ -277,31 +318,39 @@ void MainWindow::userAddFellow(QString ip) mFeiq.sendImOnLine(fellow->getIp()); } -void MainWindow::notifyUnread(const ViewEvent *event) +void MainWindow::notifyUnshown(UnshownMessage& umsg) { + auto event = umsg.event.get(); if (event->what == ViewEventType::SEND_TIMEO) { auto e = static_cast(event); auto fellow = e->fellow.get(); - showNotification(fellow, "发送超时:"+simpleTextOf(e->content.get())); + umsg.notifyId = showNotification(fellow, "发送超时:"+simpleTextOf(e->content.get())); } else if (event->what == ViewEventType::MESSAGE) { auto e = static_cast(event); auto fellow = e->fellow.get(); + QString text=""; + bool first=false; for (auto content : e->contents) { - showNotification(fellow, simpleTextOf(content.get())); + auto t = simpleTextOf(content.get()); + if (first) + text = t; + else + text = text+"\n"+t; } + umsg.notifyId = showNotification(fellow, text); } } -void MainWindow::showNotification(const Fellow *fellow, const QString &text) +long MainWindow::showNotification(const Fellow *fellow, const QString &text) { QString content(text); if (content.length()>20) content = content.left(20)+"..."; - PlatformDepend::instance().showNotify(QString(fellow->getName().c_str())+":", content); + return PlatformDepend::instance().showNotify(QString(fellow->getName().c_str())+":", content, fellow->getIp().c_str()); } void MainWindow::navigateToFileTask(IdType packetNo, IdType fileId, bool upload) @@ -462,12 +511,12 @@ void MainWindow::initFeiq() qDebug()<<"feiq started"; } -void MainWindow::updateUnread(const Fellow *fellow) +void MainWindow::updateUnshownHint(const Fellow *fellow) { - auto it = mUnreadEvents.find(fellow); - if (it != mUnreadEvents.end()) + auto it = mUnshownEvents.find(fellow); + if (it != mUnshownEvents.end()) { - auto count = (*it).second.size(); + auto count = it->second.size(); if (count == 0) { mFellowList.mark(*fellow, ""); @@ -483,26 +532,30 @@ void MainWindow::updateUnread(const Fellow *fellow) int MainWindow::getUnreadCount() { - auto begin = mUnreadEvents.begin(); - auto end = mUnreadEvents.end(); + auto begin = mUnshownEvents.begin(); + auto end = mUnshownEvents.end(); auto count = 0; for (auto it = begin; it != end; it++) { - count += it->second.size(); + for (auto msg : it->second) + { + if (msg.isUnread()) + ++count; + } } return count; } -void MainWindow::flushUnread(const Fellow *fellow) +void MainWindow::flushUnshown(const Fellow *fellow) { - auto it = mUnreadEvents.find(fellow); - if (it != mUnreadEvents.end()) + auto it = mUnshownEvents.find(fellow); + if (it != mUnshownEvents.end()) { auto& list = (*it).second; while (!list.empty()) { - auto event = list.front(); - readEvent(event.get()); + auto msg = list.front(); + readEvent(msg.event.get()); list.pop_front(); } } @@ -525,7 +578,10 @@ void MainWindow::readEvent(const ViewEvent *event) auto time = e->when.time_since_epoch().count(); for (auto content : e->contents) { - mRecvTextEdit->addFellowContent(content.get(), time); + if (e->fellow == nullptr) + mRecvTextEdit->addMyContent(content.get(), time); + else + mRecvTextEdit->addFellowContent(content.get(), time); } } } @@ -550,3 +606,27 @@ QString MainWindow::simpleTextOf(const Content *content) break; } } + +UnshownMessage &MainWindow::addUnshownMessage(const Fellow *fellow, shared_ptr event) +{ + UnshownMessage msg; + msg.event = event; + mUnshownEvents[fellow].push_back(msg); + return mUnshownEvents[fellow].back(); +} + +UnshownMessage* MainWindow::findUnshownMessage(int id) +{ + auto begin = mUnshownEvents.begin(); + auto end = mUnshownEvents.end(); + + for (auto it = begin; it != end; it++) + { + for (auto& msg : it->second){ + if (msg.notifyId == id) + return &msg; + } + } + + return nullptr; +} diff --git a/mainwindow.h b/mainwindow.h index 7228b5c..e182cd3 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -21,6 +21,19 @@ class MainWindow; class FeiqWin; +struct UnshownMessage +{ + shared_ptr event; + bool replied = false; + bool read = false; + long notifyId = 0; + + bool isUnread() + { + return !replied && !read; + } +}; + Q_DECLARE_METATYPE(shared_ptr) class MainWindow : public QMainWindow, IFeiqView { @@ -33,6 +46,10 @@ public: void setFeiqWin(FeiqWin* feiqWin); +public slots: + void onNotifyClicked(const QString& fellowIp); + void onNotifyReplied(long notifyId, const QString& fellowIp, const QString& reply); + protected: void enterEvent(QEvent *event); @@ -62,19 +79,22 @@ private slots: private: void userAddFellow(QString ip); - void notifyUnread(const ViewEvent* event); - void showNotification(const Fellow* fellow, const QString& text); + long showNotification(const Fellow* fellow, const QString& text); shared_ptr checkCurFellow(); void showResult(pair ret, const Content *content); vector fellowSearchDriver(const QString& text); void initFeiq(); - void updateUnread(const Fellow* fellow); - int getUnreadCount(); - void flushUnread(const Fellow* fellow); void readEvent(const ViewEvent* event); void setBadgeNumber(int number); QString simpleTextOf(const Content* content); + UnshownMessage& addUnshownMessage(const Fellow *fellow, shared_ptr event); + UnshownMessage *findUnshownMessage(int id); + void notifyUnshown(UnshownMessage &umsg); + void updateUnshownHint(const Fellow* fellow); + int getUnreadCount(); + void flushUnshown(const Fellow* fellow); + // IFileTaskObserver interface public: void onStateChanged(FileTask *fileTask); @@ -95,7 +115,7 @@ private: RecvTextEdit* mRecvTextEdit; SendTextEdit* mSendTextEdit; QString mTitle; - unordered_map>> mUnreadEvents; + unordered_map> mUnshownEvents; FeiqWin* mFeiqWin = nullptr; }; diff --git a/osx/notification.h b/osx/notification.h index c00b599..1b2ffa3 100644 --- a/osx/notification.h +++ b/osx/notification.h @@ -2,13 +2,18 @@ #define OSXNOTIFICATION_H #include +#include +class MainWindow; class Notification { public: explicit Notification(); - void show(const QString& title, const QString& content); + int show(const QString& title, const QString& content, const QString &fellowIp); void hideAll(); + +public: + void setMainWnd(MainWindow* mainWnd); }; #endif // OSXNOTIFICATION_H diff --git a/osx/notification.mm b/osx/notification.mm index 529df9d..d09436c 100644 --- a/osx/notification.mm +++ b/osx/notification.mm @@ -1,22 +1,46 @@ #include "notification.h" +#include "notificationimpl.h" +#include +#include "../mainwindow.h" -#import +static NotificationImpl* impl = [[NotificationImpl alloc] init]; + +static void clickCallback(void* arg, NSString* fellowIp) +{ + MainWindow* mainWnd = (MainWindow*)arg; + const char* ip = [fellowIp UTF8String]; + mainWnd->onNotifyClicked(ip); +} + +static void replyCallback(void* arg, long notifyId, NSString* fellowIp, NSString* str) +{ + const char* reply = [str UTF8String]; + const char* ip = [fellowIp UTF8String]; + + MainWindow* mainWnd = (MainWindow*)arg; + mainWnd->onNotifyReplied(notifyId, ip, reply); +} Notification::Notification() { } -void Notification::show(const QString &title, const QString &content) +int Notification::show(const QString &title, const QString &content, const QString& fellowIp) { - NSUserNotification *userNotification = [[[NSUserNotification alloc] init] autorelease]; - userNotification.title = title.toNSString(); - userNotification.informativeText = content.toNSString(); - NSUserNotificationCenter* center = [NSUserNotificationCenter defaultUserNotificationCenter]; - [center deliverNotification:userNotification]; + NSString* objcTitle = title.toNSString(); + NSString* objcMessage = content.toNSString(); + return [impl show: objcTitle message: objcMessage extra: fellowIp.toNSString()]; } void Notification::hideAll() { - [[NSUserNotificationCenter defaultUserNotificationCenter] removeAllDeliveredNotifications]; + [impl hideAll]; +} + +void Notification::setMainWnd(MainWindow *mainWnd) +{ + impl->clickCallback = clickCallback; + impl->replyCallback = replyCallback; + impl->callbackArg = mainWnd; } diff --git a/osx/notificationimpl.h b/osx/notificationimpl.h new file mode 100644 index 0000000..cbb2488 --- /dev/null +++ b/osx/notificationimpl.h @@ -0,0 +1,32 @@ +#ifndef NOTIFICATIONIMPL_H +#define NOTIFICATIONIMPL_H + +#ifdef __cplusplus +extern "C"{ +#endif + +#import + +typedef void(*ClickCallback)(void*, NSString*); +typedef void(*ReplyCallback)(void*, long, NSString*, NSString*); + +@interface NotificationImpl : NSObject + { + @public + ClickCallback clickCallback; + ReplyCallback replyCallback; + void* callbackArg; + + @private + int id; + } + -(instancetype)init; + -(long)show: (NSString*)title message:(NSString*)msg extra:(NSString*)who; + -(void)hideAll; +@end + +#ifdef __cplusplus +} +#endif + +#endif // NOTIFICATIONIMPL_H diff --git a/osx/notificationimpl.mm b/osx/notificationimpl.mm new file mode 100644 index 0000000..8bb771d --- /dev/null +++ b/osx/notificationimpl.mm @@ -0,0 +1,61 @@ +#include "notificationimpl.h" +#include + +@interface NotificationImpl () +@end + +@implementation NotificationImpl + +-(instancetype)init +{ + self = [super init]; + + if(self) + { + id=0; + [[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:self]; + } + + return self; +} + +-(long)show:(NSString*)title message:(NSString*)msg extra:(NSString*)who +{ + NSUserNotification* notification = [[NSUserNotification alloc] init]; + notification.title = title; + if (who != nil && who.length > 0) + { + notification.userInfo=@{@"extra":who}; + notification.hasReplyButton = true; + } + int myid = ++id; + notification.identifier = [NSString stringWithFormat:@"%d",myid]; + notification.informativeText = msg; + + [[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification: notification]; + + return (long)myid; +} + +-(void)hideAll +{ + [[NSUserNotificationCenter defaultUserNotificationCenter] removeAllDeliveredNotifications]; +} + +-(BOOL)userNotificationCenter:(NSUserNotificationCenter *)center shouldPresent:(NSUserNotification *)notification +{ + return YES; +} +-(void)userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification +{ + NSString* who = [notification.userInfo objectForKey:@"extra"]; + int myid = notification.identifier.intValue; + if (notification.activationType == NSUserNotificationActivationTypeContentsClicked){ + clickCallback(callbackArg, who); + } + else if (notification.activationType == NSUserNotificationActivationTypeReplied){ + replyCallback(callbackArg, myid, who, notification.response.string); + } +} + +@end diff --git a/osx/osxplatform.cpp b/osx/osxplatform.cpp index eaa2f48..60d22ea 100644 --- a/osx/osxplatform.cpp +++ b/osx/osxplatform.cpp @@ -6,9 +6,9 @@ OsxPlatform::OsxPlatform() } -void OsxPlatform::showNotify(const QString &title, const QString &content) +long OsxPlatform::showNotify(const QString &title, const QString &content, const QString & fellowIp) { - mNotify.show(title, content); + return mNotify.show(title, content, fellowIp); } void OsxPlatform::hideAllNotify() @@ -23,3 +23,9 @@ void OsxPlatform::setBadgeNumber(int number) else QtMac::setBadgeLabelText(QString::number(number)); } + +void OsxPlatform::setMainWnd(MainWindow *mainWnd) +{ + IPlatform::setMainWnd(mainWnd); + mNotify.setMainWnd(mainWnd); +} diff --git a/osx/osxplatform.h b/osx/osxplatform.h index 8525159..5b2e58d 100644 --- a/osx/osxplatform.h +++ b/osx/osxplatform.h @@ -10,11 +10,12 @@ public: OsxPlatform(); public: - void showNotify(const QString& title, const QString& content) override; + long showNotify(const QString& title, const QString& content, const QString &fellowIp) override; void hideAllNotify() override; void setBadgeNumber(int number) override; + void setMainWnd(MainWindow *mainWnd) override; private: Notification mNotify; }; diff --git a/platformdepend.cpp b/platformdepend.cpp index f28853f..a7caac3 100644 --- a/platformdepend.cpp +++ b/platformdepend.cpp @@ -7,10 +7,12 @@ class MockPlatform : public IPlatform { public: - void showNotify(const QString& title, const QString& content) + long showNotify(const QString& title, const QString& content, const QString& data) { (void)title; (void)content; + (void)data; + return 0; } void hideAllNotify() { @@ -43,9 +45,9 @@ PlatformDepend &PlatformDepend::instance() return me; } -void PlatformDepend::showNotify(const QString &title, const QString &content) +long PlatformDepend::showNotify(const QString &title, const QString &content, const QString &fellowIp) { - mImpl->showNotify(title, content); + return mImpl->showNotify(title, content, fellowIp); } void PlatformDepend::hideAllNotify() @@ -57,3 +59,9 @@ void PlatformDepend::setBadgeNumber(int number) { mImpl->setBadgeNumber(number); } + +void PlatformDepend::setMainWnd(MainWindow *mainWnd) +{ + IPlatform::setMainWnd(mainWnd); + mImpl->setMainWnd(mainWnd); +} diff --git a/platformdepend.h b/platformdepend.h index cc0c27e..725cc63 100644 --- a/platformdepend.h +++ b/platformdepend.h @@ -2,15 +2,22 @@ #define PLATFORMDEPEND_H #include +class MainWindow; + class IPlatform { public: virtual ~IPlatform(){} - virtual void showNotify(const QString& title, const QString& content) = 0; + virtual long showNotify(const QString& title, const QString& content, const QString & fellowIp) = 0; virtual void hideAllNotify() = 0; virtual void setBadgeNumber(int number) = 0; + + virtual void setMainWnd(MainWindow* mainWnd) + { + Q_UNUSED(mainWnd); + } }; class PlatformDepend : public IPlatform @@ -23,11 +30,12 @@ public: static PlatformDepend& instance(); public: - void showNotify(const QString& title, const QString& content) override; + long showNotify(const QString& title, const QString& content, const QString & fellowIp) override; void hideAllNotify() override; void setBadgeNumber(int number) override; + void setMainWnd(MainWindow* mainWnd) override; private: IPlatform* mImpl; }; diff --git a/plugin/unreadchecker.cpp b/plugin/unreadchecker.cpp deleted file mode 100644 index 6173ba0..0000000 --- a/plugin/unreadchecker.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include "unreadchecker.h" -#include -#include "platformdepend.h" - -#define PLUGIN_NAME "unread_checker" -REGISTER_PLUGIN(PLUGIN_NAME, UnreadChecker) - -UnreadChecker::UnreadChecker() -{ -} - -void UnreadChecker::timerEvent(QTimerEvent *event) -{ - if (event->timerId() == mUnreadTimerId) - { - auto count = mFeiq->getUnreadCount(); - if (count > 0) - { - PlatformDepend::instance().hideAllNotify(); - PlatformDepend::instance().showNotify("未读提醒", QString("还有%1条未读消息").arg(count)); - } - } -} - -void UnreadChecker::init() -{ - IPlugin::init(); - - auto settings = mFeiq->settings(); - mUnreadTimerInterval = settings->value(PLUGIN_NAME"/timer", "600").toInt(); - if (mUnreadTimerInterval > 0) - mUnreadTimerId = startTimer(mUnreadTimerInterval*1000, Qt::VeryCoarseTimer); -} - -void UnreadChecker::unInit() -{ - if (mUnreadTimerId > 0) - killTimer(mUnreadTimerId); -} diff --git a/plugin/unreadchecker.h b/plugin/unreadchecker.h deleted file mode 100644 index 8d41408..0000000 --- a/plugin/unreadchecker.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef UNREADCHECKER_H -#define UNREADCHECKER_H - -#include "iplugin.h" -#include - -class UnreadChecker : public QObject, public IPlugin -{ - Q_OBJECT - -public: - UnreadChecker(); - void init() override; - void unInit() override; - -protected: - void timerEvent(QTimerEvent *event) override; - -private: - int mUnreadTimerInterval; - int mUnreadTimerId=-1; - int mLastCheckCount=0; -}; - -#endif // UNREADCHECKER_H