iptton 发表于 2009-6-7 18:50

[Qt] 可显示表情的编辑器

似乎很久没发过新贴了。
在 libfetion-gui 项目里有这样一个任务:信息编辑框表情图片显示。目前的显示方式是直接显示代码,如 :) , :-p 等


实现如下:
fxeditor.h
#ifndef FXEDITOR_H
#define FXEDITOR_H

#include <QTextEdit>
typedef QPair<QString,QString> mypair;
class FxEditor : public QTextEdit
{
    Q_OBJECT
public:
    FxEditor(QWidget*parent = 0);
    QString toPlainText () const;
public slots:
    void onTextChanged();
private:
    // do not use map
    // because it sort the key by char order
    QMap<QString,QString> strToHtml;
    QList<mypair> strToHtmlList;
};

#endif // FXEDITOR_H

fxeditor.cpp
#include "fxeditor.h"
#include <QDebug>

FxEditor::FxEditor(QWidget*parent):QTextEdit(parent)
{
    // setup the list
    // this list should not be a class alone or a global variable?
    mypair a("o:)","<img src=\"./faces/47.gif\" />");
    mypair b(":)","<img src=\"./faces/1.gif\" />");
    strToHtmlList<<a<<b;
    strToHtml["&gt;:)"]="<img src=\"%path%/50.gif\" />";
    strToHtml["o:)"]="<img src=\"%path%/47.gif\" />"; // error :)
    strToHtml["*-:)"]="<img src=\"%path%/37.gif\" />";
    strToHtml[":-d"]="<img src=\"%path%/2.gif\" />";
    strToHtml[":-o"]="<img src=\"%path%/4.gif\" />";
    strToHtml[":-p"]="<img src=\"%path%/5.gif\" />";
    strToHtml["(h)"]="<img src=\"%path%/6.gif\" />";
    strToHtml[":-@"]="<img src=\"%path%/7.gif\" />";
    strToHtml[":("]="<img src=\"%path%/8.gif\" />";
    strToHtml[":'("]="<img src=\"%path%/9.gif\" />";
    strToHtml[":\"&gt;"]="<img src=\"%path%/10.gif\" />"; // work delay
    strToHtml["^o)"]="<img src=\"%path%/11.gif\" />";
    strToHtml[":&amp;"]="<img src=\"%path%/12.gif\" />";// work delay
    strToHtml["8o|"]="<img src=\"%path%/13.gif\" />";
    strToHtml["|-)"]="<img src=\"%path%/14.gif\" />";
    strToHtml[":-#"]="<img src=\"%path%/15.gif\" />";
    strToHtml["8-)"]="<img src=\"%path%/16.gif\" />";
    strToHtml["(s)"]="<img src=\"%path%/17.gif\" />";
    strToHtml["(st)"]="<img src=\"%path%/18.gif\" />";
    strToHtml["(o)"]="<img src=\"%path%/19.gif\" />";
    strToHtml["(l)"]="<img src=\"%path%/20.gif\" />";
    strToHtml["(u)"]="<img src=\"%path%/21.gif\" />";
    strToHtml["(@)"]="<img src=\"%path%/22.gif\" />";
    strToHtml["(&amp;)"]="<img src=\"%path%/23.gif\" />";// work delay
    strToHtml["(sn)"]="<img src=\"%path%/24.gif\" />";
    strToHtml["(*)"]="<img src=\"%path%/25.gif\" />";
    strToHtml["(#)"]="<img src=\"%path%/26.gif\" />";
    strToHtml["(r)"]="<img src=\"%path%/27.gif\" />";
    strToHtml["(})"]="<img src=\"%path%/28.gif\" />";
    strToHtml["({)"]="<img src=\"%path%/29.gif\" />";
    strToHtml["(k)"]="<img src=\"%path%/30.gif\" />";
    strToHtml["(f)"]="<img src=\"%path%/31.gif\" />";
    strToHtml["(w)"]="<img src=\"%path%/32.gif\" />";
    strToHtml["(g)"]="<img src=\"%path%/33.gif\" />";
    strToHtml["(^)"]="<img src=\"%path%/34.gif\" />";
    strToHtml["-8"]="<img src=\"%path%/35.gif\" />";
    strToHtml["(i)"]="<img src=\"%path%/36.gif\" />";
    strToHtml["(c)"]="<img src=\"%path%/38.gif\" />";
    strToHtml["(um)"]="<img src=\"%path%/39.gif\" />";
    strToHtml["(mp)"]="<img src=\"%path%/40.gif\" />";
    strToHtml["(co)"]="<img src=\"%path%/41.gif\" />";
    strToHtml[":-|"]="<img src=\"%path%/42.gif\" />";
    strToHtml[":-/"]="<img src=\"%path%/43.gif\" />";
    strToHtml[":-s"]="<img src=\"%path%/44.gif\" />";
    strToHtml[")-|"]="<img src=\"%path%/45.gif\" />";
    strToHtml["(d)"]="<img src=\"%path%/46.gif\" />";
    strToHtml[":-?"]="<img src=\"%path%/48.gif\" />";
    strToHtml["(y)"]="<img src=\"%path%/49.gif\" />";
    strToHtml[":-b"]="<img src=\"%path%/51.gif\" />";
    strToHtml["b)"]="<img src=\"%path%/52.gif\" />";
    strToHtml[";)"]="<img src=\"%path%/3.gif\" />";
    strToHtml[":)"]="<img src=\"%path%/1.gif\" />";
    //strToHtml[""]="<img src=\"%path%/.gif\" />";

    connect(this,SIGNAL(textChanged()),this,SLOT(onTextChanged()));
}
QString FxEditor::toPlainText()const
{
    QString oristr = toHtml();
    //qDebug()<<oristr;
    // replace all <img ..> to str
    QMap<QString, QString>::const_iterator i = strToHtml.constBegin();
    while (i != strToHtml.end()) {
      QString k = i.value();
      oristr.replace(k.replace("%path%","./faces"),i.key());
      ++i;
    }
    // replace all html tags
    // remove <!Do..
    oristr.remove(QRegExp("<!(^>)+>"));
    // remove stylesheet tag and its content
    oristr.remove(QRegExp("<[^>]+css\">[^<]*</style>"));
    // remove other tags
    oristr.remove(QRegExp("<[^>]+>"));
    oristr.replace("&lt;","<");
    oristr.replace("&gt;",">");

    // remove the newline
    oristr.remove(0,2);
    //qDebug()<<"\n orient plainText return :"<<QTextEdit::toPlainText()<<"\n";
    //return QTextEdit::toPlainText();
    return oristr;
}
void FxEditor::onTextChanged()
{
    static bool changeByMe = false;
    if(changeByMe)
      return;

    QString oristr = toHtml();
    QTextDocument *td = this->document();
    bool changed = false;

    int newCursorPosition = this->textCursor().position();
    QMap<QString,QString>::const_iterator i = strToHtml.constBegin();
    qDebug()<<oristr;
    //qDebug()<<QString("position:%1").arg(newCursorPosition);
    while (i != strToHtml.end()) {
      //计算新位置
      QTextCursor foundCursor(td);
      while(!foundCursor.isNull() && !foundCursor.atEnd()){
            foundCursor = td->find(i.key(),foundCursor);
            if(!foundCursor.isNull()){
                qDebug()<<i.key();
                changed=true;
                int foundCursorPosition= foundCursor.position();
                if(foundCursorPosition >= newCursorPosition){
                  //@ TO FIX
                  //when & turn to &amp; && > turn to &gt;
                  //this doen't work as expect.
                  newCursorPosition -= i.key().size()-1;
                }
                //QString str = td->toHtml();
                //str.replace(foundCursorPosition,i.key().size(), i.value());
            }
      }
      //切换
      QString k = i.value();
      oristr.replace(i.key(),k.replace("%path%","./faces"));
      ++i;
    }
    //qDebug()<<QString("position:%1").arg(newCursorPosition);
    if(changed){
      changeByMe = true;
      setHtml(oristr);
      QTextCursor c(td);
      c.setPosition(newCursorPosition);
      this->setTextCursor(c);
      changeByMe = false;
    }
    qDebug()<<"\n"<<toPlainText()<<"\n";
}

表情符对应的图片是硬编码的,这个做法扩展性不好,更好的做法是从外部读取字符和图片对应表。这样就可以方便的支持自定义表情了
页: [1]
查看完整版本: [Qt] 可显示表情的编辑器