C++,Qt开发的通讯录列表控件

基于索引导航控件,根据索引对联系人分组,支持多种操作模式,允许自定义设置正则表达式判断号码运营商。

根据以往惯例,先上图

有关运营商正则匹配代码如下

/// 运营商正则列表
/// 注意:暂未使用,可自行实现,默认顺序为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);

不知不觉两万多字,实现代码就不提供了,夜深了,以后有时间条件允许并且可行的情况下酌情补上实现代码

有关更多技术分享与交流请加QQ群:717743458。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值