QTfrontend/ui/widget/chatwidget.cpp
changeset 7741 d216f0599291
parent 7740 076f57836ee3
child 7742 e5e529dcc9bb
equal deleted inserted replaced
7740:076f57836ee3 7741:d216f0599291
    46 #include "gameuiconfig.h"
    46 #include "gameuiconfig.h"
    47 #include "playerslistmodel.h"
    47 #include "playerslistmodel.h"
    48 
    48 
    49 #include "chatwidget.h"
    49 #include "chatwidget.h"
    50 
    50 
    51 
       
    52 ListWidgetNickItem::ListWidgetNickItem(const QString& nick, bool isFriend, bool isIgnored) : QListWidgetItem(nick)
       
    53 {
       
    54     setData(Friend, isFriend);
       
    55     setData(Ignore, isIgnored);
       
    56 }
       
    57 
       
    58 void ListWidgetNickItem::setData(StateFlag role, const QVariant &value)
       
    59 {
       
    60     QListWidgetItem::setData(role, value);
       
    61 
       
    62     updateIcon();
       
    63 }
       
    64 
       
    65 bool ListWidgetNickItem::operator< (const QListWidgetItem & other) const
       
    66 {
       
    67     // case in-sensitive comparison of the associated strings
       
    68     // chars that are no letters are sorted at the end of the list
       
    69 
       
    70     ListWidgetNickItem otherNick = const_cast<ListWidgetNickItem &>(dynamic_cast<const ListWidgetNickItem &>(other));
       
    71 
       
    72     // ignored always down
       
    73     if (data(Ignore).toBool() != otherNick.data(Ignore).toBool())
       
    74         return !data(Ignore).toBool();
       
    75 
       
    76     // friends always up
       
    77     if (data(Friend).toBool() != otherNick.data(Friend).toBool())
       
    78         return data(Friend).toBool();
       
    79 
       
    80     QString txt1 = text().toLower();
       
    81     QString txt2 = other.text().toLower();
       
    82 
       
    83     bool firstIsShorter = (txt1.size() < txt2.size());
       
    84     int len = firstIsShorter?txt1.size():txt2.size();
       
    85 
       
    86     for (int i = 0; i < len; i++)
       
    87     {
       
    88         if (txt1[i] == txt2[i])
       
    89             continue;
       
    90         if (txt1[i].isLetter() != txt2[i].isLetter())
       
    91             return txt1[i].isLetter();
       
    92         return (txt1[i] < txt2[i]);
       
    93     }
       
    94 
       
    95     return firstIsShorter;
       
    96 }
       
    97 
       
    98 void ListWidgetNickItem::updateIcon()
       
    99 {
       
   100     quint32 iconNum = 0;
       
   101 
       
   102     QList<bool> flags;
       
   103     flags
       
   104         << data(Ready).toBool()
       
   105         << data(ServerAdmin).toBool()
       
   106         << data(RoomAdmin).toBool()
       
   107         << data(Registered).toBool()
       
   108         << data(Friend).toBool()
       
   109         << data(Ignore).toBool()
       
   110         ;
       
   111 
       
   112     for(int i = flags.size() - 1; i >= 0; --i)
       
   113         if(flags[i])
       
   114             iconNum |= 1 << i;
       
   115 
       
   116     if(m_icons().contains(iconNum))
       
   117     {
       
   118         setIcon(m_icons().value(iconNum));
       
   119     }
       
   120     else
       
   121     {
       
   122         QPixmap result(24, 16);
       
   123         result.fill(Qt::transparent);
       
   124 
       
   125         QPainter painter(&result);
       
   126 
       
   127         if(data(Ready).toBool())
       
   128             painter.drawPixmap(0, 0, 16, 16, QPixmap(":/res/chat/lamp.png"));
       
   129 
       
   130         QString mainIconName(":/res/chat/");
       
   131 
       
   132         if(data(RoomAdmin).toBool())
       
   133             mainIconName += "roomadmin";
       
   134         else if(data(ServerAdmin).toBool())
       
   135             mainIconName += "serveradmin";
       
   136         else
       
   137             mainIconName += "hedgehog";
       
   138 
       
   139         if(!data(Registered).toBool())
       
   140             mainIconName += "_gray";
       
   141 
       
   142         painter.drawPixmap(8, 0, 16, 16, QPixmap(mainIconName + ".png"));
       
   143 
       
   144         if(data(Ignore).toBool())
       
   145             painter.drawPixmap(8, 0, 16, 16, QPixmap(":/res/chat/ignore.png"));
       
   146         else
       
   147         if(data(Friend).toBool())
       
   148             painter.drawPixmap(8, 0, 16, 16, QPixmap(":/res/chat/friend.png"));
       
   149 
       
   150         painter.end();
       
   151 
       
   152         QIcon icon(result);
       
   153 
       
   154         setIcon(icon);
       
   155         m_icons().insert(iconNum, icon);
       
   156     }
       
   157 
       
   158     if(data(Ignore).toBool())
       
   159         setForeground(Qt::gray);
       
   160     else
       
   161     if(data(Friend).toBool())
       
   162         setForeground(Qt::green);
       
   163     else
       
   164         setForeground(QBrush(QColor(0xff, 0xcc, 0x00)));
       
   165 }
       
   166 
       
   167 QHash<quint32, QIcon> & ListWidgetNickItem::m_icons()
       
   168 {
       
   169     static QHash<quint32, QIcon> iconsCache;
       
   170 
       
   171     return iconsCache;
       
   172 }
       
   173 
    51 
   174 QString * HWChatWidget::s_styleSheet = NULL;
    52 QString * HWChatWidget::s_styleSheet = NULL;
   175 QStringList * HWChatWidget::s_displayNone = NULL;
    53 QStringList * HWChatWidget::s_displayNone = NULL;
   176 bool HWChatWidget::s_isTimeStamped = true;
    54 bool HWChatWidget::s_isTimeStamped = true;
   177 QString HWChatWidget::s_tsFormat = ":mm:ss";
    55 QString HWChatWidget::s_tsFormat = ":mm:ss";
   477 void HWChatWidget::setIgnoreListKick(bool enabled)
   355 void HWChatWidget::setIgnoreListKick(bool enabled)
   478 {
   356 {
   479     m_autoKickEnabled = enabled;
   357     m_autoKickEnabled = enabled;
   480 }
   358 }
   481 
   359 
   482 void HWChatWidget::loadList(QStringList & list, const QString & file)
       
   483 {
       
   484     list.clear();
       
   485     QFile txt(cfgdir->absolutePath() + "/" + file);
       
   486     if(!txt.open(QIODevice::ReadOnly))
       
   487         return;
       
   488     QTextStream stream(&txt);
       
   489     stream.setCodec("UTF-8");
       
   490 
       
   491     while(!stream.atEnd())
       
   492     {
       
   493         QString str = stream.readLine();
       
   494         if(str.startsWith(";") || str.length() == 0)
       
   495             continue;
       
   496         list << str.trimmed();
       
   497     }
       
   498     //readd once we require newer Qt than 4.4
       
   499     //list.removeDuplicates();
       
   500     txt.close();
       
   501 }
       
   502 
       
   503 void HWChatWidget::saveList(QStringList & list, const QString & file)
       
   504 {
       
   505     QFile txt(cfgdir->absolutePath() + "/" + file);
       
   506 
       
   507     // list empty? => rather have no file for the list than an empty one
       
   508     if (list.isEmpty())
       
   509     {
       
   510         if (txt.exists())
       
   511         {
       
   512             // try to remove file, if successful we're done here.
       
   513             if (txt.remove())
       
   514                 return;
       
   515         }
       
   516         else
       
   517             // there is no file
       
   518             return;
       
   519     }
       
   520 
       
   521     if(!txt.open(QIODevice::WriteOnly | QIODevice::Truncate))
       
   522         return;
       
   523     QTextStream stream(&txt);
       
   524     stream.setCodec("UTF-8");
       
   525 
       
   526     stream << "; this list is used by Hedgewars - do not edit it unless you know what you're doing!" << endl;
       
   527     for(int i = 0; i < list.size(); i++)
       
   528         stream << list[i] << endl;
       
   529     txt.close();
       
   530 }
       
   531 
       
   532 void HWChatWidget::updateNickItem(QListWidgetItem *nickItem)
       
   533 {
       
   534     QString nick = nickItem->text();
       
   535     ListWidgetNickItem * item = dynamic_cast<ListWidgetNickItem*>(nickItem);
       
   536 
       
   537     item->setData(ListWidgetNickItem::Friend, QVariant(friendsList.contains(nick, Qt::CaseInsensitive)));
       
   538     item->setData(ListWidgetNickItem::Ignore, QVariant(ignoreList.contains(nick, Qt::CaseInsensitive)));
       
   539 }
       
   540 
       
   541 void HWChatWidget::updateNickItems()
       
   542 {
       
   543     /*for(int i = 0; i < chatNicks->count(); i++)
       
   544         updateNickItem(chatNicks->item(i));
       
   545 
       
   546     chatNicks->sortItems();*/
       
   547 }
       
   548 
       
   549 void HWChatWidget::loadLists(const QString & nick)
       
   550 {
       
   551     loadList(ignoreList, nick.toLower() + "_ignore.txt");
       
   552     loadList(friendsList, nick.toLower() + "_friends.txt");
       
   553     updateNickItems();
       
   554 }
       
   555 
       
   556 void HWChatWidget::saveLists(const QString & nick)
       
   557 {
       
   558     saveList(ignoreList, nick.toLower() + "_ignore.txt");
       
   559     saveList(friendsList, nick.toLower() + "_friends.txt");
       
   560 }
       
   561 
       
   562 
   360 
   563 void HWChatWidget::returnPressed()
   361 void HWChatWidget::returnPressed()
   564 {
   362 {
   565     QStringList lines = chatEditLine->text().split('\n');
   363     QStringList lines = chatEditLine->text().split('\n');
   566     chatEditLine->rememberCurrentText();
   364     chatEditLine->rememberCurrentText();
   597 
   395 
   598 const QRegExp HWChatWidget::URLREGEXP = QRegExp("(http://)?(www\\.)?(hedgewars\\.org(/[^ ]*)?)");
   396 const QRegExp HWChatWidget::URLREGEXP = QRegExp("(http://)?(www\\.)?(hedgewars\\.org(/[^ ]*)?)");
   599 
   397 
   600 void HWChatWidget::onChatString(const QString& nick, const QString& str)
   398 void HWChatWidget::onChatString(const QString& nick, const QString& str)
   601 {
   399 {
   602     bool isFriend = false;
   400     QSortFilterProxyModel * playersSortFilterModel = qobject_cast<QSortFilterProxyModel *>(chatNicks->model());
       
   401     if(!playersSortFilterModel)
       
   402         return;
       
   403 
       
   404     PlayersListModel * players = qobject_cast<PlayersListModel *>(playersSortFilterModel->sourceModel());
       
   405 
       
   406     if(!players)
       
   407         return;
   603 
   408 
   604     if (!nick.isEmpty())
   409     if (!nick.isEmpty())
   605     {
   410     {
   606         // don't show chat lines that are from ignored nicks
   411         // don't show chat lines that are from ignored nicks
   607         if (ignoreList.contains(nick, Qt::CaseInsensitive))
   412         if (players->isFlagSet(nick, PlayersListModel::Ignore))
   608             return;
   413             return;
   609         // friends will get special treatment, of course
   414     }
   610         isFriend = friendsList.contains(nick, Qt::CaseInsensitive);
   415 
   611     }
   416     bool isFriend = (!nick.isEmpty()) && players->isFlagSet(nick, PlayersListModel::Friend);
   612 
   417 
   613     QString formattedStr = Qt::escape(str.mid(1));
   418     QString formattedStr = Qt::escape(str.mid(1));
   614     // make hedgewars.org urls actual links
   419     // make hedgewars.org urls actual links
   615     formattedStr = formattedStr.replace(URLREGEXP, "<a href=\"http://\\3\">\\3</a>");
   420     formattedStr = formattedStr.replace(URLREGEXP, "<a href=\"http://\\3\">\\3</a>");
   616 
   421 
   695     chatText->setHtml("<html><body>"+chatStrings.join("<br>")+"</body></html>");
   500     chatText->setHtml("<html><body>"+chatStrings.join("<br>")+"</body></html>");
   696 
   501 
   697     chatText->moveCursor(QTextCursor::End);
   502     chatText->moveCursor(QTextCursor::End);
   698 }
   503 }
   699 
   504 
       
   505 
   700 void HWChatWidget::nickAdded(const QString & nick, bool notifyNick)
   506 void HWChatWidget::nickAdded(const QString & nick, bool notifyNick)
   701 {
   507 {
   702     bool isIgnored = ignoreList.contains(nick, Qt::CaseInsensitive);
   508     QSortFilterProxyModel * playersSortFilterModel = qobject_cast<QSortFilterProxyModel *>(chatNicks->model());
       
   509     if(!playersSortFilterModel)
       
   510         return;
       
   511 
       
   512     PlayersListModel * players = qobject_cast<PlayersListModel *>(playersSortFilterModel->sourceModel());
       
   513 
       
   514     if(!players)
       
   515         return;
       
   516 
       
   517     bool isIgnored = players->isFlagSet(nick, PlayersListModel::Ignore);
   703 
   518 
   704     if (isIgnored && m_isAdmin && m_autoKickEnabled)
   519     if (isIgnored && m_isAdmin && m_autoKickEnabled)
   705     {
   520     {
   706         emit kick(nick);
   521         emit kick(nick);
   707         return;
   522         return;
   708     }
   523     }
   709 
       
   710     QListWidgetItem * item = new ListWidgetNickItem(nick, friendsList.contains(nick, Qt::CaseInsensitive), isIgnored);
       
   711     updateNickItem(item);
       
   712     /*chatNicks->addItem(item);*/
       
   713 
   524 
   714     if ((!isIgnored) && (nick != m_userNick)) // don't auto-complete own name
   525     if ((!isIgnored) && (nick != m_userNick)) // don't auto-complete own name
   715         chatEditLine->addNickname(nick);
   526         chatEditLine->addNickname(nick);
   716 
   527 
   717     emit nickCountUpdate(chatNicks->model()->rowCount());
   528     emit nickCountUpdate(chatNicks->model()->rowCount());
   725 
   536 
   726 void HWChatWidget::nickRemoved(const QString& nick)
   537 void HWChatWidget::nickRemoved(const QString& nick)
   727 {
   538 {
   728     chatEditLine->removeNickname(nick);
   539     chatEditLine->removeNickname(nick);
   729 
   540 
   730     /*foreach(QListWidgetItem * item, chatNicks->findItems(nick, Qt::MatchExactly))
   541     emit nickCountUpdate(chatNicks->model()->rowCount());
   731         chatNicks->takeItem(chatNicks->row(item));*/
       
   732 
       
   733     //emit nickCountUpdate(chatNicks->count());
       
   734 }
   542 }
   735 
   543 
   736 void HWChatWidget::clear()
   544 void HWChatWidget::clear()
   737 {
   545 {
   738     chatEditLine->reset();
   546     chatEditLine->reset();
   856         chatEditLine->removeNickname(nick);
   664         chatEditLine->removeNickname(nick);
   857         displayNotice(tr("%1 has been added to your ignore list").arg(linkedNick(nick)));
   665         displayNotice(tr("%1 has been added to your ignore list").arg(linkedNick(nick)));
   858     }
   666     }
   859 
   667 
   860     if(mil.size())
   668     if(mil.size())
   861     {
       
   862         chatNicks->scrollTo(chatNicks->selectionModel()->selectedRows()[0]);
   669         chatNicks->scrollTo(chatNicks->selectionModel()->selectedRows()[0]);
   863         chatNickSelected(); // update context menu
       
   864     }
       
   865 }
   670 }
   866 
   671 
   867 void HWChatWidget::onFriend()
   672 void HWChatWidget::onFriend()
   868 {
   673 {
   869     QModelIndexList mil = chatNicks->selectionModel()->selectedRows();
   674     QModelIndexList mil = chatNicks->selectionModel()->selectedRows();
   898         chatEditLine->addNickname(nick);
   703         chatEditLine->addNickname(nick);
   899         displayNotice(tr("%1 has been added to your friends list").arg(linkedNick(nick)));
   704         displayNotice(tr("%1 has been added to your friends list").arg(linkedNick(nick)));
   900     }
   705     }
   901 
   706 
   902     if(mil.size())
   707     if(mil.size())
   903     {
       
   904         chatNicks->scrollTo(chatNicks->selectionModel()->selectedRows()[0]);
   708         chatNicks->scrollTo(chatNicks->selectionModel()->selectedRows()[0]);
   905         chatNickSelected(); // update context menu
   709 }
   906     }
   710 /*
   907 }
       
   908 
       
   909 void HWChatWidget::chatNickDoubleClicked(QListWidgetItem * item)
   711 void HWChatWidget::chatNickDoubleClicked(QListWidgetItem * item)
   910 {
   712 {
   911     if (item != NULL)
   713     if (item != NULL)
   912         m_clickedNick = item->text();
   714         m_clickedNick = item->text();
   913     else
   715     else
   914         m_clickedNick = "";
   716         m_clickedNick = "";
   915     QList<QAction *> actions = chatNicks->actions();
   717     QList<QAction *> actions = chatNicks->actions();
   916     actions.first()->activate(QAction::Trigger);
   718     actions.first()->activate(QAction::Trigger);
   917 }
   719 }
   918 
   720 */
   919 void HWChatWidget::chatNickSelected()
       
   920 {
       
   921 }
       
   922 
       
   923 void HWChatWidget::setStatus(const QString & nick, ListWidgetNickItem::StateFlag flag, bool status)
       
   924 {
       
   925     /*QList<QListWidgetItem *> items = chatNicks->findItems(nick, Qt::MatchExactly);
       
   926 
       
   927     if (items.size() == 1)
       
   928     {
       
   929         items[0]->setData(flag, status);
       
   930         updateNickItem(items[0]);
       
   931     }*/
       
   932 }
       
   933 
       
   934 void HWChatWidget::setReadyStatus(const QString & nick, bool isReady)
       
   935 {
       
   936     setStatus(nick, ListWidgetNickItem::Ready, isReady);
       
   937 }
       
   938 
       
   939 void HWChatWidget::setAdminStatus(const QString & nick, bool isAdmin)
       
   940 {
       
   941     setStatus(nick, ListWidgetNickItem::ServerAdmin, isAdmin);
       
   942 }
       
   943 
       
   944 void HWChatWidget::setRoomMasterStatus(const QString & nick, bool isAdmin)
       
   945 {
       
   946     setStatus(nick, ListWidgetNickItem::RoomAdmin, isAdmin);
       
   947 }
       
   948 
       
   949 void HWChatWidget::setRegisteredStatus(const QStringList & nicks, bool isRegistered)
       
   950 {
       
   951     foreach(const QString & nick, nicks)
       
   952         setStatus(nick, ListWidgetNickItem::Registered, isRegistered);
       
   953 }
       
   954 
   721 
   955 void HWChatWidget::adminAccess(bool b)
   722 void HWChatWidget::adminAccess(bool b)
   956 {
   723 {
   957     chatNicks->removeAction(acKick);
   724     chatNicks->removeAction(acKick);
   958     chatNicks->removeAction(acBan);
   725     chatNicks->removeAction(acBan);