Freeciv21
Develop your civilization from humble roots to a global empire
chatline.cpp
Go to the documentation of this file.
1 
12 #include "chatline.h"
13 // Qt
14 #include <QActionGroup>
15 #include <QApplication>
16 #include <QCheckBox>
17 #include <QCompleter>
18 #include <QGridLayout>
19 #include <QHash>
20 #include <QPainter>
21 #include <QPushButton>
22 #include <QScrollBar>
23 #include <QTextBlock>
24 #include <QToolButton>
25 
26 // common
27 #include "chat.h"
28 #include "chatline_common.h"
29 
30 // client
31 #include "audio/audio.h"
32 #include "client_main.h"
33 #include "climap.h"
34 #include "colors_common.h"
35 #include "connectdlg_common.h"
36 #include "control.h"
37 #include "dialogs.h"
38 #include "fc_client.h"
39 #include "featured_text.h"
40 #include "fonts.h"
41 #include "game.h"
42 #include "icons.h"
43 #include "messagewin.h"
44 #include "page_game.h"
45 #include "views/view_map.h"
46 #include "views/view_map_common.h"
47 
48 static bool is_plain_public_message(const QString &s);
49 
50 QStringList chat_listener::history = QStringList();
51 
52 namespace {
53 
54 QHash<QString, QString> color_mapping;
55 
56 } // namespace
57 
61 void set_chat_colors(const QHash<QString, QString> &colors)
62 {
63  color_mapping = colors;
64 }
65 
69 chat_listener::chat_listener() : position(HISTORY_END) {}
70 
76  const struct text_tag_list *)
77 {
78 }
79 
87 {
88  QString splayer, s;
89 
90  history << message;
92 
93  /*
94  * If client send commands to take ai, set /away to disable AI
95  */
96  if (message.startsWith(QLatin1String("/take "))) {
97  s = s.remove(QStringLiteral("/take "));
98  players_iterate(pplayer)
99  {
100  splayer = QString(pplayer->name);
101  splayer = "\"" + splayer + "\"";
102 
103  if (!splayer.compare(s)) {
104  if (is_ai(pplayer)) {
105  send_chat(message.toLocal8Bit());
106  send_chat("/away");
107  return;
108  }
109  }
110  }
112  }
113 
114  /*
115  * Option to send to allies by default
116  */
117  if (!message.isEmpty()) {
120  send_chat((QString(CHAT_ALLIES_PREFIX) + " " + message).toLocal8Bit());
121  } else {
122  send_chat(message.toLocal8Bit());
123  }
124  }
125  // Empty messages aren't sent
126  // FIXME Inconsistent behavior: "." will send an empty message to allies
127 }
128 
134 {
135  if (!history.empty() && position == HISTORY_END) {
136  position = history.size() - 1;
137  } else if (position > 0) {
138  position--;
139  }
140  return history.empty() ? QLatin1String("") : history.at(position);
141 }
142 
148 {
149  if (position == HISTORY_END) {
150  return QLatin1String("");
151  }
152  position++;
153  if (position >= history.size()) {
155  return QLatin1String("");
156  } else {
157  return history.at(position);
158  }
159 }
160 
165 
169 chat_input::chat_input(QWidget *parent) : QLineEdit(parent)
170 {
171  connect(this, &QLineEdit::returnPressed, this, &chat_input::send);
173 }
174 
179 {
180  send_chat_message(text());
181  clear();
182 }
183 
188 {
189  QStringList word_list;
190 
191  // sourced from server/commands.cpp
192  word_list << QStringLiteral("/start");
193  word_list << QStringLiteral("/help");
194  word_list << QStringLiteral("/list colors");
195  word_list << QStringLiteral("/list connections");
196  word_list << QStringLiteral("/list delegations");
197  word_list << QStringLiteral("/list ignored users");
198  word_list << QStringLiteral("/list map image definitions");
199  word_list << QStringLiteral("/list players");
200  word_list << QStringLiteral("/list rulesets");
201  word_list << QStringLiteral("/list scenarios");
202  word_list << QStringLiteral("/list nationsets");
203  word_list << QStringLiteral("/list teams");
204  word_list << QStringLiteral("/list votes");
205  word_list << QStringLiteral("/quit");
206  word_list << _("/cut <connection-name>");
207  word_list << _("/explain <option-name>");
208  word_list << _("/show <option-name>");
209  word_list << QStringLiteral("/show all");
210  word_list << QStringLiteral("/show vital");
211  word_list << QStringLiteral("/show situational");
212  word_list << QStringLiteral("/show rare");
213  word_list << QStringLiteral("/show changed");
214  word_list << QStringLiteral("/show locked");
215  word_list << QStringLiteral("/show rulesetdir");
216  word_list << _("/wall <message>");
217  word_list << _("/connectmsg <message>");
218  word_list << _("/vote yes|no|abstain [vote number]");
219  word_list << _("/debug diplomacy <player>");
220  word_list << _("/debug ferries");
221  word_list << _("/debug tech <player>");
222  word_list << _("/debug city <x> <y>");
223  word_list << _("/debug units <x> <y>");
224  word_list << _("/debug unit <id>");
225  word_list << QStringLiteral("/debug timing");
226  word_list << QStringLiteral("/debug info");
227  word_list << _("/set <option-name> <value>");
228  word_list << _("/team <player> <team>");
229  word_list << _("/rulesetdir <directory>");
230  word_list << _("/metamessage <meta-line>");
231  word_list << _("/metapatches <meta-line>");
232  word_list << QStringLiteral("/metaconnection up|down|?");
233  word_list << _("/metaserver <address>");
234  word_list << _("/aitoggle <player-name>");
235  word_list << _("/take <player-name>");
236  word_list << _("/observe <player-name>");
237  word_list << _("/detach <connection-name>");
238  word_list << _("/create <player-name> [ai type]");
239  word_list << QStringLiteral("/away");
240  word_list << _("/handicapped <player-name>");
241  word_list << _("/novice <player-name>");
242  word_list << _("/easy <player-name>");
243  word_list << _("/normal <player-name>");
244  word_list << _("/hard <player-name>");
245  word_list << _("/cheating <player-name>");
246  word_list << _("/experimental <player-name>");
247  word_list << QStringLiteral("/cmdlevel none|info|basic|ctrl|admin|hack");
248  word_list << QStringLiteral("/first");
249  word_list << QStringLiteral("/timeoutshow");
250  word_list << _("/timeoutset <time>");
251  word_list << _("/timeoutadd <time>");
252  word_list << _("/timeoutincrease <turn> <turninc> <value> <valuemult>");
253  word_list << _("/cancelvote <vote number>");
254  word_list << _("/ignore [type=]<pattern>");
255  word_list << _("/unignore <range>");
256  word_list << _("/playercolor <player-name> <color>");
257  word_list << _("/playernation <player-name> [nation] [is-male] [leader] "
258  "[style]");
259  word_list << QStringLiteral("/endgame");
260  word_list << QStringLiteral("/surrender");
261  word_list << _("/remove <player-name>");
262  word_list << _("/save <file-name>");
263  word_list << _("/scensave <file-name>");
264  word_list << _("/load <file-name>");
265  word_list << _("/read <file-name>");
266  word_list << _("/write <file-name>");
267  word_list << QStringLiteral("/reset game|ruleset|script|default");
268  word_list << _("/default <option name>");
269  word_list << _("/lua cmd <script line>");
270  word_list << _("/lua unsafe-cmd <script line>");
271  word_list << _("/lua file <script file>");
272  word_list << _("/lua unsafe-file <script file>");
273  word_list << _("/kick <user>");
274  word_list << _("/delegate to <username>");
275  word_list << QStringLiteral("/delegate cancel");
276  word_list << _("/delegate take <player-name>");
277  word_list << QStringLiteral("/delegate restore");
278  word_list << _("/delegate show <player-name>");
279  word_list << _("/aicmd <player> <command>");
280  word_list << _("/fcdb lua <script>");
281  word_list << _("/mapimg define <mapdef>");
282  word_list << _("/mapimg show <id>|all");
283  word_list << _("/mapimg create <id>|all");
284  word_list << _("/mapimg delete <id>|all");
285  word_list << QStringLiteral("/mapimg colortest");
286  word_list << QStringLiteral("/rfcstyle");
287  word_list << QStringLiteral("/serverid");
288 
290  {
291  if (pconn->playing) {
292  word_list << pconn->playing->name;
293  word_list << pconn->playing->username;
294  } else {
295  word_list << pconn->username;
296  }
297  }
299 
300  players_iterate(pplayer) { word_list << pplayer->name; }
302 
303  delete completer();
304 
305  auto cmplt = new QCompleter(word_list, this);
306  cmplt->setCaseSensitivity(Qt::CaseInsensitive);
307  cmplt->setCompletionMode(QCompleter::InlineCompletion);
308  setCompleter(cmplt);
309 }
310 
315 {
316  if (event->type() == QEvent::KeyPress) {
317  QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
318  switch (keyEvent->key()) {
319  case Qt::Key_Up:
320  setText(back_in_history());
321  return true;
322  case Qt::Key_Down:
323  setText(forward_in_history());
324  return true;
325  }
326  }
327  return QLineEdit::event(event);
328 }
329 
333 void chat_input::focusInEvent(QFocusEvent *event)
334 {
336  QLineEdit::focusInEvent(event);
337 }
338 
342 chat_widget::chat_widget(QWidget *parent)
343 {
344  QGridLayout *gl;
345  setParent(parent);
346  setMinimumSize(200, 100);
347  setResizable(Qt::LeftEdge | Qt::RightEdge | Qt::TopEdge | Qt::BottomEdge);
348 
349  gl = new QGridLayout;
350  gl->setVerticalSpacing(0);
351  gl->setContentsMargins(QMargins());
352  setLayout(gl);
353 
354  cb = new QToolButton;
355  cb->setFixedSize(QSize(25, 25));
356  cb->setIconSize(QSize(24, 24));
357  cb->setToolTip(_("Set who can see your messages by default."));
358 
359  const auto current_icon = [] {
361  ? QStringLiteral("private")
362  : QStringLiteral("public"));
363  };
364  cb->setIcon(current_icon());
365 
366  cb_menu = new QMenu;
367  cb->setMenu(cb_menu);
368  cb->setPopupMode(QToolButton::InstantPopup);
369 
370  // Populate the menu
371  auto group = new QActionGroup(cb_menu);
372  auto action = cb_menu->addAction(
373  fcIcons::instance()->getIcon(QStringLiteral("private")),
374  _("Allies Only"));
375  action->setCheckable(true);
377  connect(action, &QAction::triggered, cb, [=] {
379  cb->setIcon(current_icon());
380  });
381  group->addAction(action);
382 
383  action = cb_menu->addAction(
384  fcIcons::instance()->getIcon(QStringLiteral("public")), _("Everyone"));
385  action->setCheckable(true);
387  connect(action, &QAction::triggered, cb, [=] {
389  cb->setIcon(current_icon());
390  });
391  group->addAction(action);
392 
393  chat_line = new chat_input;
394  chat_line->installEventFilter(this);
395 
396  remove_links = new QPushButton();
397  remove_links->setIconSize(QSize(24, 24));
398  remove_links->setFixedWidth(25);
399  remove_links->setFixedHeight(25);
400  remove_links->setIcon(
401  fcIcons::instance()->getIcon(QStringLiteral("erase")));
402  remove_links->setToolTip(_("Clear links"));
403 
404  show_hide = new QPushButton();
405  show_hide->setIcon(
406  fcIcons::instance()->getIcon(QStringLiteral("expand-down")));
407  show_hide->setIconSize(QSize(24, 24));
408  show_hide->setFixedWidth(25);
409  show_hide->setFixedHeight(25);
410  show_hide->setToolTip(_("Show/hide chat"));
411  show_hide->setCheckable(true);
412  show_hide->setChecked(true);
413 
414  mw = new move_widget(this);
415  mw->put_to_corner();
416 
417  chat_output = new text_browser_dblclck(this);
418  chat_output->setFont(fcFont::instance()->getFont(fonts::chatline));
419  chat_output->setReadOnly(true);
420  chat_output->setVisible(true);
421  chat_output->setAcceptRichText(true);
422  chat_output->setOpenLinks(false);
423  chat_output->setReadOnly(true);
424 
425  auto title = new QLabel(_("Chat"));
426  title->setAlignment(Qt::AlignCenter);
427  title->setMouseTracking(true);
428 
429  gl->addWidget(mw, 0, 0, Qt::AlignLeft | Qt::AlignTop);
430  gl->addWidget(title, 0, 1, 1, 2);
431  gl->setColumnStretch(1, 100);
432  gl->addWidget(show_hide, 0, 3);
433  gl->addWidget(chat_output, 1, 0, 1, 4);
434  gl->addWidget(chat_line, 2, 0, 1, 2);
435  gl->addWidget(cb, 2, 2);
436  gl->addWidget(remove_links, 2, 3);
437 
438  connect(chat_output, &QTextBrowser::anchorClicked, this,
440  connect(remove_links, &QAbstractButton::clicked, this,
442  connect(show_hide, &QAbstractButton::toggled, this,
444  setMouseTracking(true);
445 
447 }
448 
453 {
454  // Just to be sure.
455  delete cb_menu;
456 }
457 
462 {
463  // Don't update chat_fheight
464  m_chat_visible = false;
465 
466  // Save the geometry before setting the minimum size
467  auto geo = geometry();
468 
469  if (visible) {
470  setMinimumSize(200, 100);
471  setResizable(Qt::LeftEdge | Qt::RightEdge | Qt::TopEdge
472  | Qt::BottomEdge);
473  } else {
474  setMinimumSize(200, 0);
475  setResizable({});
476  }
477 
478  chat_line->setVisible(visible);
479  chat_output->setVisible(visible);
480  cb->setVisible(visible && !is_server_running());
481  remove_links->setVisible(visible);
482 
483  int h = visible ? qRound(parentWidget()->size().height()
484  * king()->qt_settings.chat_fheight)
485  : sizeHint().height();
486 
487  // Heuristic that more or less works
488  bool expand_up =
489  (y() > parentWidget()->height() - y() - (visible ? h : height()));
490 
491  QString icon_name = (expand_up ^ visible) ? QLatin1String("expand-up")
492  : QLatin1String("expand-down");
493  show_hide->setIcon(fcIcons::instance()->getIcon(icon_name));
494 
495  if (expand_up) {
496  geo.setTop(std::max(geo.bottom() - h, 0));
497  geo.setHeight(h);
498  // Prevent it from going out of screen
499  if (geo.bottom() > parentWidget()->height()) {
500  geo.translate(0, parentWidget()->height() - geo.bottom());
501  }
502  } else {
503  geo.setBottom(std::min(geo.top() + h, parentWidget()->height()));
504  }
505  setGeometry(geo);
506 
507  m_chat_visible = visible;
508 }
509 
514 {
515  show_hide->setChecked(true); // Make sure we're visible
516  chat_line->setFocus(Qt::ShortcutFocusReason);
517 }
518 
523 {
524  chat_output->setFont(fcFont::instance()->getFont(fonts::chatline));
525 }
526 
531 
535 void chat_widget::anchor_clicked(const QUrl &link)
536 {
537  int n;
538  QStringList sl;
539  int id;
540  enum text_link_type type;
541  sl = link.toString().split(QStringLiteral(","));
542  n = sl.at(0).toInt();
543  id = sl.at(1).toInt();
544 
545  type = static_cast<text_link_type>(n);
546  struct tile *ptile = nullptr;
547  switch (type) {
548  case TLT_CITY: {
549  struct city *pcity = game_city_by_number(id);
550 
551  if (pcity) {
552  ptile = client_city_tile(pcity);
553  } else {
554  output_window_append(ftc_client, _("This city isn't known!"));
555  }
556  } break;
557  case TLT_TILE:
558  ptile = index_to_tile(&(wld.map), id);
559 
560  if (!ptile) {
562  _("This tile doesn't exist in this game!"));
563  }
564  break;
565  case TLT_UNIT: {
566  struct unit *punit = game_unit_by_number(id);
567 
568  if (punit) {
569  ptile = unit_tile(punit);
570  } else {
571  output_window_append(ftc_client, _("This unit isn't known!"));
572  }
573  }
574  case TLT_INVALID:
575  break;
576  }
577  if (ptile) {
578  queen()->mapview_wdg->center_on_tile(ptile);
579  link_mark_restore(type, id);
580  }
581 }
582 
587  const struct text_tag_list *tags)
588 {
589  QColor col = chat_output->palette().color(QPalette::Text);
590  append(apply_tags(message, tags, col));
591 }
592 
596 void chat_widget::append(const QString &str)
597 {
598  chat_output->append(str);
599  chat_output->verticalScrollBar()->setSliderPosition(
600  chat_output->verticalScrollBar()->maximum());
601 }
602 
606 void chat_widget::paintEvent(QPaintEvent *event)
607 {
608  QStyleOption opt;
609  opt.init(this);
610  QPainter p(this);
611  style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
612 }
613 
615 {
616  Q_UNUSED(event);
617  emit dbl_clicked();
618 }
619 
623 bool chat_widget::eventFilter(QObject *obj, QEvent *event)
624 {
625  if (obj == chat_line) {
626  if (event->type() == QEvent::KeyPress) {
627  QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
628  if (keyEvent->key() == Qt::Key_Escape) {
629  queen()->mapview_wdg->setFocus();
630  return true;
631  }
632  }
633  if (event->type() == QEvent::ShortcutOverride) {
634  event->setAccepted(true);
635  }
636  }
637  return QObject::eventFilter(obj, event);
638 }
639 
644 {
645  if (is_server_running()) {
646  cb->hide();
647  } else {
648  cb->show();
649  }
650 }
651 
657 {
658  int line_count = 0;
659  int line_height;
660  int size;
661  QTextBlock qtb;
662 
663  qtb = chat_output->document()->firstBlock();
664  /* Count all lines in all text blocks layouts
665  * document()->lineCount returns number of lines without wordwrap */
666 
667  while (qtb.isValid()) {
668  line_count = line_count + qtb.layout()->lineCount();
669  qtb = qtb.next();
670  }
671 
672  if (line_count == 0) {
673  return 0;
674  }
675 
676  line_height = (chat_output->document()->size().height()
677  - 2 * chat_output->document()->documentMargin())
678  / line_count;
679 
680  size = lines * line_height + chat_line->size().height()
681  + chat_output->document()->documentMargin();
682  size = qMax(0, size);
683 
684  return size;
685 }
686 
690 void chat_widget::make_link(struct tile *ptile)
691 {
692  struct unit *punit;
693  QString buf;
694 
695  punit = find_visible_unit(ptile);
696  if (tile_city(ptile)) {
697  buf = city_link(tile_city(ptile));
698  } else if (punit) {
699  buf = unit_link(punit);
700  } else {
701  buf = tile_link(ptile);
702  }
703  chat_line->insert(buf);
704  chat_line->setFocus();
705 }
706 
710 QString apply_tags(QString str, const struct text_tag_list *tags,
711  QColor bg_color)
712 {
713  if (tags == nullptr) {
714  return str;
715  }
716 
717  // Tag offsets are relative to bytes.
718  const auto qba = str.toUtf8();
719 
720  // Tags to insert into the text
721  std::map<int, QString> html_tags;
722 
723  text_tag_list_iterate(tags, ptag)
724  {
725  int start = text_tag_start_offset(ptag);
726  if (start == FT_OFFSET_UNSET) {
727  start = 0;
728  }
729 
730  int stop = text_tag_stop_offset(ptag);
731  if (stop == FT_OFFSET_UNSET) {
732  stop = qba.length();
733  }
734 
735  if (start == stop) {
736  // Get rid of empty tags
737  continue;
738  }
739 
740  // We always append opening tags and prepend closing tags
741  // This corresponds to increasing depth in the tag tree
742  switch (text_tag_type(ptag)) {
743  case TTT_BOLD:
744  html_tags[start] += QStringLiteral("<b>");
745  html_tags[stop] = html_tags[stop].prepend(QStringLiteral("</b>"));
746  break;
747  case TTT_ITALIC:
748  html_tags[start] += QStringLiteral("<i>");
749  html_tags[stop] = html_tags[stop].prepend(QStringLiteral("</i>"));
750  break;
751  case TTT_STRIKE:
752  html_tags[start] += QStringLiteral("<s>");
753  html_tags[stop] = html_tags[stop].prepend(QStringLiteral("</s>"));
754  break;
755  case TTT_UNDERLINE:
756  html_tags[start] += QStringLiteral("<u>");
757  html_tags[stop] = html_tags[stop].prepend(QStringLiteral("</u>"));
758  break;
759  case TTT_COLOR: {
760  QString style;
761  if (!text_tag_color_foreground(ptag).isEmpty()) {
762  auto color = text_tag_color_foreground(ptag);
763  if (color_mapping.find(color) != color_mapping.end()) {
764  color = color_mapping[color];
765  }
766  if (QColor::isValidColor(color)) {
767  style += QStringLiteral("color:%1;").arg(color);
768  }
769  }
770  if (!text_tag_color_background(ptag).isEmpty()) {
771  auto color = text_tag_color_background(ptag);
772  if (color_mapping.find(color) != color_mapping.end()) {
773  color = color_mapping[color];
774  }
775  if (QColor::isValidColor(color)) {
776  style += QStringLiteral("background-color:%1;").arg(color);
777  }
778  }
779  html_tags[start] += QStringLiteral("<span style=\"%1\">").arg(style);
780  html_tags[stop] = html_tags[stop].prepend(QStringLiteral("</span>"));
781  break;
782  }
783  case TTT_LINK: {
784  QColor pcolor;
785 
786  switch (text_tag_link_type(ptag)) {
787  case TLT_CITY:
788  pcolor = get_color(tileset, COLOR_MAPVIEW_CITY_LINK);
789  break;
790  case TLT_TILE:
791  pcolor = get_color(tileset, COLOR_MAPVIEW_TILE_LINK);
792  break;
793  case TLT_UNIT:
794  pcolor = get_color(tileset, COLOR_MAPVIEW_UNIT_LINK);
795  break;
796  case TLT_INVALID:
797  break;
798  }
799 
800  const auto color = pcolor.name(QColor::HexRgb);
801  html_tags[start] += QStringLiteral("<font color=\"%1\">").arg(color);
802  html_tags[start] += QString("<a href=%1,%2>")
803  .arg(QString::number(text_tag_link_type(ptag)),
804  QString::number(text_tag_link_id(ptag)));
805  html_tags[stop] =
806  html_tags[stop].prepend(QStringLiteral("</a></font>"));
807  } break;
808  case TTT_INVALID:
809  break;
810  }
811  }
813 
814  // Insert the HTML markup in the text
815  auto html = QStringLiteral();
816  int last_position = 0;
817  for (auto &[position, tags_to_insert] : html_tags) {
818  html += QString(qba.mid(last_position, position - last_position))
819  .toHtmlEscaped();
820  html += tags_to_insert;
821  last_position = position;
822  }
823  html += QString(qba.mid(last_position)).toHtmlEscaped();
824 
825  return html;
826 }
827 
832 static bool is_plain_public_message(const QString &s)
833 {
834  QString s1, str;
835  int i;
836 
837  str = s.trimmed();
838  if (str.at(0) == SERVER_COMMAND_PREFIX || str.at(0) == CHAT_ALLIES_PREFIX
839  || str.at(0) == CHAT_DIRECT_PREFIX) {
840  return false;
841  }
842 
843  // Search for private message
844  if (!str.contains(CHAT_DIRECT_PREFIX)) {
845  return true;
846  }
847  i = str.indexOf(CHAT_DIRECT_PREFIX);
848  str = str.left(i);
849 
850  // Compare all players and connections looking for match
852  {
853  s1 = pconn->username;
854  if (s1.length() < i) {
855  continue;
856  }
857  if (!QString::compare(s1.left(i), str, Qt::CaseInsensitive)) {
858  return false;
859  }
860  }
862  players_iterate(pplayer)
863  {
864  s1 = pplayer->name;
865  if (s1.length() < i) {
866  continue;
867  }
868  if (!QString::compare(s1.left(i), str, Qt::CaseInsensitive)) {
869  return false;
870  }
871  }
873 
874  return true;
875 }
876 
881 void real_output_window_append(const QString &astring,
882  const text_tag_list *tags)
883 {
884  king()->set_status_bar(astring);
885 
886  if (astring.contains(client.conn.username)) {
887  qApp->alert(king()->central_wdg);
888  }
889 
891  tags);
892 }
893 
897 void version_message(const QString &vertext)
898 {
899  king()->set_status_bar(vertext);
900 }
#define CHAT_DIRECT_PREFIX
Definition: chat.h:25
#define CHAT_ALLIES_PREFIX
Definition: chat.h:24
#define SERVER_COMMAND_PREFIX
Definition: chat.h:23
void real_output_window_append(const QString &astring, const text_tag_list *tags)
Appends the string to the chat output window.
Definition: chatline.cpp:881
void version_message(const QString &vertext)
Got version message from metaserver.
Definition: chatline.cpp:897
void set_chat_colors(const QHash< QString, QString > &colors)
Sets color substitution map.
Definition: chatline.cpp:61
static bool is_plain_public_message(const QString &s)
Copyright (c) 1996-2023 Freeciv21 and Freeciv contributors.
Definition: chatline.cpp:832
QString apply_tags(QString str, const struct text_tag_list *tags, QColor bg_color)
Applies tags to text.
Definition: chatline.cpp:710
int send_chat(const char *message)
Send the message as a chat to the server.
void output_window_append(const struct ft_color color, const char *featured_text)
Add a line of text to the output ("chatline") window, like puts() would do it in the console.
struct tag_types html_tags
Definition: civmanual.cpp:82
void send()
Sends the content of the input box.
Definition: chatline.cpp:178
void update_completion()
Called whenever the completion word list changes.
Definition: chatline.cpp:187
void focusInEvent(QFocusEvent *event) override
Event handler for chat_input, used for history.
Definition: chatline.cpp:333
chat_input(QWidget *parent=nullptr)
Constructor.
Definition: chatline.cpp:169
bool event(QEvent *event) override
Event handler for chat_input, used for history.
Definition: chatline.cpp:314
static const int HISTORY_END
Definition: chatline.h:45
QString forward_in_history()
Goes forward one position in history, and returns the message at the new position.
Definition: chatline.cpp:147
void send_chat_message(const QString &message)
Sends commands to server, but first searches for custom keys, if it finds then it makes custom action...
Definition: chatline.cpp:86
void reset_history_position()
Go to the end of the history.
Definition: chatline.cpp:164
QString back_in_history()
Goes back one position in history, and returns the message at the new position.
Definition: chatline.cpp:133
static QStringList history
Definition: chatline.h:39
chat_listener()
Constructor.
Definition: chatline.cpp:69
virtual void chat_message_received(const QString &, const struct text_tag_list *)
Called whenever a message is received.
Definition: chatline.cpp:75
int position
Definition: chatline.h:41
QTextBrowser * chat_output
Definition: chatline.h:133
void chat_message_received(const QString &message, const struct text_tag_list *tags) override
Adds news string to chat_widget (from chat_listener interface)
Definition: chatline.cpp:586
virtual ~chat_widget()
Destructor.
Definition: chatline.cpp:452
void anchor_clicked(const QUrl &link)
User clicked some custom link.
Definition: chatline.cpp:535
QPushButton * remove_links
Definition: chatline.h:134
chat_widget(QWidget *parent)
Constructor for chat_widget.
Definition: chatline.cpp:342
chat_input * chat_line
Definition: chatline.h:108
void update_widgets()
Hides allies and links button for local game.
Definition: chatline.cpp:643
void take_focus()
Shows the chat and ensures the chat line has focus.
Definition: chatline.cpp:513
move_widget * mw
Definition: chatline.h:138
QToolButton * cb
Definition: chatline.h:136
int default_size(int lines)
Returns how much space chatline of given number of lines would require, or zero if it can't be determ...
Definition: chatline.cpp:656
void update_font()
Updates font for chat_widget.
Definition: chatline.cpp:522
bool m_chat_visible
Definition: chatline.h:132
QMenu * cb_menu
Definition: chatline.h:137
void rm_links()
User clicked clear links button.
Definition: chatline.cpp:530
void append(const QString &str)
Adds news string to chat_widget.
Definition: chatline.cpp:596
QPushButton * show_hide
Definition: chatline.h:135
void set_chat_visible(bool visible)
Manages toggling minimization.
Definition: chatline.cpp:461
void make_link(struct tile *ptile)
Makes link to tile/unit or city.
Definition: chatline.cpp:690
void paintEvent(QPaintEvent *event) override
Paint event for chat_widget.
Definition: chatline.cpp:606
bool eventFilter(QObject *obj, QEvent *event) override
Processess history for chat.
Definition: chatline.cpp:623
static fcFont * instance()
Returns instance of fc_font.
Definition: fonts.cpp:34
QIcon getIcon(const QString &id)
Returns icon by given name.
Definition: icons.cpp:125
static fcIcons * instance()
Returns instance of fc_icons.
Definition: icons.cpp:36
void set_status_bar(const QString &str, int timeout=20000)
Sets application status bar for given time in miliseconds.
Definition: fc_client.cpp:606
static void invoke(_member_fct_ function, _args_ &&...args)
Definition: listener.h:145
void center_on_tile(tile *tile, bool animate=true)
Centers the view on a tile.
Definition: view_map.cpp:197
void put_to_corner()
Puts move widget to left top corner.
Definition: decorations.cpp:99
map_view * mapview_wdg
Definition: page_game.h:81
void setResizable(Qt::Edges edges)
Set resizable flags.
void mouseDoubleClickEvent(QMouseEvent *event) override
Definition: chatline.cpp:614
enum client_states client_state()
Return current client state.
struct civclient client
@ C_S_RUNNING
Definition: client_main.h:43
struct tile * client_city_tile(const struct city *pcity)
Client variant of city_tile().
Definition: climap.cpp:64
QColor get_color(const struct tileset *t, enum color_std stdcolor)
Return a pointer to the given "standard" color.
bool is_server_running()
The general chain of events:
#define conn_list_iterate(connlist, pconn)
Definition: connection.h:99
#define conn_list_iterate_end
Definition: connection.h:101
unit * find_visible_unit(const ::tile *ptile)
Return a pointer to a visible unit, if there is one.
Definition: control.cpp:749
enum event_type event
Definition: events.cpp:68
class fc_client * king()
Return fc_client instance.
Definition: gui_main.cpp:58
#define _(String)
Definition: fcintl.h:50
enum text_link_type text_tag_link_type(const struct text_tag *ptag)
Return the link target type suggested by this text tag.
const char * tile_link(const struct tile *ptile)
Get a text link to a tile.
QString text_tag_color_background(const struct text_tag *ptag)
Return the background color suggested by this text tag.
QString text_tag_color_foreground(const struct text_tag *ptag)
Return the foreground color suggested by this text tag.
ft_offset_t text_tag_stop_offset(const struct text_tag *ptag)
Return the stop offset (in bytes) of this text tag.
const struct ft_color ftc_client
const char * city_link(const struct city *pcity)
Get a text link to a city.
int text_tag_link_id(const struct text_tag *ptag)
Return the link target id suggested by this text tag (city id, tile index or unit id).
ft_offset_t text_tag_start_offset(const struct text_tag *ptag)
Return the start offset (in bytes) of this text tag.
const char * unit_link(const struct unit *punit)
Get a text link to an unit.
#define text_tag_list_iterate_end
#define text_tag_list_iterate(tags, ptag)
#define FT_OFFSET_UNSET
Definition: featured_text.h:95
text_link_type
@ TLT_INVALID
@ TLT_TILE
@ TLT_UNIT
@ TLT_CITY
text_tag_type
@ TTT_LINK
@ TTT_BOLD
@ TTT_ITALIC
@ TTT_INVALID
@ TTT_STRIKE
@ TTT_COLOR
@ TTT_UNDERLINE
struct unit * game_unit_by_number(int id)
Find unit out of all units in game: now uses fast idex method, instead of looking through all units o...
Definition: game.cpp:112
struct civ_game game
Definition: game.cpp:47
struct world wld
Definition: game.cpp:48
struct city * game_city_by_number(int id)
Often used function to get a city pointer from a city ID.
Definition: game.cpp:103
struct tile * index_to_tile(const struct civ_map *imap, int mindex)
Return the tile for the given index position.
Definition: map.cpp:429
Colors.
const char *const chatline
Definition: fonts.h:22
client_options * gui_options
Definition: options.cpp:74
char * lines
Definition: packhand.cpp:131
pageGame * queen()
Return game instandce.
Definition: page_game.cpp:557
#define players_iterate_end
Definition: player.h:520
#define players_iterate(_pplayer)
Definition: player.h:514
#define is_ai(plr)
Definition: player.h:227
size_t size
Definition: specvec.h:64
Definition: city.h:291
struct conn_list * est_connections
Definition: game.h:88
struct conn_list * all_connections
Definition: game.h:87
struct connection conn
Definition: client_main.h:89
bool gui_qt_allied_chat_only
Definition: options.h:166
char username[MAX_LEN_NAME]
Definition: connection.h:151
Definition: tile.h:42
Definition: unit.h:134
struct civ_map map
Definition: world_object.h:21
struct city * tile_city(const struct tile *ptile)
Return the city on this tile (or nullptr), checking for city center.
Definition: tile.cpp:72
#define unit_tile(_pu)
Definition: unit.h:371
void link_mark_restore(enum text_link_type type, int id)
Add a visible link for 1 turn.
void link_marks_clear_all()
Clear all visible links.