Commit 0544763e by NitefullWind

1. 导航模块实现闪烁通知功能。

parent 63e2e165
...@@ -51,3 +51,15 @@ QString FMPHome::userName() ...@@ -51,3 +51,15 @@ QString FMPHome::userName()
Q_D(FMPHome); Q_D(FMPHome);
return d->_userName; return d->_userName;
} }
int FMPHome::blink(FMPluginInterface *plugin, const QString &image)
{
Q_D(FMPHome);
return d->blink(plugin, image);
}
bool FMPHome::stopBlink(int blinkId)
{
Q_D(FMPHome);
return d->stopBlink(blinkId);
}
...@@ -28,6 +28,9 @@ public: ...@@ -28,6 +28,9 @@ public:
bool isLogined(); bool isLogined();
QString userName(); QString userName();
int blink(FMPluginInterface *plugin, const QString &image);
bool stopBlink(int blinkId);
private: private:
FMPHomePrivate *d_ptr; FMPHomePrivate *d_ptr;
bool _inited; bool _inited;
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
TEMPLATE = lib TEMPLATE = lib
QT += core gui network QT += core gui network concurrent
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11 CONFIG += c++11
......
...@@ -10,6 +10,22 @@ public: ...@@ -10,6 +10,22 @@ public:
virtual int login() = 0; virtual int login() = 0;
virtual bool isLogined() = 0; virtual bool isLogined() = 0;
virtual QString userName() = 0; virtual QString userName() = 0;
/**
* @brief blink
* 在导航窗口中闪烁某张图片,并在下次点击导航窗口时唤起传入的插件
* @param plugin 要换起的插件对象
* @param image 要闪烁的图片地址
* @return int 此闪烁的标识id,可调用stopBlink(int blinkId)结束此闪烁
*/
virtual int blink(FMPluginInterface *plugin, const QString &image) = 0;
/**
* @brief stopBlink
* 结束某个闪烁
* @param blinkId 创建blink时返回的闪烁标识id
* @return bool 如果参数blinkId标识的闪烁不存在或已结束则返回false, 否则返回true
*/
virtual bool stopBlink(int blinkId) = 0;
}; };
Q_DECLARE_INTERFACE(FMPHomeInterface, "com.fmp.home") Q_DECLARE_INTERFACE(FMPHomeInterface, "com.fmp.home")
......
...@@ -9,10 +9,12 @@ ...@@ -9,10 +9,12 @@
#include <QPropertyAnimation> #include <QPropertyAnimation>
#include <QEasingCurve> #include <QEasingCurve>
#include <QStateMachine> #include <QStateMachine>
#include <QHistoryState>
#include <QSystemTrayIcon> #include <QSystemTrayIcon>
#include <QMenu> #include <QMenu>
#include <QtConcurrent>
NavWindow::NavWindow(FMPSettingsInterface *&settings, QWidget *parent) : NavWindow::NavWindow(QWidget *parent) :
QDialog(parent), QDialog(parent),
ui(new Ui::NavWindow), ui(new Ui::NavWindow),
_btn_group(new QButtonGroup(this)), _btn_group(new QButtonGroup(this)),
...@@ -43,14 +45,22 @@ NavWindow::NavWindow(FMPSettingsInterface *&settings, QWidget *parent) : ...@@ -43,14 +45,22 @@ NavWindow::NavWindow(FMPSettingsInterface *&settings, QWidget *parent) :
this->move(FMPHomeSettings::instance()->getWindowPosition()); this->move(FMPHomeSettings::instance()->getWindowPosition());
connect(ui->navMainBtn, SIGNAL(moved(QPoint)), this, SLOT(onMoved(QPoint))); connect(ui->navMainBtn, SIGNAL(moved(QPoint)), this, SLOT(onMoved(QPoint)));
connect(this, SIGNAL(navImageChanged()), this, SLOT(onNavImageChanged()));
} }
NavWindow::~NavWindow() NavWindow::~NavWindow()
{ {
delete _btn_group; delete _btn_group;
for(int i=0; i<actions.size(); ++i) {
delete actions.at(i);
}
actions.clear(); actions.clear();
delete _animationShow; delete _animationShow;
delete _systemTrayIcon; delete _systemTrayIcon;
delete stateGroup;
delete stateDefault;
delete stateSpread;
delete stateBlink;
delete ui; delete ui;
} }
...@@ -80,12 +90,26 @@ void NavWindow::spreadMenus(const bool isSpread) ...@@ -80,12 +90,26 @@ void NavWindow::spreadMenus(const bool isSpread)
void NavWindow::initMenu() void NavWindow::initMenu()
{ {
QState *stateDefault = new QState(_stateMachine); stateGroup = new QState(_stateMachine);
stateDefault->assignProperty(ui->navMainBtn, "styleSheet", "#navMainBtn{ background-image: url(:fm-icon_01);margin: -30 0 0 -30;}"); stateDefault = new QState(stateGroup);
QState *stateSpread = new QState(_stateMachine); stateSpread = new QState(stateGroup);
stateSpread->assignProperty(ui->navMainBtn, "styleSheet", "#navMainBtn{ background-image: url(:fm-icon_02);margin: -30 0 0 -30;}"); stateDefault->assignProperty(this, "navImage", ":fm-icon_01");
stateSpread->addTransition(ui->navMainBtn, &QPushButton::clicked, stateDefault);
stateDefault->addTransition(ui->navMainBtn, &QPushButton::clicked, stateSpread); stateDefault->addTransition(ui->navMainBtn, &QPushButton::clicked, stateSpread);
stateSpread->assignProperty(this, "navImage", ":fm-icon_02");
stateSpread->addTransition(ui->navMainBtn, &QPushButton::clicked, stateDefault);
stateGroup->setInitialState(stateDefault);
QHistoryState *stateGroupHistory = new QHistoryState(stateGroup);
stateGroupHistory->setDefaultState(stateDefault);
_stateMachine->addState(stateGroup);
stateBlink = new QState(_stateMachine);
stateGroup->addTransition(this, &NavWindow::startBlink, stateBlink);
stateBlink->addTransition(ui->navMainBtn, &QPushButton::clicked, stateGroupHistory);
stateBlink->addTransition(this, &NavWindow::stopBlink, stateGroupHistory);
connect(stateBlink, &QState::exited, this, [=](){
_isStateBlink = false;
});
_stateMachine->addState(stateBlink);
connect(stateSpread, &QState::exited, this, [&](){ connect(stateSpread, &QState::exited, this, [&](){
ui->navMainBtn->raise(); ui->navMainBtn->raise();
...@@ -137,7 +161,7 @@ void NavWindow::initMenu() ...@@ -137,7 +161,7 @@ void NavWindow::initMenu()
} }
ui->navMainBtn->raise(); ui->navMainBtn->raise();
_stateMachine->addDefaultAnimation(_animationShow); _stateMachine->addDefaultAnimation(_animationShow);
_stateMachine->setInitialState(stateDefault); _stateMachine->setInitialState(stateGroup);
_stateMachine->start(); _stateMachine->start();
} }
...@@ -155,7 +179,7 @@ void NavWindow::initSystemTrayIcon() ...@@ -155,7 +179,7 @@ void NavWindow::initSystemTrayIcon()
auto quitAction = new QAction(QString::fromLocal8Bit("退出"), this); auto quitAction = new QAction(QString::fromLocal8Bit("退出"), this);
connect(quitAction, &QAction::triggered, this, [&](){ connect(quitAction, &QAction::triggered, this, [&](){
_systemTrayIcon->hide(); // _systemTrayIcon->hide();
emit menuBtnClicked("quit"); emit menuBtnClicked("quit");
}); });
auto menus = new QMenu(this); auto menus = new QMenu(this);
...@@ -169,3 +193,122 @@ void NavWindow::onMoved(QPoint point) ...@@ -169,3 +193,122 @@ void NavWindow::onMoved(QPoint point)
{ {
FMPHomeSettings::instance()->setWindowPosition(point); FMPHomeSettings::instance()->setWindowPosition(point);
} }
int NavWindow::addBlink(FMPluginInterface *plugin, const QString &image)
{
// Create blink's id.
int blinkId;
do{
blinkId = qrand();
}while(_blinkObjIdSet.contains(blinkId));
// Create BlinkObject.
BlinkObject bo = {
blinkId, plugin, image
};
_blinkObjQueue.push_back(bo);
_blinkObjIdSet.insert(blinkId);
// 如果blinkFuture正在运行则无需再次调用
if(!_blinkFuture.isRunning()) {
blink();
}
HOME_DEBUG() << "Add blink: " << blinkId;
return blinkId;
}
bool NavWindow::removeBlink(int blinkId)
{
bool isOk = false;
do {
isOk = _blinkObjIdSet.contains(blinkId);
if(!isOk) break;
for(int i=0; i<_blinkObjQueue.size(); ++i) {
if (_blinkObjQueue.at(i).id == blinkId) {
_blinkObjQueue.removeAt(i);
_blinkObjIdSet.remove(blinkId);
if(i==0 && _isStateBlink) {
emit stopBlink();
}
isOk = true;
break;
}
}
} while(0);
HOME_DEBUG() << "Stop blink: " << blinkId << " isOk: " << isOk;
return isOk;
}
void NavWindow::blink()
{
_blinkFuture = QtConcurrent::run([this](){
// 循环闪烁队列进行操作
while(!_blinkObjQueue.isEmpty()) {
BlinkObject blinkObject = _blinkObjQueue.first();
// 发送startBlink信号使状态机进入stateBlink
emit startBlink();
_isStateBlink = true;
QPropertyAnimation m_animation;
m_animation.setTargetObject(this);
m_animation.setPropertyName("windowOpacity");
m_animation.setDuration(200);
m_animation.setEasingCurve(QEasingCurve::InOutSine);
QEventLoop loop;
connect(&m_animation, &QPropertyAnimation::finished, &loop, &QEventLoop::quit);
//! 状态机在stateBlink时持续闪烁
//! 前面刚发送了startBlink信号,状态机可能还没切换到stateBlink状态,所以不能用stateBlink->active()方法.
while(_isStateBlink) {
m_animation.setStartValue(1);
m_animation.setEndValue(0);
m_animation.start();
loop.exec();
QString oldImage = _navImage;
setNavImage(blinkObject.image);
m_animation.setStartValue(0);
m_animation.setEndValue(1);
m_animation.start();
loop.exec();
m_animation.setStartValue(1);
m_animation.setEndValue(0);
m_animation.start();
loop.exec();
setNavImage(oldImage);
m_animation.setStartValue(0);
m_animation.setEndValue(1);
m_animation.start();
loop.exec();
}
if(_blinkObjIdSet.contains(blinkObject.id)) {
HOME_DEBUG() << "Active blink plugin: " << blinkObject.id;
// 如果blinkObject.id还在set中,说明没有调用该闪烁的stop方法,可以发送激活插件信号
emit pluginActived(blinkObject.plugin);
_blinkObjIdSet.remove(blinkObject.id);
_blinkObjQueue.pop_front();
}
}
});
}
QString NavWindow::navImage() const
{
return _navImage;
}
void NavWindow::setNavImage(const QString &image)
{
_navImage = image;
emit navImageChanged();
}
void NavWindow::onNavImageChanged()
{
ui->navMainBtn->setStyleSheet(QString(
"#navMainBtn{"
"background: url(%1) center no-repeat;"
"border: none;}"
).arg(_navImage));
}
...@@ -3,7 +3,10 @@ ...@@ -3,7 +3,10 @@
#include <QDialog> #include <QDialog>
#include <vector> #include <vector>
#include <QQueue>
#include <QSet>
#include <QString> #include <QString>
#include <QFuture>
namespace Ui { namespace Ui {
class NavWindow; class NavWindow;
...@@ -15,16 +18,35 @@ class QParallelAnimationGroup; ...@@ -15,16 +18,35 @@ class QParallelAnimationGroup;
class QSequentialAnimationGroup; class QSequentialAnimationGroup;
class FMPSettingsInterface; class FMPSettingsInterface;
class QStateMachine; class QStateMachine;
class QState;
class QSystemTrayIcon; class QSystemTrayIcon;
class FMPluginInterface;
/**
* struct BlinkObject '闪烁'结构体
* id: 闪烁对象的id
* plugin: 闪烁结束时回调的插件对象
* image: 闪烁的图片
**/
typedef struct {
int id;
FMPluginInterface *plugin;
QString image;
} BlinkObject;
class NavWindow : public QDialog class NavWindow : public QDialog
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QString navImage READ navImage WRITE setNavImage NOTIFY navImageChanged)
public: public:
explicit NavWindow(FMPSettingsInterface* &settings, QWidget *parent = 0); explicit NavWindow(QWidget *parent = 0);
~NavWindow(); ~NavWindow();
QString navImage() const;
void setNavImage(const QString &image);
public slots: public slots:
/** /**
...@@ -34,12 +56,48 @@ public slots: ...@@ -34,12 +56,48 @@ public slots:
*/ */
void spreadMenus(const bool isSpread); void spreadMenus(const bool isSpread);
/**
* @brief addBlink
* 向闪烁队列中添加一个闪烁对象
* @param plugin 闪烁对象的plugin
* @param image 闪烁对象的image
* @return 返回该闪烁的id
*/
int addBlink(FMPluginInterface *plugin, const QString &image);
/**
* @brief removeBlink
* 从闪烁队列中移除一个闪烁
* @param blinkId 要移除的闪烁对象的id
* @return 是否成功
*/
bool removeBlink(int blinkId);
signals: signals:
void menuBtnClicked(QString btnName); void menuBtnClicked(QString btnName);
/**
* @brief startBlink
* 此信号使状态机进入stateBlink
*/
void startBlink();
/**
* @brief stopBlink
* 此信号使状态机退出stateBlink
*/
void stopBlink();
/**
* @brief pluginActived
* 此信号在状态机在stateBlink并且点击导航按钮时发出
* @param plugin blinkObject的plugin
*/
void pluginActived(FMPluginInterface* plugin);
void navImageChanged();
private slots: private slots:
void onMenuBtnClicked(QAbstractButton*); void onMenuBtnClicked(QAbstractButton*);
void onMoved(QPoint point); void onMoved(QPoint point);
void onNavImageChanged();
private: private:
Ui::NavWindow *ui; Ui::NavWindow *ui;
...@@ -50,12 +108,29 @@ private: ...@@ -50,12 +108,29 @@ private:
QParallelAnimationGroup* _animationShow; QParallelAnimationGroup* _animationShow;
QRect _centerGeometry; QRect _centerGeometry;
QStateMachine *_stateMachine; QStateMachine *_stateMachine;
QState *stateGroup;
QState *stateDefault;
QState *stateSpread;
QState *stateBlink;
QString _navImage;
//! 标识状态机是否在stateBlink状态
//! 之所以没用bool QState::active()方法是因为多进程同步问题
bool _isStateBlink;
//! 闪烁队列、闪烁id的set及执行闪烁的进程future
QQueue<BlinkObject> _blinkObjQueue;
QSet<int> _blinkObjIdSet;
QFuture<void> _blinkFuture;
void initMenu();
//! System tray icon. //! System tray icon.
QSystemTrayIcon *_systemTrayIcon; QSystemTrayIcon *_systemTrayIcon;
private:
void initSystemTrayIcon(); void initSystemTrayIcon();
void initMenu();
void blink();
private: private:
/** /**
......
...@@ -15,8 +15,7 @@ ...@@ -15,8 +15,7 @@
</property> </property>
<property name="styleSheet"> <property name="styleSheet">
<string notr="true">#navMainBtn { <string notr="true">#navMainBtn {
background-image: url(:fm-icon_01); background: url(:fm-icon_01) center no-repeat;
margin: -30 0 0 -30;
border: none; border: none;
} }
......
...@@ -31,12 +31,13 @@ int FMPHomePrivate::Init() ...@@ -31,12 +31,13 @@ int FMPHomePrivate::Init()
_settings = q->GetService<FMPSettingsInterface>(q->_ctx); _settings = q->GetService<FMPSettingsInterface>(q->_ctx);
FMPHomeSettings::instance()->init(_settings, logger); FMPHomeSettings::instance()->init(_settings, logger);
_navWindow = new NavWindow(_settings); _navWindow = new NavWindow;
FMPStartEventHandler* handler = new FMPStartEventHandler(q->_ctx, q); FMPStartEventHandler* handler = new FMPStartEventHandler(q->_ctx, q);
_navWindow->show(); _navWindow->show();
connect(_navWindow, SIGNAL(menuBtnClicked(QString)), this, SLOT(onMenuBtnClicked(QString))); connect(_navWindow, SIGNAL(menuBtnClicked(QString)), this, SLOT(onMenuBtnClicked(QString)));
connect(_navWindow, &NavWindow::pluginActived, this, &FMPHomePrivate::onPluginActived);
q->_inited = true; q->_inited = true;
return FMP_SUCCESS; return FMP_SUCCESS;
...@@ -76,6 +77,25 @@ int FMPHomePrivate::login() ...@@ -76,6 +77,25 @@ int FMPHomePrivate::login()
} }
} }
int FMPHomePrivate::blink(FMPluginInterface *plugin, const QString &image)
{
int blinkId = _navWindow->addBlink(plugin, image);
return blinkId;
}
bool FMPHomePrivate::stopBlink(int blinkId)
{
return _navWindow->removeBlink(blinkId);
}
void FMPHomePrivate::onPluginActived(FMPBaseInterface *plugin)
{
if(plugin != nullptr) {
plugin->StartService();
}
}
void FMPHomePrivate::onMenuBtnClicked(QString btnName) void FMPHomePrivate::onMenuBtnClicked(QString btnName)
{ {
Q_Q(FMPHome); Q_Q(FMPHome);
......
...@@ -20,8 +20,12 @@ public: ...@@ -20,8 +20,12 @@ public:
void StartPlugins(const QVariantList &pids); void StartPlugins(const QVariantList &pids);
int login(); int login();
int blink(FMPluginInterface *plugin, const QString &image);
bool stopBlink(int blinkId);
public slots: public slots:
void onMenuBtnClicked(QString btnName); void onMenuBtnClicked(QString btnName);
void onPluginActived(FMPBaseInterface* plugin);
public: public:
FMPHome *q_ptr; FMPHome *q_ptr;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment