⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chattextwgt.cpp

📁 用qt4 编写的局域网聊天工具
💻 CPP
字号:
/*************************************************************************** *   Copyright (C) 2007 by Anistratov Oleg                                 * *   ower@users.sourceforge.net                                            * *                                                                         * *   This program is free software; you can redistribute it and/or modify  * *   it under the terms of the GNU General Public License version 2        * *   as published by the Free Software Foundation;                         * *                                                                         * *   This program is distributed in the hope that it will be useful,       * *   but WITHOUT ANY WARRANTY; without even the implied warranty of        * *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         * *   GNU General Public License for more details.                          * *                                                                         * ***************************************************************************/#include "chattextwgt.h"// TODO remove "globals.h" from this header#include "globals.h"#include <QTextCursor>#include <QScrollBar>#include <QFile>#include <QDateTime>#include <QTextFrame>#include "message.h"#include "smileswgt.h"#include "smileswgt.h"#include "abstractchatcore.h"#include "animatedsmile.h"QList<Smile> ChatTextWgt::m_smiles;ChatTextWgt::ChatTextWgt(QWidget *parent) : QWidget(parent),  m_smilesFromSender(0),  m_keepAnimations(-1){  QGridLayout* grid = new QGridLayout(this);  m_text            = new TextBrowser(this);  m_text->setOpenExternalLinks(true);  grid->addWidget(m_text, 0, 0);  grid->setMargin(0);  m_text->verticalScrollBar()->setTracking(true);  initSmiles(QChatSettings::settings()->smilesThemePath());  connect(m_text, SIGNAL(viewportChanged())    , this, SLOT(setAnimations()));  connect(m_text, SIGNAL(viewportVisible(bool)), this, SLOT(playPauseAnimations(bool)));}ChatTextWgt::~ChatTextWgt(){  foreach(AnimatedSmile* sm, m_animatedSmiles)    delete sm;  qDebug("[ChatTextWgt::~ChatTextWgt]\n");}//\*****************************************************************************void ChatTextWgt::addSmile(const QStringList & smiles, const QString & name){  m_smiles.append(Smile(smiles, name));}//\*****************************************************************************void ChatTextWgt::initSmiles(const QString & path){  QFile file(path + "/emoticons.xml");  QDomDocument dom_document;  QDomElement  root;  QDomElement  child;  QDomElement  emoticon;  QDomElement  name;  QDomNodeList elements;  QDomNodeList elements_names;  QStringList  list;  m_smiles.clear();  if(!file.open(QIODevice::ReadOnly))  {    Globals::addError("Couldn't open " + path + "/emoticons.xml");    return;  }  if(!dom_document.setContent(&file, true))  {    Globals::addError("Couldn't parse " + path + "/emoticons.xml");    return;  }  root  = dom_document.documentElement();  elements = root.elementsByTagName("emoticon");  for(uint i = 0, len = elements.length(); i < len; i++)  {    emoticon = elements.item(i).toElement();    elements_names = emoticon.elementsByTagName("string");    list.clear();    for(uint j = 0, len = elements_names.length(); j < len; j++)    {      child = elements_names.item(j).toElement();      list.append(child.text());    }    addSmile(list, emoticon.attribute("file"));  }}//\*****************************************************************************void ChatTextWgt::addMsg(const Message* msg){  QTextDocument*   doc = new QTextDocument;  QTextCharFormat  fmt;  QTextBlockFormat bl_fmt;  QDateTime        date_time;  QTextCursor      cur_old = m_text->textCursor();  QTextCursor      cur_new;  QBrush           brush(Qt::SolidPattern);  int              insert_begin;  if(msg->isHtml())    doc->setHtml(msg->msg());  else    doc->setPlainText(msg->msg());  // preparing msg header(user and time information)  // ************************  date_time.setTime_t(msg->receiveTime());  if(isSystemMsg(msg->type()))    brush.setColor(QChatSettings::settings()->sysColor());  else    brush.setColor(msg->color());  fmt.setForeground(brush);  QString msg_hdr(QChatSettings::settings()->strOption("DisplayMessagesFormat"));  QString tm_fmt = msg_hdr.section(QString("%time%"), 1, 1);  msg_hdr.replace(QRegExp("%time%([^<]*)%time%"), date_time.toString(tm_fmt));  msg_hdr.replace("%user", msg->userName());  msg_hdr.replace("%comp", msg->compName());  if(msg->requested())    msg_hdr.prepend(">");  // ************************  // setting cursor to the end of document and inserting msg header text with needed format  cur_new = m_text->textCursor();  cur_new.clearSelection();  cur_new.setPosition(m_text->toPlainText().size());  cur_new.setCharFormat(fmt);  cur_new.insertText(msg_hdr);  // processing message and inserting smiles  // ************************  int idx_end = 0;  QString str;  QString smile;  QString msg_ = doc->toPlainText();  cur_new = doc->rootFrame()->firstCursorPosition();  smile   = nextSmile  (msg_);  idx_end = msg_.indexOf(smile);  for(; idx_end != -1 && !smile.isEmpty();)  {    str     = msg_.left(idx_end);    msg_    = msg_.right(msg_.size() - idx_end - smile.size());    cur_new = doc->find(smile, cur_new);    if(!cur_new.isNull())    {      while(cur_new.selectedText() != smile)      {        cur_new.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);        if(cur_new.position() == doc->toPlainText().size())          break;      }      if(cur_new.selectedText() == smile)      {        // FIXME workarounding qt4.3 bug        if(cur_new.currentList())          cur_new.insertText(" ");        insertSmile(cur_new, smile);      }      if(cur_new.position() == doc->toPlainText().size())        break;    }    if((smile = nextSmile(msg_)).isEmpty())      break;    idx_end = msg_.indexOf(smile);  }  // ************************  processLinks(doc);  // inserting processed text in the end of the chat view  cur_new = m_text->textCursor();  insert_begin = m_text->toPlainText().size();  cur_new.setPosition(insert_begin);  cur_new.insertHtml(doc->toHtml());//   cur_new.insertText(doc->toPlainText());  // coloring whole msg accordingly to settings  if(!(isSystemMsg(msg->type()) && !QChatSettings::settings()->boolOption("ColorWholeSystemMessage") ||     (msg->type() == AbstractChatCore::MESSAGE  && !QChatSettings::settings()->boolOption("ColorWholeMessage"))))  {    cur_new.setPosition (insert_begin);    cur_new.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);    cur_new.mergeCharFormat(fmt);    cur_new.clearSelection();  }  // restoring selection  m_text->setTextCursor(cur_old);  playPauseAnimations(QChatSettings::settings()->boolOption("UseAnimatedSmiles"));  // if animation is disabled we will show only the first frame except showing nothing  if(!QChatSettings::settings()->boolOption("UseAnimatedSmiles"))    foreach(AnimatedSmile* sm, m_animatedSmiles)    {      sm->setPaused(false);      sm->nextFrame();      sm->setPaused(true);    }  cur_new.insertBlock(QTextBlockFormat());  // TODO add autoscroll settings//   if(scrl_max)  m_text->verticalScrollBar()->setValue(m_text->verticalScrollBar()->maximum());  setAnimations();  delete doc;}//\*****************************************************************************void ChatTextWgt::setMsg(const QString & msg ){  QTextCursor cur_new = m_text->textCursor();  cur_new.clearSelection();  // Obrabotka soobscheniya i vstavka smailov  int idx_end = 0;  QString str;  QString smile;  QString msg_ = msg;  cur_new.beginEditBlock();  smile   = nextSmile  (msg_);  idx_end = msg_.indexOf(smile);  for(int i = 0; i < 10 && idx_end != -1 && !smile.isEmpty(); i++)  {    str     = msg_.left(idx_end);    msg_    = msg_.right(msg_.size() - idx_end - smile.size());    cur_new.insertText(str);    insertSmile(cur_new, smile);    if((smile = nextSmile(msg_)).isEmpty())      break;    idx_end = msg_.indexOf(smile);  }  str = msg_;  cur_new.insertText(str);  cur_new.endEditBlock();}//\*****************************************************************************QString ChatTextWgt::nextSmile(const QString & str, Smile** smile_){  int i, j;  int idx = -1, idx1;  int smile = -1;  int smile_pos = -1;  int smile_size = 0;  for(i = 0; i < m_smiles.size(); i++)    for(j = 0; j < m_smiles[i].smiles.size(); j++)    {      idx1 = str.indexOf(m_smiles[i].smiles[j]);      if(idx1 >= 0 && (idx1 <= idx || idx < 0))      {        if(m_smiles[i].smiles[j].size() >= smile_size)        {          smile_size = m_smiles[i].smiles[j].size();          smile      = i;          smile_pos  = j;          idx        = idx1;        }      }    }  if(smile >= 0 && smile_pos >= 0)  {    if(smile_)      *smile_ = &m_smiles[smile];    return m_smiles[smile].smiles[smile_pos];  }  else    return QString("");}//\*****************************************************************************QString ChatTextWgt::nextSmile(const QString & str) const{  int i, j;  int idx = -1, idx1;  int smile = -1;  int smile_pos = -1;  int smile_size = 0;  for(i = 0; i < m_smiles.size(); i++)    for(j = 0; j < m_smiles[i].smiles.size(); j++)    {      idx1 = str.indexOf(m_smiles[i].smiles[j]);      if(idx1 >= 0 && (idx1 < idx || idx < 0 || (idx1 == idx && m_smiles[i].smiles[j].size() >= smile_size)))      {        smile_size = m_smiles[i].smiles[j].size();        smile      = i;        smile_pos  = j;        idx        = idx1;      }    }  if(m_smilesFromSender)  {    for(i = 0; i < m_smilesFromSender->size(); i++)    {      idx1 = str.indexOf((*m_smilesFromSender)[i].smiles[0]);      if(idx1 >= 0 && (idx1 <= idx || idx < 0))      {        if((*m_smilesFromSender)[i].smiles[0].size() >= smile_size)        {          smile_size = (*m_smilesFromSender)[i].smiles[0].size();          smile      = i;          smile_pos  = -1;          idx        = idx1;        }      }    }  }  if(smile >= 0 && smile_pos >= 0)    return m_smiles[smile].smiles[smile_pos];  else if(smile >= 0 && smile_pos == -1)    return (*m_smilesFromSender)[smile].smiles[0];  return QString("");}//\*****************************************************************************void ChatTextWgt::insertSmile(QTextCursor cursor, const QString & smile){  switch(QChatSettings::settings()->smilesPolicy())  {    case QChatSettings::NoSmiles :      return;    case QChatSettings::DontUseSmilesFromSender :      insertSmileFromLocalTheme(cursor, smile);      break;    case QChatSettings::UseSmilesFromSender :      if(!insertSmileFromLocalTheme(cursor, smile))         insertSmileFromSender(cursor, smile);      break;    case QChatSettings::AlwaysUseSmilesFromSender :      if(!insertSmileFromSender(cursor, smile))         insertSmileFromLocalTheme(cursor, smile);      break;  }}//\*****************************************************************************void ChatTextWgt::setSmilesFromSender(QList<Smile> * smiles){  m_smilesFromSender = smiles;}void ChatTextWgt::processLinks(QTextDocument* doc){  QTextCursor cursor = doc->rootFrame()->firstCursorPosition();  for(;;)  {    cursor = doc->find(QRegExp("\\b(http|ftp|https)://[\\S]+"), cursor);    if(!cursor.isNull())      cursor.insertHtml((QString("<a href=%1>%2</a>").arg(cursor.selectedText()).arg(cursor.selectedText())));    else      break;  }}void ChatTextWgt::setAnimations(){  int min = m_text->cursorForPosition(QPoint(0, 0)).position();  int max = m_text->cursorForPosition(QPoint(m_text->size().width(), m_text->size().height())).position();  foreach(AnimatedSmile* sm, m_animatedSmiles)    sm->pauseIfHidden(min, max);}bool ChatTextWgt::insertSmileFromSender(QTextCursor cursor, const QString & smile){  int i;  if(m_smilesFromSender)  {    for(i = 0; i < m_smilesFromSender->size(); i++)      if((*m_smilesFromSender)[i].smiles[0] == smile)      {        if(QFile((*m_smilesFromSender)[i].name).exists())        {          cursor.insertText(" ");          AnimatedSmile* asmile = new AnimatedSmile;          asmile->init(cursor.position() + m_text->toPlainText().size() - 1, (*m_smilesFromSender)[i].name, m_text->document());          m_animatedSmiles.append(asmile);          return true;        }        m_smilesFromSender->clear();        break;      }  }  return false;}bool ChatTextWgt::insertSmileFromLocalTheme(QTextCursor cursor, const QString & smile){  QString smiles_dir =  QChatSettings::settings()->smilesThemePath();  int i, j;  for(i = 0; i < m_smiles.size(); i++)    for(j = 0; j < m_smiles[i].smiles.size(); j++)      if(m_smiles[i].smiles[j] == smile)      {        if(QFile(smiles_dir + m_smiles[i].name).exists())          cursor.insertImage(smiles_dir + m_smiles[i].name);        else if(QFile(smiles_dir + m_smiles[i].name + ".png").exists())          cursor.insertImage(smiles_dir + m_smiles[i].name + ".png");        else if(QFile(smiles_dir + m_smiles[i].name + ".jpg").exists())          cursor.insertImage(smiles_dir + m_smiles[i].name + ".jpg");        else if(QFile(smiles_dir + m_smiles[i].name + ".gif").exists())        {          cursor.insertText(" ");          AnimatedSmile* asmile = new AnimatedSmile;          asmile->init(cursor.position() + m_text->toPlainText().size() - 1, (smiles_dir + m_smiles[i].name + ".gif"), m_text->document());          m_animatedSmiles.append(asmile);        }        else if(QFile(smiles_dir + m_smiles[i].name + ".mng").exists())        {          cursor.insertText(" ");          AnimatedSmile* asmile = new AnimatedSmile;          asmile->init(cursor.position() + m_text->toPlainText().size() - 1, (smiles_dir + m_smiles[i].name + ".mng"), m_text->document());          m_animatedSmiles.append(asmile);        }        else          cursor.insertText(m_smiles[i].smiles[j]);        return true;      }  return false;}void ChatTextWgt::playPauseAnimations(bool play){  if(play && !QChatSettings::settings()->boolOption("UseAnimatedSmiles"))    return;  if(play && m_keepAnimations < 0)    foreach(AnimatedSmile* sm, m_animatedSmiles)      sm->start();  else if(!play)    foreach(AnimatedSmile* sm, m_animatedSmiles)      sm->stop();  else  {    int i, j;    for(i = m_animatedSmiles.size() - 1, j = 0; i >= 0 && j < m_keepAnimations; i--)    {      if(m_animatedSmiles[i]->animated())      {        m_animatedSmiles[i]->start();        j++;      }    }    for(; i >= 0; i--)      if(m_animatedSmiles[i]->animated())        m_animatedSmiles[i]->setPaused(true);  }  if(play)    setAnimations();}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -