Qt全局信号管理器

目的

Qt信号在多对象之间传递非常的不方便,绑定时必须持有对象,这存在很大的局限性。所以我就想能不能用信号ID来做唯一标识,将信号和槽进行解耦。

代码

头文件

#ifndef HGSSIGNALMANAGER_H
#define HGSSIGNALMANAGER_H

#include <QObject>
#include <iostream>
#include <QList>
#include <QMap>
#include <memory>

#include "h_basegui_global.h"

//自定义信号ID
enum HgsSignalID
{
	SIGNALS_TEST_VOID = 0,
	SIGNALS_TEST_QT = 1,
	SIGNALS_TEST_CONSUMER = 2
};

//连接信息结构体
typedef struct HgsLinkInfo
{
	HgsSignalID id;		//信号ID
	QObject* object;		//Qt对象
	const char* method;	//信号或者槽函数
	Qt::ConnectionType connectType = Qt::AutoConnection;	//连接方式,信号不用关注
}HgsSignalInfo, HgsSlotInfo;


class H_BASEGUI_EXPORT HgsSignalManager : public QObject
{
	Q_OBJECT

public:
	/*
	*申明成单例类方便调用
	*/
	static HgsSignalManager* getInstall();

	/*
	* 按信号ID注册信号
	* @Parameter: HgsSignalID signalID 信号ID
	* @Parameter: QObject * sender     发送者句柄
	* @Parameter: const char * method  信号函数
	* @Returns:   void
	*/
	void registerSignal(HgsSignalID signalID, QObject* sender, const char* method);


	/*
	* 按信号ID绑定槽函数
	* @Parameter: HgsSignalID signalID 信号ID
	* @Parameter: QObject * sender	   接收者句柄	
	* @Parameter: const char * method  槽函数 	
	* @Parameter: Qt::ConnectionType connectType 连接类型
	* @Returns:   void
	*/
	void bindSlot(HgsSignalID signalID, QObject* recever, const char* method, Qt::ConnectionType connectType = Qt::AutoConnection);


	/*
	* 连接信号与槽,一般在main函数最后调用
	* 将信号与槽函数全部绑定上
	* @Returns:   void
	*/
	void linkSignalSlot();

	/*
	* 解绑信号,先阶段还没实现
	*/
	//void unLinkSignalSlot(HgsSignalID signalId);
public:
private:
	HgsSignalManager();

private:
	typedef QList<HgsLinkInfo> LinkList;
	typedef QMap<QObject*, LinkList> SignalLinkMap;
	typedef QMap<QObject*, LinkList> SlotLinkMap;

	QMap<HgsSignalID, SignalLinkMap> m_signalMap;
	QMap<HgsSignalID, SlotLinkMap> m_slotMap;
private:
	static HgsSignalManager* m_pInstall;
};

#endif // HGSSIGNALMANAGER_H

实现

#include "precompiler.h"
#include "HgsSignalManager.h"

#include <QDebug>

HgsSignalManager* HgsSignalManager::m_pInstall = nullptr;

HgsSignalManager* HgsSignalManager::getInstall()
{
	if (nullptr == m_pInstall)
	{
		m_pInstall = new HgsSignalManager();
	}

	return m_pInstall;
}

void HgsSignalManager::registerSignal(HgsSignalID signalId, QObject* sender, const char* method)
{
	auto iterSignal = m_signalMap.find(signalId);
	if (iterSignal == m_signalMap.end())
	{
		//新增信号ID
		HgsSignalInfo info;
		info.id = signalId;
		info.object = sender;
		info.method = method;

		LinkList list;
		list.push_back(info);

		SignalLinkMap linkMap;
		linkMap[sender] = list;

		m_signalMap[signalId] = linkMap;
	}
	else
	{
		HgsSignalInfo info;
		info.id = signalId;
		info.object = sender;
		info.method = method;

		SignalLinkMap linkMap = m_signalMap[signalId];
		auto iterLink = linkMap.find(sender);
		if (iterLink == linkMap.end())
		{
			LinkList list;
			list.push_back(info);

			linkMap[sender] = list;
			m_signalMap[signalId] = linkMap;
		}
		else
		{
			LinkList list = linkMap[sender];
			list.push_back(info);

			linkMap[sender] = list;
			m_signalMap[signalId] = linkMap;
		}
	}
}

void HgsSignalManager::bindSlot(HgsSignalID signalId, QObject* recever, const char* method, Qt::ConnectionType connectType)
{
	auto iterSignal = m_slotMap.find(signalId);
	if (iterSignal == m_slotMap.end())
	{
		//新增信号ID
		HgsSlotInfo info;
		info.id = signalId;
		info.object = recever;
		info.method = method;
		info.connectType = connectType;

		LinkList list;
		list.push_back(info);

		SignalLinkMap linkMap;
		linkMap[recever] = list;

		m_slotMap[signalId] = linkMap;
	}
	else
	{
		HgsSignalInfo info;
		info.id = signalId;
		info.object = recever;
		info.method = method;
		info.connectType = connectType;

		SignalLinkMap linkMap = m_slotMap[signalId];
		auto iterLink = linkMap.find(recever);
		if (iterLink == linkMap.end())
		{
			LinkList list;
			list.push_back(info);

			linkMap[recever] = list;
			m_slotMap[signalId] = linkMap;
		}
		else
		{
			LinkList list = linkMap[recever];
			list.push_back(info);

			linkMap[recever] = list;
			m_slotMap[signalId] = linkMap;
		}
	}
}

void HgsSignalManager::linkSignalSlot()
{
	auto iter = m_signalMap.begin();
	for (iter; iter != m_signalMap.end(); ++iter)
	{
		HgsSignalID signalId = iter.key();
		auto slotLinkMapIter = m_slotMap.find(signalId);
		if (slotLinkMapIter == m_slotMap.end())
		{
			continue;
		}

		auto signalLinkMap = iter.value();
		auto slotLinkMap = slotLinkMapIter.value();

		auto iterSignalLink = signalLinkMap.begin();
		for (iterSignalLink; iterSignalLink != signalLinkMap.end(); ++iterSignalLink)
		{
			auto iterSlotLink = slotLinkMap.begin();
			for (iterSlotLink; iterSlotLink != slotLinkMap.end(); ++iterSlotLink)
			{
				auto signalLinkList = iterSignalLink.value();
				auto slotLinkList = iterSlotLink.value();

				for (int i = 0; i < signalLinkList.count(); ++i)
				{
					for (int j= 0; j < slotLinkList.count(); ++ j)
					{
						auto signalLinkInfo = signalLinkList.value(i);
						auto slotLinkInfo = slotLinkList.value(j);
						connect(signalLinkInfo.object, signalLinkInfo.method, slotLinkInfo.object, slotLinkInfo.method, slotLinkInfo.connectType);
					}
				}
			}
		}
	}
}

// void HgsSignalManager::unLinkSignalSlot(HgsSignalID signalId)
// {
// 	auto iterSignalLinkMap = m_signalMap.find(signalId);
// 	if (iterSignalLinkMap == m_signalMap.end())
// 	{
// 		return;
// 	}
// 
// 	auto iterSlotLinkMap = m_slotMap.find(signalId);
// 	if (iterSlotLinkMap == m_slotMap.end())
// 	{
// 		return;
// 	}
// 
// 	auto signalLinkMap = iterSignalLinkMap.value();
// 	auto slotLinkMap = iterSlotLinkMap.value();
// 
// 	auto iterSignalLink = signalLinkMap.begin();
// 	for (iterSignalLink; iterSignalLink != signalLinkMap.end(); ++iterSignalLink)
// 	{
// 		auto iterSlotLink = slotLinkMap.begin();
// 		for (iterSlotLink; iterSlotLink != slotLinkMap.end(); ++iterSlotLink)
// 		{
// 			auto signalLinkList = iterSignalLink.value();
// 			auto slotLinkList = iterSlotLink.value();
// 
// 			for (int i = 0; i < signalLinkList.count(); ++i)
// 			{
// 				for (int j = 0; j < slotLinkList.count(); ++j)
// 				{
// 					auto signalLinkInfo = signalLinkList.value(i);
// 					auto slotLinkInfo = slotLinkList.value(j);
// 					disconnect(signalLinkInfo.object, signalLinkInfo.method, slotLinkInfo.object, slotLinkInfo.method);
// 				}
// 			}
// 		}
// 	}
// }

HgsSignalManager::HgsSignalManager()
{

}

特别注意

HgsSignalManager::linkSignalSlot()

1.该函数在当前版本只能调用一次,调用多次存在重复连接问题
2.该函数一般在所有信号注册完毕,所有曹函数绑定完毕后调用。所以我一般在main函数的末尾调用

后续计划

1.细化连接信息的存储,内部自动检测当前信号是否已连接,避免重复连接
2.添加取消绑定函数

  1. 按信号ID解绑
  2. 按信号发送者解绑
  3. 按信号接收者解绑

结尾

谢谢,如有错误请指正

资源

测试代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值