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()); |
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); |