Browse Source

优化osx下的通知;

删除未读提醒(鸡肋)
tags/v1.1
chenyong 8 years ago
parent
commit
b754c3409c
15 changed files with 309 additions and 138 deletions
  1. +4
    -4
      feiq.pro
  2. +0
    -7
      feiqwin.cpp
  3. +0
    -3
      feiqwin.h
  4. +117
    -37
      mainwindow.cpp
  5. +26
    -6
      mainwindow.h
  6. +6
    -1
      osx/notification.h
  7. +32
    -8
      osx/notification.mm
  8. +32
    -0
      osx/notificationimpl.h
  9. +61
    -0
      osx/notificationimpl.mm
  10. +8
    -2
      osx/osxplatform.cpp
  11. +2
    -1
      osx/osxplatform.h
  12. +11
    -3
      platformdepend.cpp
  13. +10
    -2
      platformdepend.h
  14. +0
    -39
      plugin/unreadchecker.cpp
  15. +0
    -25
      plugin/unreadchecker.h

+ 4
- 4
feiq.pro View File

@@ -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



+ 0
- 7
feiqwin.cpp View File

@@ -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;


+ 0
- 3
feiqwin.h View File

@@ -27,9 +27,6 @@ public:
const FeiqModel* feiqModel();
Settings* settings();

public:
int getUnreadCount();

private:
void init(MainWindow* mainWin);
void unInit();


+ 117
- 37
mainwindow.cpp View File

@@ -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<ViewEvent>)), this, SLOT(handleFeiqViewEvent(shared_ptr<ViewEvent>)));

@@ -105,13 +108,55 @@ void MainWindow::setFeiqWin(FeiqWin *feiqWin)
mFeiqWin->init(this);
}

void MainWindow::onNotifyClicked(const QString& fellowIp)
{
qDebug()<<fellowIp;
auto fellow = mFeiq.getModel().findFirstFellowOf(fellowIp.toStdString());
if (fellow)
openChartTo(fellow.get());

raise();
activateWindow();
showNormal();
}

void MainWindow::onNotifyReplied(long notifyId, const QString &fellowIp, const QString &reply)
{
auto fellow = mFeiq.getModel().findFirstFellowOf(fellowIp.toStdString());
if (fellow)
{
//回复消息
auto content = make_shared<TextContent>();
content->text = reply.toStdString();

mFeiq.send(fellow, content);

//设为已回复
auto msgRepliedTo = findUnshownMessage(notifyId);
if (msgRepliedTo)
{
msgRepliedTo->replied=true;
}

//将自己的回复放入未显示列表
auto event = make_shared<MessageViewEvent>();
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<Fellow> 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<ViewEvent> event)
auto e = static_cast<FellowViewEvent*>(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<const SendTimeoEvent*>(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<const MessageViewEvent*>(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<ViewEvent> 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;
}

+ 26
- 6
mainwindow.h View File

@@ -21,6 +21,19 @@ class MainWindow;

class FeiqWin;

struct UnshownMessage
{
shared_ptr<ViewEvent> event;
bool replied = false;
bool read = false;
long notifyId = 0;

bool isUnread()
{
return !replied && !read;
}
};

Q_DECLARE_METATYPE(shared_ptr<ViewEvent>)
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<Fellow> checkCurFellow();
void showResult(pair<bool, string> ret, const Content *content);
vector<const Fellow*> 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<ViewEvent> 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<const Fellow*, list<shared_ptr<ViewEvent>>> mUnreadEvents;
unordered_map<const Fellow*, list<UnshownMessage>> mUnshownEvents;
FeiqWin* mFeiqWin = nullptr;
};



+ 6
- 1
osx/notification.h View File

@@ -2,13 +2,18 @@
#define OSXNOTIFICATION_H

#include <QString>
#include <QObject>

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

+ 32
- 8
osx/notification.mm View File

@@ -1,22 +1,46 @@
#include "notification.h"
#include "notificationimpl.h"
#include <QDebug>
#include "../mainwindow.h"

#import <cocoa/Cocoa.h>
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;
}

+ 32
- 0
osx/notificationimpl.h View File

@@ -0,0 +1,32 @@
#ifndef NOTIFICATIONIMPL_H
#define NOTIFICATIONIMPL_H

#ifdef __cplusplus
extern "C"{
#endif

#import <Foundation/Foundation.h>

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

+ 61
- 0
osx/notificationimpl.mm View File

@@ -0,0 +1,61 @@
#include "notificationimpl.h"
#include <QDebug>

@interface NotificationImpl () <NSUserNotificationCenterDelegate>
@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

+ 8
- 2
osx/osxplatform.cpp View File

@@ -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);
}

+ 2
- 1
osx/osxplatform.h View File

@@ -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;
};


+ 11
- 3
platformdepend.cpp View File

@@ -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);
}

+ 10
- 2
platformdepend.h View File

@@ -2,15 +2,22 @@
#define PLATFORMDEPEND_H

#include <QString>
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;
};


+ 0
- 39
plugin/unreadchecker.cpp View File

@@ -1,39 +0,0 @@
#include "unreadchecker.h"
#include <QTimerEvent>
#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);
}

+ 0
- 25
plugin/unreadchecker.h View File

@@ -1,25 +0,0 @@
#ifndef UNREADCHECKER_H
#define UNREADCHECKER_H

#include "iplugin.h"
#include <QObject>

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

Loading…
Cancel
Save