QTfrontend/chatwidget.cpp
changeset 4897 11598e7aa7e6
parent 4892 b0610081ee95
child 4898 7a94005874c9
equal deleted inserted replaced
4896:972d418057a7 4897:11598e7aa7e6
    15  * You should have received a copy of the GNU General Public License
    15  * You should have received a copy of the GNU General Public License
    16  * along with this program; if not, write to the Free Software
    16  * along with this program; if not, write to the Free Software
    17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
    17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
    18  */
    18  */
    19 
    19 
       
    20 #include <QDesktopServices>
    20 #include <QTextBrowser>
    21 #include <QTextBrowser>
    21 #include <QLineEdit>
    22 #include <QLineEdit>
    22 #include <QAction>
    23 #include <QAction>
    23 #include <QApplication>
    24 #include <QApplication>
    24 #include <QTextDocument>
    25 #include <QTextDocument>
    25 #include <QDir>
    26 #include <QDir>
    26 #include <QSettings>
    27 #include <QSettings>
    27 #include <QFile>
    28 #include <QFile>
    28 #include <QTextStream>
    29 #include <QTextStream>
       
    30 #include <QMenu>
       
    31 #include <QCursor>
    29 #include <QScrollBar>
    32 #include <QScrollBar>
       
    33 #include <QItemSelectionModel>
    30 
    34 
    31 #include "hwconsts.h"
    35 #include "hwconsts.h"
    32 #include "SDLs.h"
    36 #include "SDLs.h"
    33 #include "gameuiconfig.h"
    37 #include "gameuiconfig.h"
    34 #include "chatwidget.h"
    38 #include "chatwidget.h"
    89         return (txt1[i] < txt2[i]);
    93         return (txt1[i] < txt2[i]);
    90     }
    94     }
    91 
    95 
    92     return firstIsShorter;
    96     return firstIsShorter;
    93 }
    97 }
       
    98 
       
    99 const char* HWChatWidget::STYLE = "a {color:white;} a.nick {text-decoration: none;}";
    94 
   100 
    95 HWChatWidget::HWChatWidget(QWidget* parent, QSettings * gameSettings, SDLInteraction * sdli, bool notify) :
   101 HWChatWidget::HWChatWidget(QWidget* parent, QSettings * gameSettings, SDLInteraction * sdli, bool notify) :
    96   QWidget(parent),
   102   QWidget(parent),
    97   mainLayout(this)
   103   mainLayout(this)
    98 {
   104 {
   122     connect(chatEditLine, SIGNAL(returnPressed()), this, SLOT(returnPressed()));
   128     connect(chatEditLine, SIGNAL(returnPressed()), this, SLOT(returnPressed()));
   123 
   129 
   124     mainLayout.addWidget(chatEditLine, 1, 0);
   130     mainLayout.addWidget(chatEditLine, 1, 0);
   125 
   131 
   126     chatText = new QTextBrowser(this);
   132     chatText = new QTextBrowser(this);
       
   133     chatText->document()->setDefaultStyleSheet(STYLE);
   127     chatText->setMinimumHeight(20);
   134     chatText->setMinimumHeight(20);
   128     chatText->setMinimumWidth(10);
   135     chatText->setMinimumWidth(10);
   129     chatText->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
   136     chatText->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
   130     chatText->setOpenExternalLinks(true);
   137     chatText->setOpenLinks(false);
       
   138     connect(chatText, SIGNAL(anchorClicked(const QUrl&)),
       
   139         this, SLOT(linkClicked(const QUrl&)));
   131     mainLayout.addWidget(chatText, 0, 0);
   140     mainLayout.addWidget(chatText, 0, 0);
   132 
   141 
   133     chatNicks = new QListWidget(this);
   142     chatNicks = new QListWidget(this);
   134     chatNicks->setMinimumHeight(10);
   143     chatNicks->setMinimumHeight(10);
   135     chatNicks->setMinimumWidth(10);
   144     chatNicks->setMinimumWidth(10);
   168 
   177 
   169     showReady = false;
   178     showReady = false;
   170     setShowFollow(true);
   179     setShowFollow(true);
   171 }
   180 }
   172 
   181 
       
   182 void HWChatWidget::linkClicked(const QUrl & link)
       
   183 {
       
   184     if (link.scheme() == "http")
       
   185         QDesktopServices::openUrl(link);
       
   186     if (link.scheme() == "hwnick")
       
   187     {
       
   188         // decode nick
       
   189         const QString& nick = QString::fromUtf8(QByteArray::fromBase64(link.encodedQuery()));
       
   190         QList<QListWidgetItem *> items = chatNicks->findItems(nick, Qt::MatchExactly);
       
   191         if (items.size() < 1)
       
   192             return;
       
   193         QMenu * popup = new QMenu();
       
   194         // selecting an item will automatically scroll there, so let's save old position
       
   195         QScrollBar * scrollBar = chatNicks->verticalScrollBar();
       
   196         int oldScrollPos = scrollBar->sliderPosition();
       
   197         // select the nick which we want to see the actions for
       
   198         chatNicks->setCurrentItem(items[0], QItemSelectionModel::Clear);
       
   199         // selecting an item will automatically scroll there, so let's save old position
       
   200         scrollBar->setSliderPosition(oldScrollPos);
       
   201         // load actions
       
   202         popup->addActions(chatNicks->actions());
       
   203         // display menu popup at mouse cursor position
       
   204         popup->popup(QCursor::pos());
       
   205     }
       
   206 }
       
   207 
   173 void HWChatWidget::setShowFollow(bool enabled)
   208 void HWChatWidget::setShowFollow(bool enabled)
   174 {
   209 {
   175     if (enabled) {
   210     if (enabled) {
   176         if (!(chatNicks->actions().contains(acFollow)))
   211         if (!(chatNicks->actions().contains(acFollow)))
   177             chatNicks->insertAction(acFriend, acFollow);
   212             chatNicks->insertAction(acFriend, acFollow);
   267 {
   302 {
   268     emit chatLine(chatEditLine->text());
   303     emit chatLine(chatEditLine->text());
   269     chatEditLine->clear();
   304     chatEditLine->clear();
   270 }
   305 }
   271 
   306 
       
   307 
   272 void HWChatWidget::onChatString(const QString& str)
   308 void HWChatWidget::onChatString(const QString& str)
   273 {
   309 {
       
   310     onChatString("", str);
       
   311 }
       
   312 
       
   313 void HWChatWidget::onChatString(const QString& nick, const QString& str)
       
   314 {
       
   315     bool isFriend = false;
       
   316 
       
   317     if (!nick.isEmpty()) {
       
   318         // don't show chat lines that are from ignored nicks
       
   319         if (ignoreList.contains(nick, Qt::CaseInsensitive))
       
   320             return;
       
   321         // friends will get special treatment, of course
       
   322         isFriend = friendsList.contains(nick, Qt::CaseInsensitive);
       
   323     }
       
   324 
   274     if (chatStrings.size() > 250)
   325     if (chatStrings.size() > 250)
   275         chatStrings.removeFirst();
   326         chatStrings.removeFirst();
   276 
   327 
   277     QString formattedStr = Qt::escape(str.mid(1));
   328     QString formattedStr = Qt::escape(str.mid(1));
   278     QStringList parts = formattedStr.split(QRegExp("\\W+"), QString::SkipEmptyParts);
   329 
   279 
   330     // "link" nick, but before that encode it in base64 to make sure it can't intefere with html/url syntax
   280     if (!formattedStr.startsWith(" ***")) // don't ignore status messages
   331     // the nick is put as querystring as putting it as host would convert it to it's lower case variant
   281     {
   332     if(!nick.isEmpty())
   282         if (formattedStr.startsWith(" *")) // emote
   333         formattedStr.replace("|nick|",QString("<a href=\"hwnick://?%1\" class=\"nick\">%2</a>").arg(QString(nick.toUtf8().toBase64())).arg(nick));
   283             parts[0] = parts[1];
       
   284         if(parts.size() > 0 && ignoreList.contains(parts[0], Qt::CaseInsensitive))
       
   285             return;
       
   286     }
       
   287 
   334 
   288     QString color("");
   335     QString color("");
   289     bool isFriend = friendsList.contains(parts[0], Qt::CaseInsensitive);
   336 
   290 
   337     // check first character for color code and set color properly
   291     if (str.startsWith("\x03"))
   338     switch (str[0].toAscii()) {
   292         color = QString("#c0c0c0");
   339         case 3:
   293     else if (str.startsWith("\x02"))
   340             color = QString("#c0c0c0");
   294         color = QString(isFriend ? "#00ff00" : "#ff00ff");
   341             break;
   295     else if (isFriend)
   342         case 2:
   296         color = QString("#00c000");
   343             color = QString(isFriend ? "#00ff00" : "#ff00ff");
   297 
   344             break;
   298     if(color.compare("") != 0)
   345         default:
       
   346             if (isFriend)
       
   347                 color = QString("#00c000");
       
   348     }
       
   349 
       
   350     if (!color.isEmpty())
   299         formattedStr = QString("<font color=\"%2\">%1</font>").arg(formattedStr).arg(color);
   351         formattedStr = QString("<font color=\"%2\">%1</font>").arg(formattedStr).arg(color);
   300 
   352 
   301     chatStrings.append(formattedStr);
   353     chatStrings.append(formattedStr);
   302 
   354 
   303     chatText->setHtml(chatStrings.join("<br>"));
   355     chatText->setHtml(chatStrings.join("<br>"));
   389         if(friendsList.contains(curritem->text(), Qt::CaseInsensitive))
   441         if(friendsList.contains(curritem->text(), Qt::CaseInsensitive))
   390             emit onFriend();
   442             emit onFriend();
   391 
   443 
   392         // scroll down on first ignore added so that people see where that nick went to
   444         // scroll down on first ignore added so that people see where that nick went to
   393         if (ignoreList.isEmpty())
   445         if (ignoreList.isEmpty())
   394             emit chatNicks->verticalScrollBar()->setValue(chatNicks->verticalScrollBar()->maximum());
   446             chatNicks->scrollToBottom();
   395 
   447 
   396         ignoreList << curritem->text().toLower();
   448         ignoreList << curritem->text().toLower();
   397         onChatString(HWChatWidget::tr("%1 *** %2 has been added to your ignore list").arg('\x03').arg(curritem->text()));
   449         onChatString(HWChatWidget::tr("%1 *** %2 has been added to your ignore list").arg('\x03').arg(curritem->text()));
   398     }
   450     }
   399     updateNickItem(curritem); // update icon/sort order/etc
   451     updateNickItem(curritem); // update icon/sort order/etc
   418         if(ignoreList.contains(curritem->text(), Qt::CaseInsensitive))
   470         if(ignoreList.contains(curritem->text(), Qt::CaseInsensitive))
   419             emit onIgnore();
   471             emit onIgnore();
   420 
   472 
   421         // scroll up on first friend added so that people see where that nick went to
   473         // scroll up on first friend added so that people see where that nick went to
   422         if (friendsList.isEmpty())
   474         if (friendsList.isEmpty())
   423             emit chatNicks->verticalScrollBar()->setValue(chatNicks->verticalScrollBar()->minimum());
   475             chatNicks->scrollToTop();
   424 
   476 
   425         friendsList << curritem->text().toLower();
   477         friendsList << curritem->text().toLower();
   426         onChatString(HWChatWidget::tr("%1 *** %2 has been added to your friends list").arg('\x03').arg(curritem->text()));
   478         onChatString(HWChatWidget::tr("%1 *** %2 has been added to your friends list").arg('\x03').arg(curritem->text()));
   427     }
   479     }
   428     updateNickItem(curritem); // update icon/sort order/etc
   480     updateNickItem(curritem); // update icon/sort order/etc