基于索引导航控件,根据索引对联系人分组,支持多种操作模式,允许自定义设置正则表达式判断号码运营商。
根据以往惯例,先上图
有关运营商正则匹配代码如下
/// 运营商正则列表
/// 注意:暂未使用,可自行实现,默认顺序为0中国移动,1中国联通,2中国电信
/// \brief sIspNumRegexList
///
QList<QString> Lncf_NavCharHelper::sIspNumRegexList = QList<QString>()<<"^(086|086\\ |086\\-|\\+86|86|\\+86\\ |\\+86\\-|86\\-|86\\ |)1(3([4-9])|4([7-8]|40)|5([0-2]|[7-9])|7(8|03|05|06)|8([2-4]|[7-8])|9(8))\\d{7,8}$"
<<"(086|086\\ |086\\-|\\+86|86|\\+86\\ |\\+86\\-|86\\-|86\\ |)1(3([0-2])|4([5-6])|5([5-6])|6([6-7])|7([5-6]|04|07|08|09|10|11|12|13|14|15|16|17|18|19)|8([5-6]))\\d{7,8}$"
<<"^(086|086\\ |086\\-|\\+86|86|\\+86\\ |\\+86\\-|86\\-|86\\ |)1(3([3]|[49])|4(10)|5(3)|7([7|00|01|02|40])|8([0-1]|[9])|9([1|9]))\\d{7,8}$";
/// 获取电话号码运营商
/// \brief GetPhoneNumIspIndex
/// \param sText
/// \return
///
uint Lncf_NavCharHelper::GetPhoneNumIspIndex(QString sText)
{
uint uCount = sIspNumRegexList.count();
for(uint i=0;i<uCount;i++){
std::regex rPhoneNum(sIspNumRegexList[i].toStdString());
if(std::regex_match(sText.toStdString(), rPhoneNum)){
return i;
}
}
return 65535;//65535标识未知运营商
}
/// 添加运营商号码段正则匹配
/// \brief AddIspNumRegexDatas
/// \param sText
///
uint Lncf_NavCharHelper::AddIspNumRegexDatas(QString sText)
{
if(!sText.isEmpty())
{
sIspNumRegexList.insert(sIspNumRegexList.count(),sText);
return sIspNumRegexList.count()-1;
}
return 0;
}
自定义属性结构定义如下
/// 通讯录列表项风格委托样式数据结构
///
typedef struct LQCONTACTLIST_STYLE_{
QColor cGroupBkgColor = QColor(88,88,88,44); //分组背景色
QColor cGroupExpanClr = QColor(77,77,77,44); //分组展开背景色
QColor cGroupHoverClr = QColor(0,0,9,66); //分组鼠标悬停背景颜色
QColor cGroupExpHover = QColor(0,0,9,33); //分组展开悬停背景色
QColor cGroupsBorders = QColor(117,131,218); //分组边框颜色
QColor cItemsBkgColor = Qt::transparent;//联系人背景色
QColor cItemsHoverClr = QColor(69,176,142); //联系人鼠标悬停背景色
QColor cItemSelectClr = QColor(244,123,64); //联系人选中背景色
QColor cIconHoverClrs = QColor(22,22,22,44); //鼠标悬停颜色
QColor cIconSelectClr = QColor(11,11,11,44); //选中项时颜色
QColor cItemNamesClrs = QColor(33,33,33); //联系人名称文字颜色
QColor cNameHoverClrs = QColor(220,220,220); //联系人名称文字鼠标悬停时颜色
QColor cNameSelectClr = QColor(255,255,255); //联系人名称文字选中时颜色
QColor cGroupTxtColor = QColor(44,44,44); //分组背景色
QColor cGroupHoverTxt = QColor(255,255,255); //分组鼠标悬停背景颜色
QColor cGroupExpanTxt = QColor(33,33,33); //分组鼠标悬停背景颜色
QColor cItemsTxtColor = QColor(33,33,33); //联系人文字颜色
QColor cItemsHoverTxt = QColor(255,255,255); //联系人鼠标悬停文字色
QColor cItemSelectTxt = QColor(235,235,235); //联系人选中文字色
QColor cGroupCountBkg = QColor(127,127,127,127); //分组成员统计背景颜色
QColor cGroupCountTxt = QColor(220,220,220); //分组成员统计文字颜色
QColor cGroupNodeClrs = QColor(127,127,127); //分组节点图标颜色
QColor cGroupNodeBkgd = QColor(58,191,136); //分组节点背景颜色
QColor cGroupNodesExp = QColor(114,133,218); //分组节点展开背景颜色
QColor cDescHoverClrs = QColor(144,144,144); //摘要文字鼠标悬停颜色
QColor cDescSelectClr = QColor(200,200,200); //摘要文字选中颜色
QColor cItemSplitLine = QColor(63,166,148,66); //分割线颜色
QColor cAvatarFrmClrs = QColor(250,74,33); //头像边框颜色
QColor cMouseHoverBkg = QColor(124,144,218); //鼠标悬停背景颜色
QColor cAvatarBkgClrs = QColor(55,55,55); //头像背景填充颜色
QColor cIspLogoBkgClr = QColor(192,192,192,127); //ISP节点颜色
QColor cOptionBkgClrs = QColor(248,148,72); //选项按钮背景颜色
QColor cCallBkgndClrs = QColor(130,144,228); //呼叫按钮悬停颜色
QColor cInviteBkgClrs = QColor(71,186,152); //邀请按钮悬停颜色
QColor cSentMailBgClr = QColor(89,83,170); //发送邮件按钮悬停颜色
QColor cChatMsgBkgClr = QColor(128,173,88); //发起会话按钮悬停颜色
QColor cOptionHoveClr = QColor(248,74,99); //选项按钮悬停颜色
QColor cAnimateColors = QColor(44,44,44,44); //点击动画效果背景颜色
uint uDescPrioritys =0; //摘要优先级,0手机号码,2电子邮件,3固话,4地址,5存根
bool bRoundActiveBg = true; //选中背景是否绘制成半圆
uint uRoundActivPos = 0; //半圆背景位置,0左侧,1右侧
bool bShowSplitLine = false; //是否显示分割线
uint nSplitLineType = 2; //分割线样式,0实线,1虚线,2点线,3点划线,4双点划线
uint nHeadeLineType = 2; //标头参考线样式,0实线,1虚线,2点线,3点划线,4双点划线
bool bIconViewModel = false; //是否为列表视图,默认是
uint uItemHeightVal = 50; //行高
uint uItemMinHeight = 34; //小图标模式行高
uint uGroupsHeights = 26; //分组行高
uint uIconGridWidth = 72; //ICON视图格子宽度
uint uIconGridHeigh = 100; //ICON视图格子高度
uint uGroupStyleIds = 0; //分组风格,0默认风格,1居中
uint uGroupBorderId = 3; //分组边框风格,0不显示边框,1全部边框,2上,3下
float fBordersWidths = 0.5; //边框宽度
double dGroupRadiusId = 0; //分组边框半径
uint uItemsStyleIds = 0; //列表项风格,0大图标模式,1小图标模式
uint uHorizeMarginG = 0; //分组项水平Margin
uint uVerticMarginG = 0; //分组项垂直Margin
uint uHorizeMarginU = 0; //联系人项水平Margin
uint uVerticMarginU = 0; //联系人项垂直Margin
double dAvatarsRadius = 0.5; //联系人头像圆角半径
bool bHasGroupArrow = false; //是否使用分组箭头,默认为否,显示圆点
uint uLogoStylesIds = 1; //摘要logo类型,0图标,1文字,其它不显示
bool bShowUserCount = true; //是否显示分组成员统计
bool bIsShowSummary = true; //显示用户摘要,如果为false则表示显示来源
bool bShowOptionBtn = true; //是否绘制选项按钮
bool bIsShowCallBtn = true; //是否显示呼叫按钮
bool bIsShowMailBtn = true; //是否显示发送邮件按钮
bool bShowInviteBtn = true; //是否显示邀请按钮
bool bIsShowChatBtn = true; //是否显示会话按钮
bool bIsShowMoreBtn = true; //是否显示自定义处理按钮
bool bRandomAvbgClr = true; //在显示文字头像事是否使用随机背景颜色
uint bAvatarsStyles = 0; //头像显示风格索引,0仅显示图像,无头像图像时显示默认头像,1无图像时显示名称第一字符,2仅显示名称第一字符
bool operator == (const LQCONTACTLIST_STYLE_& rhs) // == 操作运算符重载
{
return (cGroupBkgColor == rhs.cGroupBkgColor) //分组背景色
&& (cGroupExpanClr == rhs.cGroupExpanClr) //分组展开背景色
&& (cGroupHoverClr == rhs.cGroupHoverClr) //分组鼠标悬停背景颜色
&& (cGroupExpHover == rhs.cGroupExpHover) //分组展开悬停背景色
&& (cGroupsBorders == rhs.cGroupsBorders) //分组边框颜色
&& (cItemsBkgColor == rhs.cItemsBkgColor) //联系人背景色
&& (cItemsHoverClr == rhs.cItemsHoverClr) //联系人鼠标悬停背景色
&& (cItemSelectClr == rhs.cItemSelectClr) //联系人选中背景色
&& (cIconHoverClrs == rhs.cIconHoverClrs) //鼠标悬停颜色
&& (cIconSelectClr == rhs.cIconSelectClr) //选中项时颜色
&& (cItemNamesClrs == rhs.cItemNamesClrs) //联系人名称文字颜色
&& (cNameHoverClrs == rhs.cNameHoverClrs) //联系人名称文字鼠标悬停时颜色
&& (cNameSelectClr == rhs.cNameSelectClr) //联系人名称文字选中时颜色
&& (cGroupTxtColor == rhs.cGroupTxtColor) //分组背景色
&& (cGroupHoverTxt == rhs.cGroupHoverTxt) //分组鼠标悬停背景颜色
&& (cGroupExpanTxt == rhs.cGroupExpanTxt) //分组鼠标悬停背景颜色
&& (cItemsTxtColor == rhs.cItemsTxtColor) //联系人文字颜色
&& (cItemsHoverTxt == rhs.cItemsHoverTxt) //联系人鼠标悬停文字色
&& (cItemSelectTxt == rhs.cItemSelectTxt) //联系人选中文字色
&& (cGroupCountBkg == rhs.cGroupCountBkg) //分组成员统计背景颜色
&& (cGroupCountTxt == rhs.cGroupCountTxt) //分组成员统计文字颜色
&& (cGroupNodeClrs == rhs.cGroupNodeClrs) //分组节点图标颜色
&& (cGroupNodeBkgd == rhs.cGroupNodeBkgd) //分组节点背景颜色
&& (cGroupNodesExp == rhs.cGroupNodesExp) //分组节点展开背景颜色
&& (cDescHoverClrs == rhs.cDescHoverClrs) //摘要文字鼠标悬停颜色
&& (cDescSelectClr == rhs.cDescSelectClr) //摘要文字选中颜色
&& (cItemSplitLine == rhs.cItemSplitLine) //分割线颜色
&& (cAvatarFrmClrs == rhs.cAvatarFrmClrs) //头像边框颜色
&& (cMouseHoverBkg == rhs.cMouseHoverBkg) //鼠标悬停背景颜色
&& (cAvatarBkgClrs == rhs.cAvatarBkgClrs) //头像背景填充颜色
&& (cIspLogoBkgClr == rhs.cIspLogoBkgClr) //ISP节点颜色
&& (cOptionBkgClrs == rhs.cOptionBkgClrs) //选项按钮背景颜色
&& (cCallBkgndClrs == rhs.cCallBkgndClrs) //呼叫按钮悬停颜色
&& (cInviteBkgClrs == rhs.cInviteBkgClrs) //邀请按钮悬停颜色
&& (cSentMailBgClr == rhs.cSentMailBgClr) //发送邮件按钮悬停颜色
&& (cChatMsgBkgClr == rhs.cChatMsgBkgClr) //发起会话按钮悬停颜色
&& (cOptionHoveClr == rhs.cOptionHoveClr) //选项按钮悬停颜色
&& (uDescPrioritys == rhs.uDescPrioritys) //摘要优先级,0手机号码,2电子邮件,3固话,4地址,5存根
&& (bRoundActiveBg == rhs.bRoundActiveBg) //选中背景是否绘制成半圆
&& (bShowSplitLine == rhs.bShowSplitLine) //是否显示分割线
&& (uRoundActivPos == rhs.uRoundActivPos)
&& (nSplitLineType == rhs.nSplitLineType) //分割线样式,0实线,1虚线,2点线,3点划线,4双点划线
&& (nHeadeLineType == rhs.nHeadeLineType) //标头参考线样式,0实线,1虚线,2点线,3点划线,4双点划线
&& (bIconViewModel == rhs.bIconViewModel) //是否为列表视图,默认是
&& (uItemHeightVal == rhs.uItemHeightVal) //行高
&& (uItemMinHeight == rhs.uItemMinHeight) //小图标模式行高
&& (uGroupsHeights == rhs.uGroupsHeights) //分组行高
&& (uIconGridWidth == rhs.uIconGridWidth) //ICON视图格子宽度
&& (uIconGridHeigh == rhs.uIconGridHeigh) //ICON视图格子高度
&& (uGroupStyleIds == rhs.uGroupStyleIds) //分组风格,0默认风格,1居中
&& (uGroupBorderId == rhs.uGroupBorderId) //分组边框风格,0不显示边框,1全部边框,2上,3下
&& (fBordersWidths == rhs.fBordersWidths) //边框宽度
&& (dGroupRadiusId == rhs.dGroupRadiusId) //分组边框半径
&& (uItemsStyleIds == rhs.uItemsStyleIds) //列表项风格,0大图标模式,1小图标模式
&& (uHorizeMarginG == rhs.uHorizeMarginG) //分组项水平Margin
&& (uVerticMarginG == rhs.uVerticMarginG) //分组项垂直Margin
&& (uHorizeMarginU == rhs.uHorizeMarginU) //联系人项水平Margin
&& (uVerticMarginU == rhs.uVerticMarginU) //联系人项垂直Margin
&& (dAvatarsRadius == rhs.dAvatarsRadius) //联系人头像圆角半径
&& (bHasGroupArrow == rhs.bHasGroupArrow) //是否显示分组箭头
&& (uLogoStylesIds == rhs.uLogoStylesIds) //运行商logo类型,0图标,1文字
&& (bShowUserCount == rhs.bShowUserCount) //是否显示分组成员统计
&& (bIsShowSummary == rhs.bIsShowSummary) //显示用户摘要,如果为false则表示显示来源
&& (bShowOptionBtn == rhs.bShowOptionBtn) //是否显示选项按钮
&& (bIsShowCallBtn == rhs.bIsShowCallBtn) //是否显示呼叫按钮
&& (bIsShowMailBtn == rhs.bIsShowMailBtn) //是否显示发送邮件按钮
&& (bShowInviteBtn == rhs.bShowInviteBtn) //是否显示邀请按钮
&& (bIsShowChatBtn == rhs.bIsShowChatBtn) //是否显示会话按钮
&& (bIsShowMoreBtn == rhs.bIsShowMoreBtn) //是否显示自定义处理按钮
&& (bRandomAvbgClr == rhs.bRandomAvbgClr) //在显示文字头像事是否使用随机背景颜色
&& (bAvatarsStyles == rhs.bAvatarsStyles); //头像显示风格索引,0仅显示图像,无头像图像时显示默认头像,1无图像时显示名称第一字符,2仅显示名称第一字符
}
bool operator != (const LQCONTACTLIST_STYLE_& rhs) // != 操作运算符重载
{
return !(*this == rhs);
}
}LQCONTACTLIST_STYLE,*PLQCONTACTLIST_STYLE;
绘制委托定义主要代码如下
class LNCF_QTSOCIALLIBS_API Lncf_QContactItemd:public Lncf_QListDelegate
{
Q_OBJECT
public:
explicit Lncf_QContactItemd(QObject *parent = nullptr);
~Lncf_QContactItemd();
private:
/// 初始化通讯录列表委托
/// \brief InitContactItemd
///
void InitContactItemd();
private:
/// 通讯录列表项风格委托样式数据结构变量
/// \brief tDelegateStyle
///
LQCONTACTLIST_STYLE tDelegateStyle;
std::u16string sOtherAppIcons; //其它应用图标
std::u16string sSourceAppsImg; //默认来源应用图标
std::u16string sGroupExpanImg; //分组展开图标
std::u16string sGroupCloseImg; //分组关闭图标
std::u16string sCallNumberImg; //呼叫号码图标
std::u16string sSentChatImage; //发起会话图标
std::u16string sSentMailImage; //发送邮件图标
std::u16string sInviteRegImgs; //邀请注册图标
std::u16string sMoreOptionImg; //更多选项图标
std::u16string sLocationImage; //位置图标
QList<std::u16string> sIspLogosLists; //运营商Logo列表,0未知,1移动,2联通,3电信,可自行添加或更改
QList<std::u16string> sIspNamesLists; //运营商名称列表
QList<QColor> vRandomClolors; //随机颜色列表
QImage pGroupExpanImg; //分组展开图标对象
QImage pGroupCloseImg; //分组收起图标对象
private:
/// 重写系统绘制
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE;
/// 绘制背景
/// \brief DrawBackgrounds
/// \param painter
/// \param option
/// \param bGroup
/// \param bExpand
///
void DrawBackgrounds(QPainter *painter,const QStyleOptionViewItem &option, const QModelIndex &index,bool bGroup,bool bExpand) const;
/// 绘制分组项
/// \brief DrawItemsGroups
/// \param painter :绘图引擎指针
/// \param option :视图风格选项引用参数
/// \param groupData :索引分组列表视图数据结构参数
///
void DrawItemsGroups(QPainter *painter,const QStyleOptionViewItem &option,bool bExpand,LQNAVLISTVIEW_GROUP groupData) const;
/// 绘制通讯录联系人项
/// \brief DrawItemContact
/// \param painter :绘图引擎指针
/// \param option :视图风格选项引用参数
/// \param itemsData :通讯录联系人视图数据结构参数
///
void DrawItemContact(QPainter *painter,const QStyleOptionViewItem &option, const QModelIndex &index,LNCFQCONTACT_LISTVIEWS itemsData) const;
/// 绘制头像
/// \brief DrawItemsAvatar
/// \param painter
/// \param option
/// \param sImagePath
/// \param bHover
/// \param sName
///
void DrawItemsAvatar(QPainter *painter,const QStyleOptionViewItem &option,std::u16string sImagePath,bool bHover,std::u16string sName=u"") const;
/// 绘制显示名
/// \brief DrawDisplayName
/// \param painter
/// \param option
/// \param sName
///
void DrawDisplayName(QPainter *painter,const QStyleOptionViewItem &option,std::u16string sName) const;
/// 绘制联系人摘要信息 第一号码或Email
/// \brief DrawUserSummary
/// \param painter
/// \param option
/// \param sDesc
/// \param uType :描述信息类别,0电话号码,1电子邮件,2地址信息
///
void DrawUserSummary(QPainter *painter,const QStyleOptionViewItem &option,std::u16string sDesc ,uint uType) const;
/// 绘制来源信息
/// \brief DrawSourcesInfo
/// \param painter
/// \param option
/// \param sName
/// \param sImage
///
void DrawSourcesInfo(QPainter *painter,const QStyleOptionViewItem &option,std::u16string sName,std::u16string sImage) const;
/// 绘制选项图标
/// \brief DrawOptionsBtns
/// \param painter
/// \param option
/// \param uHover :鼠标移动的控件索引,0无,1音频通话,2视频通话,3更多
/// \param bCall :是否绘制呼叫快速按钮
/// \param bEmail :是否绘制发送邮件快速按钮
/// \param bChat :是否绘制发起会话快速按钮
/// \param bInvite :是否绘制发送邀请快速按钮
///
void DrawOptionsBtns(QPainter *painter,const QStyleOptionViewItem &option,uint uHover,bool bCall,bool bEmail,bool bChat,bool bInvite) const;
/// 绘制分割线
/// \brief DrawSplitupLine
/// \param painter
/// \param option
///
void DrawSplitupLine(QPainter *painter,const QStyleOptionViewItem &option) const;
//属性代码省略
};
部分主要绘制代码如下
/// 重写系统绘制
void Lncf_QContactItemd::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
if(index.isValid())
{
painter->save();
painter->setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
painter->setPen(Qt::NoPen);
//判断是分组还是用户
if(index.data(LQCONTACTLIST_ROLES::CONTACTLIST_HEADE).toBool())
{
//绘制分组项目
bool bHasExpand = index.data(LQCONTACTLIST_ROLES::CONTACTLIST_EXPAN).toBool();
QVariant varGroup = index.data(LQCONTACTLIST_ROLES::CONTACTLIST_GROUP);
LQNAVLISTVIEW_GROUP ItemGroupData = varGroup.value<LQNAVLISTVIEW_GROUP>();
//绘制背景
DrawBackgrounds(painter,option,index,true,bHasExpand);
//绘制分组
DrawItemsGroups(painter,option,bHasExpand,ItemGroupData);
}
else{
//绘制通讯录联系人项目
QVariant varContact = index.data(LQCONTACTLIST_ROLES::CONTACTLIST_ITEMS);
LNCFQCONTACT_LISTVIEWS ItemContactData = varContact.value<LNCFQCONTACT_LISTVIEWS>();
DrawBackgrounds(painter,option,index,false,false);
DrawItemContact(painter,option,index,ItemContactData);
}
painter->restore();
}
}
/// 绘制通讯录联系人项
/// \brief DrawItemContact
/// \param painter :绘图引擎指针
/// \param option :视图风格选项引用参数
/// \param itemsData :通讯录联系人视图数据结构参数
///
void Lncf_QContactItemd::DrawItemContact(QPainter *painter,const QStyleOptionViewItem &option, const QModelIndex &index,LNCFQCONTACT_LISTVIEWS itemsData) const
{
painter->save();
//绘制头像
DrawItemsAvatar(painter,option,itemsData.sAvatarImgPath,index.data(LQCONTACTLIST_ROLES::CONTACTLOGO_HOVER).toBool(),itemsData.sItemsShowName);
//绘制联系人名称
DrawDisplayName(painter,option,itemsData.sItemsShowName);
// 绘制摘要信息,号码或Email或地址
if(option.rect.height()>41){
uint descType = 0;
std::u16string uContactDesc;
if(!itemsData.sItemOneNumber.empty())
uContactDesc = itemsData.sItemOneNumber;
else{
if(!itemsData.sItemMailValue.empty()){
uContactDesc = itemsData.sItemMailValue;
descType = 1;
}
else{
if(!itemsData.sItemAddresses.empty()){
uContactDesc = itemsData.sItemAddresses;
descType = 2;
}
}
}
if(!tDelegateStyle.bIconViewModel&&!uContactDesc.empty())
this->DrawUserSummary(painter,option,uContactDesc,descType);
else{
if(!tDelegateStyle.bIconViewModel&&!itemsData.sItemStubValue.empty())
this->DrawSourcesInfo(painter,option,itemsData.sItemStubValue,itemsData.sItemStubImage);
}
}
// 绘制选项图标
if(!this->tDelegateStyle.bIconViewModel&&this->tDelegateStyle.bShowOptionBtn){
/// \param bCall :是否绘制呼叫快速按钮
/// \param bEmail :是否绘制发送邮件快速按钮
/// \param bChat :是否绘制发起会话快速按钮
/// \param bInvite :是否绘制发送邀请快速按钮
///
//鼠标移动的控件索引,0无,1呼叫,2邮件,3会话,4邀请,5更多
uint uOptionHover = 0;
if(index.data(LQCONTACTLIST_ROLES::CONTACTCALL_HOVER).toBool())
uOptionHover =1;
else if(index.data(LQCONTACTLIST_ROLES::CONTACTMAIL_HOVER).toBool())
uOptionHover =2;
else if(index.data(LQCONTACTLIST_ROLES::CONTACTCHAT_HOVER).toBool())
uOptionHover =3;
else if(index.data(LQCONTACTLIST_ROLES::CONTACTINVITE_HOVER).toBool())
uOptionHover =4;
else{
if(index.data(LQCONTACTLIST_ROLES::CONTACTMORE_HOVER).toBool())
uOptionHover =5;
}
DrawOptionsBtns(painter,option,uOptionHover,!itemsData.sItemOneNumber.empty()||!itemsData.sItemsTelphone.empty(),
!itemsData.sItemMailValue.empty(),
itemsData.gUserStubIdVal != uNullUuidVal?true:false,
itemsData.gUserStubIdVal == uNullUuidVal);
}
// 绘制分割线
if(!this->tDelegateStyle.bIconViewModel&&tDelegateStyle.bShowSplitLine)
DrawSplitupLine(painter,option);
painter->restore();
}
/// 绘制显示名
/// \brief DrawDisplayName
/// \param painter
/// \param option
/// \param sName
///
void Lncf_QContactItemd::DrawDisplayName(QPainter *painter,const QStyleOptionViewItem &option,std::u16string sName) const
{
painter->save();
QRect rcName,rcText;
if(!tDelegateStyle.bIconViewModel){
int leftMargin=option.rect.left()+option.rect.height();
rcName = QRect(leftMargin, option.rect.top()+(option.rect.height()>41?5:0), option.rect.width()-leftMargin, option.rect.height()>41?20:option.rect.height());
rcText= rcName;
}
else{
rcName = QRect(option.rect.left()+1, option.rect.top()+option.rect.width(), option.rect.width()-2, 20);
rcText = QRect(rcName.left()+4,rcName.top(),rcName.width()-8,rcName.height());
}
painter->setPen(this->tDelegateStyle.cItemsTxtColor);
// 鼠标悬停或者选中时改变背景色
painter->setPen(QPen(tDelegateStyle.cItemNamesClrs));
if (option.state.testFlag(QStyle::State_MouseOver)) {
painter->setPen(Qt::NoPen);
painter->setBrush(tDelegateStyle.cItemsHoverClr);
if(tDelegateStyle.bIconViewModel)
painter->drawRoundedRect(rcName, rcName.height()/2, rcName.height()/2);
painter->setPen(QPen(tDelegateStyle.cNameHoverClrs));
}
if (option.state.testFlag(QStyle::State_Selected)) {
painter->setPen(Qt::NoPen);
painter->setBrush(tDelegateStyle.cItemSelectClr);
if(tDelegateStyle.bIconViewModel)
painter->drawRoundedRect(rcName, rcName.height()/2, rcName.height()/2);
painter->setPen(QPen(tDelegateStyle.cNameSelectClr));
}
QFont fontObj=painter->font();
fontObj.setPixelSize(12);
QFontMetrics fontMetrics(fontObj);
painter->setFont(fontObj);
QString szName = QString::fromStdU16String(sName);
QString sShowName=fontMetrics.elidedText(szName,Qt::ElideRight,rcText.width());
painter->drawText(rcText,tDelegateStyle.bIconViewModel?Qt::AlignCenter:Qt::AlignVCenter,sShowName);
painter->restore();
}
/// 绘制联系人摘要信息 第一号码或Email
/// \brief DrawUserSummary
/// \param painter
/// \param option
/// \param sDesc
/// \param uType :描述信息类别,0电话号码,1电子邮件,2地址信息
///
void Lncf_QContactItemd::DrawUserSummary(QPainter *painter,const QStyleOptionViewItem &option,std::u16string sDesc,uint uType) const
{
//uLogoStylesIds 摘要logo类型,0图标,1文字,其它不显示
painter->save();
uint uIspIndex = 65535;
if(uType==0&&(tDelegateStyle.uLogoStylesIds==0||tDelegateStyle.uLogoStylesIds==1)){
uIspIndex= Lncf_NavCharHelper::GetPhoneNumIspIndex(QString::fromStdU16String(sDesc));
}
int leftMargin=option.rect.left()+option.rect.height()+((tDelegateStyle.uLogoStylesIds==0?20:0||tDelegateStyle.uLogoStylesIds==1?44:0));
QRectF descRect = QRect(leftMargin, option.rect.bottom()-24, option.rect.width()-leftMargin, 18);
QRectF descLogoFrm = QRectF(option.rect.left()+option.rect.height(),option.rect.bottom()-20,tDelegateStyle.uLogoStylesIds==0?14:42,14);
QRectF descLogo = QRectF(descLogoFrm.left()+1,descLogoFrm.top()+1,descLogoFrm.width()-2,descLogoFrm.height()-2);
QString sMsgText;
if(sDesc.empty())
sMsgText = tr("Contact summary data is empty");
else
sMsgText=QString::fromStdU16String(sDesc);
QFont fontObj=painter->font();
fontObj.setPointSize(7);
painter->setFont(fontObj);
///在前面绘制运营商或Email图标
/// 0电话号码,1电子邮件,2地址信息
if(tDelegateStyle.uLogoStylesIds==0)
{
painter->setPen(Qt::NoPen);
painter->setBrush(tDelegateStyle.cIspLogoBkgClr);
painter->drawRoundedRect(descLogoFrm,descLogoFrm.height()/2,descLogoFrm.height()/2);
painter->setPen(QPen(tDelegateStyle.cItemsTxtColor));
painter->setFont(fontObj);
switch (uType) {
case 0:{
if(uIspIndex>=0&&uIspIndex<sIspNamesLists.count())
painter->drawImage(descLogo,QImage(QString::fromStdU16String(sIspLogosLists[uIspIndex+1])));
else painter->drawImage(descLogo,QImage(QString::fromStdU16String(sIspLogosLists[0])));
}break;
case 1:{
painter->drawImage(descLogo,QImage(QString::fromStdU16String(sSentMailImage)));
}break;
case 2:{
painter->drawImage(descLogo,QImage(QString::fromStdU16String(sLocationImage)));
}break;
}
}
if(tDelegateStyle.uLogoStylesIds==1)
{
painter->setPen(Qt::NoPen);
painter->setBrush(tDelegateStyle.cIspLogoBkgClr);
painter->drawRoundedRect(descLogoFrm,descLogoFrm.height()/2,descLogoFrm.height()/2);
painter->setPen(QPen(tDelegateStyle.cItemsTxtColor));
switch (uType) {
case 0:{
if(uIspIndex>=0&&uIspIndex<sIspNamesLists.count())
painter->drawText(descLogo,Qt::AlignCenter,QString::fromStdU16String(sIspNamesLists[uIspIndex+1]));
else painter->drawText(descLogo,Qt::AlignCenter,QString::fromStdU16String(sIspNamesLists[0]));
}break;
case 1:{
painter->drawText(descLogo,Qt::AlignCenter,tr("MAIL"));
}break;
case 2:{
painter->drawText(descLogo,Qt::AlignCenter,tr("ADDR"));
}break;
}
}
painter->setPen(QPen(tDelegateStyle.cItemsTxtColor));
if (option.state.testFlag(QStyle::State_MouseOver)) {
painter->setPen(QPen(tDelegateStyle.cDescHoverClrs));
}
if (option.state.testFlag(QStyle::State_Selected)) {
painter->setPen(QPen(tDelegateStyle.cDescSelectClr));
}
fontObj.setPointSize(8);
QFontMetrics fontMetrics(fontObj);
painter->setFont(fontObj);
sMsgText=fontMetrics.elidedText(sMsgText,Qt::ElideRight,descRect.width());
painter->drawText(descRect,Qt::AlignLeft|Qt::AlignBottom, sMsgText);
painter->restore();
}
/// 绘制来源信息
/// \brief DrawSourcesInfo
/// \param painter
/// \param option
/// \param sName
/// \param sImage
///
void Lncf_QContactItemd::DrawSourcesInfo(QPainter *painter,const QStyleOptionViewItem &option,std::u16string sName,std::u16string sImage) const
{
painter->save();
int leftMargin=option.rect.left()+option.rect.height();
QRectF logoRect = QRect(leftMargin, option.rect.bottom()-24, 16, 16);
QRectF msgsRect = QRect(leftMargin+18, option.rect.bottom()-24, option.rect.width()-leftMargin, 18);
QImage imgIcon = sImage.empty()?QImage(QString::fromStdU16String(sSourceAppsImg)):QImage(QString::fromStdU16String(sImage));
if(imgIcon.isNull())
imgIcon = QImage(QString::fromStdU16String(sSourceAppsImg));
painter->drawImage(logoRect, imgIcon);
painter->setPen(QPen(tDelegateStyle.cItemsTxtColor));
if (option.state.testFlag(QStyle::State_MouseOver)) {
painter->setPen(QPen(tDelegateStyle.cDescHoverClrs));
}
if (option.state.testFlag(QStyle::State_Selected)) {
painter->setPen(QPen(tDelegateStyle.cDescSelectClr));
}
QString sMsgText = tr("Stub Apps:");
if(sName.empty())
sMsgText = tr("Unknown Stub App source");
else
sMsgText+=QString::fromStdU16String(sName);
QFont fontObj=painter->font();
fontObj.setPixelSize(msgsRect.height()/1.7);
QFontMetrics fontMetrics(fontObj);
painter->setFont(fontObj);
sMsgText=fontMetrics.elidedText(sMsgText,Qt::ElideRight,msgsRect.width());
painter->drawText(msgsRect,Qt::AlignLeft|Qt::AlignVCenter, sMsgText);
painter->restore();
}
有关ListView定义主要代码如下
class LNCF_QTSOCIALLIBS_API Lncf_QContactListv :public Lncf_IndexNavListv
{
Q_OBJECT
Q_PROPERTY(QString sOtherAppIcons READ GetOtherAppIcons WRITE SetOtherAppIcons) //其它应用图标
Q_PROPERTY(QString sSourceAppsImg READ GetSourceAppsImg WRITE SetSourceAppsImg) //默认来源应用图标
Q_PROPERTY(QString sGroupExpanImg READ GetGroupExpanImg WRITE SetGroupExpanImg) //分组展开图标
Q_PROPERTY(QString sGroupCloseImg READ GetGroupCloseImg WRITE SetGroupCloseImg) //分组关闭图标
Q_PROPERTY(QString sCallNumberImg READ GetCallNumberImg WRITE SetCallNumberImg) //呼叫号码图标
Q_PROPERTY(QString sSentChatImage READ GetSentChatImage WRITE SetSentChatImage) //发起会话图标
Q_PROPERTY(QString sSentMailImage READ GetSentMailImage WRITE SetSentMailImage) //发送邮件图标
Q_PROPERTY(QString sInviteRegImgs READ GetInviteRegImgs WRITE SetInviteRegImgs) //邀请注册图标
Q_PROPERTY(QString sMoreOptionImg READ GetMoreOptionImg WRITE SetMoreOptionImg) //更多选项图标
Q_PROPERTY(bool bHasMouseEvent READ GetHasMouseEvent WRITE SetHasMouseEvent) //是否启用鼠标事件
Q_PROPERTY(bool bHasHoverEvent READ GetHasHoverEvent WRITE SetHasHoverEvent) //是否处理鼠标悬停事件
Q_PROPERTY(bool bShowItemsTips READ GetShowItemsTips WRITE SetShowItemsTips) //是否显示鼠标悬停时提示信息
Q_PROPERTY(bool bHasShowGroups READ GetHasShowGroups WRITE SetHasShowGroups) //是否显示分组
public:
explicit Lncf_QContactListv(QWidget *parent = nullptr);
~Lncf_QContactListv();
public:
/// 初始化列表虚函数
/// \brief InitContactList
/// \param bGrid :是否为窗格导航风格
///
virtual void InitContactList(bool bGrid=false);
/// 重初始化封面布局,必须先调用此函数
/// \brief InitCoverLayout
/// \param btnList
/// \param bHorizeOption
/// \param sImgPath
/// \param sTitle
/// \param sLoadTip
/// \param sDesc
///
void InitCoversLayout(QList<LQCOVEROPTION_BNINF> btnList=QList<LQCOVEROPTION_BNINF>(),bool bHorizeOption = true,
std::u16string sImgPath= u"", std::u16string sTitle=u"",std::u16string sLoadTip=u"",std::u16string sDesc=u"") override;
private:
/// 初始化分组
/// \brief InitContactGroup
///
void InitContactGroup();
private:
QStandardItemModel *pListItemModel = nullptr; //列表模型对象指针
Lncf_QContactItemd *pItemsDelegate = nullptr; //列表项委托对象指针
Lncf_QContactSortm *pSortFilteMode = nullptr; //列表筛选器模型对象指针
/// 是否启用鼠标跟踪
/// \brief bMouseTracking
///
bool bMouseTracking = false;
/// 是否显示分组
/// \brief bHasShowGroups
///
bool bHasShowGroups = true;
/// 分组是否已经初始化
/// \brief bInitGroupItem
///
bool bInitGroupItem = false;
/// 索引分组文本
/// \brief sNaviTextsList
///
QList<std::u16string> sNaviTextsList;
public:
/// 添加通讯录联系人项目
/// \brief AddContactDatas
/// \param data :默认视图数据
///
void AddContactDatas(LNCFQCONTACT_LISTVIEWS data);
/// 添加通讯录联系人集合
/// 注意:此函数不会清空列表,追加数据,如果存在相同属性的数据则不会被添加
/// \brief AddContactsList
/// \param data
///
void AddContactsList(std::vector<LNCFQCONTACT_LISTVIEWS> data);
/// 设置通讯录联系人列表数据集合
/// 注意:此函数会清空列表,并重置数据
/// \brief SetContactsList
/// \param vList
///
void SetContactsList(std::vector<LNCFQCONTACT_LISTVIEWS> &vList);
/// 删除通讯录联系人
/// \brief RemovesContacts
/// \param tUserInf
/// \param uErrMsg
/// \return
///
bool RemovesContacts(LNCFQCONTACT_LISTVIEWS tUserInf,QString &uErrMsg);
/// 检查目标联系人属性是否存在,检查三个itemid属性
/// \brief HasContactExist
/// \param data,主要用结构体三个参数:存根ID
/// \return
///
bool HasContactExist(LNCFQCONTACT_LISTVIEWS data);
/// 更新用户数据
/// \brief UpdateUserDatas
/// \param data :默认视图数据
///
bool UpdatedContacts(LNCFQCONTACT_LISTVIEWS data,QString &uErrMsg);
/// 根据模型索引更新模型联系人数据
/// \brief UpdatedContacts
/// \param index :索引ID
/// \param data :视图数据
///
bool UpdatedContacts(const QModelIndex &index,LNCFQCONTACT_LISTVIEWS data,QString &uErrMsg);
/// 激活指定的联系人项
/// \brief ActivedContacts
/// \param tagContact
///
bool ActivedContacts(const LNCFQCONTACT_LISTVIEWS tagContact,QString &uErrMsg);
/// 更新列表数据
/// \brief UpdatedListDatas
///
void UpdatedListDatas();
//属性代码省略
};
使用者连接信号定义如下
/// 列表分组展开或收起
/// \brief GroupItemsExpand
/// \param bExpand 是否展开,true表示展开否则为收起
/// \param uIndex :首字母索引ID
/// \param index :模型索引ID
///
void GroupsItemExpand(const bool &bExpand,const uint64_t uIndex, const QModelIndex &index);
/// 列表视图元素单击事件信号
/// \brief ItemElementClick
/// \param nElement 元素索引定义 0:头像区域,1呼叫按钮区域,2发送邮件按钮区域,3发起会话按钮区域,4发送邀请按钮区域,5更多选项按钮区域
/// \param index
///
void ItemElementClick(const int &nElement,const QModelIndex &index);
/// 列表视图元素双击事件信号
/// \brief ItemElementDbClick
/// \param nElement
/// \param index
///
void ItemElementDbClick(const int &nElement,const QModelIndex &index);
/// 列表视图Ui元素鼠标悬停事件
/// \brief ItemElementHover
/// \param nElement 元素索引定义 0:头像区域,1呼叫按钮区域,2发送邮件按钮区域,3发起会话按钮区域,4发送邀请按钮区域,5更多选项按钮区域
/// \param index
/// \param itemRect 当前项目矩形区域
/// \param evtPos 鼠标悬停位置坐标[当前窗口]
/// \param evtGlobalPos 鼠标悬停位置坐标[桌面窗口]
///
void ItemElementHover(const int &nElement,const QModelIndex &index,const QRect &itemRect,const QPoint &evtPos,const QPoint &evtGlobalPos);
/// 处理列表项单击信号
/// \brief HandItemsClicked
/// \param index
///
void ListItemsClicked(const QModelIndex &index);
/// 分组右键单击事件
/// \brief GroupsRightClicked
/// \param tGroupInf
/// \param point
///
void GroupsRightClicked(const LQNAVLISTVIEW_GROUP &tGroupInf,const QPoint &point,const QModelIndex &index);
/// 联系人右键单击事件
/// \brief ItemRightClickEvts
/// \param tUsersInf
/// \param point
///
void ItemRightClickEvts(const LNCFQCONTACT_LISTVIEWS &tItemsInf,const QPoint &point,const QModelIndex &index);
不知不觉两万多字,实现代码就不提供了,夜深了,以后有时间条件允许并且可行的情况下酌情补上实现代码