Commit d8fe97ad by NitefullWind

Merge branch 'fmp_home'

parents 17f2ea8c 0544763e
......@@ -51,3 +51,15 @@ QString FMPHome::userName()
Q_D(FMPHome);
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:
bool isLogined();
QString userName();
int blink(FMPluginInterface *plugin, const QString &image);
bool stopBlink(int blinkId);
private:
FMPHomePrivate *d_ptr;
bool _inited;
......
......@@ -6,7 +6,7 @@
TEMPLATE = lib
QT += core gui network
QT += core gui network concurrent
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
......
......@@ -10,6 +10,22 @@ public:
virtual int login() = 0;
virtual bool isLogined() = 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")
......
......@@ -9,10 +9,12 @@
#include <QPropertyAnimation>
#include <QEasingCurve>
#include <QStateMachine>
#include <QHistoryState>
#include <QSystemTrayIcon>
#include <QMenu>
#include <QtConcurrent>
NavWindow::NavWindow(FMPSettingsInterface *&settings, QWidget *parent) :
NavWindow::NavWindow(QWidget *parent) :
QDialog(parent),
ui(new Ui::NavWindow),
_btn_group(new QButtonGroup(this)),
......@@ -43,14 +45,22 @@ NavWindow::NavWindow(FMPSettingsInterface *&settings, QWidget *parent) :
this->move(FMPHomeSettings::instance()->getWindowPosition());
connect(ui->navMainBtn, SIGNAL(moved(QPoint)), this, SLOT(onMoved(QPoint)));
connect(this, SIGNAL(navImageChanged()), this, SLOT(onNavImageChanged()));
}
NavWindow::~NavWindow()
{
delete _btn_group;
for(int i=0; i<actions.size(); ++i) {
delete actions.at(i);
}
actions.clear();
delete _animationShow;
delete _systemTrayIcon;
delete stateGroup;
delete stateDefault;
delete stateSpread;
delete stateBlink;
delete ui;
}
......@@ -80,12 +90,26 @@ void NavWindow::spreadMenus(const bool isSpread)
void NavWindow::initMenu()
{
QState *stateDefault = new QState(_stateMachine);
stateDefault->assignProperty(ui->navMainBtn, "styleSheet", "#navMainBtn{ background-image: url(:fm-icon_01);margin: -30 0 0 -30;}");
QState *stateSpread = new QState(_stateMachine);
stateSpread->assignProperty(ui->navMainBtn, "styleSheet", "#navMainBtn{ background-image: url(:fm-icon_02);margin: -30 0 0 -30;}");
stateSpread->addTransition(ui->navMainBtn, &QPushButton::clicked, stateDefault);
stateGroup = new QState(_stateMachine);
stateDefault = new QState(stateGroup);
stateSpread = new QState(stateGroup);
stateDefault->assignProperty(this, "navImage", ":fm-icon_01");
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, [&](){
ui->navMainBtn->raise();
......@@ -137,7 +161,7 @@ void NavWindow::initMenu()
}
ui->navMainBtn->raise();
_stateMachine->addDefaultAnimation(_animationShow);
_stateMachine->setInitialState(stateDefault);
_stateMachine->setInitialState(stateGroup);
_stateMachine->start();
}
......@@ -155,7 +179,7 @@ void NavWindow::initSystemTrayIcon()
auto quitAction = new QAction(QString::fromLocal8Bit("退出"), this);
connect(quitAction, &QAction::triggered, this, [&](){
_systemTrayIcon->hide();
// _systemTrayIcon->hide();
emit menuBtnClicked("quit");
});
auto menus = new QMenu(this);
......@@ -169,3 +193,122 @@ void NavWindow::onMoved(QPoint 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 @@
#include <QDialog>
#include <vector>
#include <QQueue>
#include <QSet>
#include <QString>
#include <QFuture>
namespace Ui {
class NavWindow;
......@@ -15,16 +18,35 @@ class QParallelAnimationGroup;
class QSequentialAnimationGroup;
class FMPSettingsInterface;
class QStateMachine;
class QState;
class QSystemTrayIcon;
class FMPluginInterface;
/**
* struct BlinkObject '闪烁'结构体
* id: 闪烁对象的id
* plugin: 闪烁结束时回调的插件对象
* image: 闪烁的图片
**/
typedef struct {
int id;
FMPluginInterface *plugin;
QString image;
} BlinkObject;
class NavWindow : public QDialog
{
Q_OBJECT
Q_PROPERTY(QString navImage READ navImage WRITE setNavImage NOTIFY navImageChanged)
public:
explicit NavWindow(FMPSettingsInterface* &settings, QWidget *parent = 0);
explicit NavWindow(QWidget *parent = 0);
~NavWindow();
QString navImage() const;
void setNavImage(const QString &image);
public slots:
/**
......@@ -34,12 +56,48 @@ public slots:
*/
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:
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:
void onMenuBtnClicked(QAbstractButton*);
void onMoved(QPoint point);
void onNavImageChanged();
private:
Ui::NavWindow *ui;
......@@ -50,12 +108,29 @@ private:
QParallelAnimationGroup* _animationShow;
QRect _centerGeometry;
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.
QSystemTrayIcon *_systemTrayIcon;
private:
void initSystemTrayIcon();
void initMenu();
void blink();
private:
/**
......
......@@ -15,8 +15,7 @@
</property>
<property name="styleSheet">
<string notr="true">#navMainBtn {
background-image: url(:fm-icon_01);
margin: -30 0 0 -30;
background: url(:fm-icon_01) center no-repeat;
border: none;
}
......
......@@ -31,12 +31,13 @@ int FMPHomePrivate::Init()
_settings = q->GetService<FMPSettingsInterface>(q->_ctx);
FMPHomeSettings::instance()->init(_settings, logger);
_navWindow = new NavWindow(_settings);
_navWindow = new NavWindow;
FMPStartEventHandler* handler = new FMPStartEventHandler(q->_ctx, q);
_navWindow->show();
connect(_navWindow, SIGNAL(menuBtnClicked(QString)), this, SLOT(onMenuBtnClicked(QString)));
connect(_navWindow, &NavWindow::pluginActived, this, &FMPHomePrivate::onPluginActived);
q->_inited = true;
return FMP_SUCCESS;
......@@ -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)
{
Q_Q(FMPHome);
......
......@@ -20,8 +20,12 @@ public:
void StartPlugins(const QVariantList &pids);
int login();
int blink(FMPluginInterface *plugin, const QString &image);
bool stopBlink(int blinkId);
public slots:
void onMenuBtnClicked(QString btnName);
void onPluginActived(FMPBaseInterface* plugin);
public:
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