ircdock.cpp
1 //------------------------------------------------------------------------------
2 // ircdock.cpp
3 //------------------------------------------------------------------------------
4 //
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License, or (at your option) any later version.
9 //
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 // 02110-1301 USA
19 //
20 //------------------------------------------------------------------------------
21 // Copyright (C) 2010 "Zalewa" <zalewapl@gmail.com>
22 //------------------------------------------------------------------------------
23 #include "gui/irc/ircdocktabcontents.h"
24 #include "gui/irc/ircnetworkselectionbox.h"
25 #include "gui/irc/ircsounds.h"
26 #include "irc/configuration/chatnetworkscfg.h"
27 #include "irc/configuration/ircconfig.h"
28 #include "irc/ircnetworkadapter.h"
29 #include "ircdock.h"
30 #include "ui_ircdock.h"
31 
32 #include <QInputDialog>
33 #include <QMessageBox>
34 #include <QTabBar>
35 #include <QToolBar>
36 
37 DClass<IRCDock> : public Ui::IRCDock
38 {
39 public:
40  IRCSounds pSounds;
41  QAction *toolBarConnect;
42  QAction *toolBarOpenChatWindow;
43 };
44 
45 DPointered(IRCDock)
46 
47 IRCDock::IRCDock(QWidget *parent)
48  : QDockWidget(parent)
49 {
50  d->setupUi(this);
51  toggleViewAction()->setIcon(QIcon(":/icons/chat.png"));
52 
53  d->pSounds.loadFromConfig();
54 
55  setupToolbar();
56 
57  connect(d->tabWidget, SIGNAL(currentChanged(int)),
58  SLOT(tabCurrentChanged(int)));
59 
60  connect(d->tabWidget, SIGNAL(tabCloseRequested(int)),
61  SLOT(tabCloseRequestedSlot(int)));
62 }
63 
64 IRCDock::~IRCDock()
65 {
66 }
67 
68 IRCDockTabContents *IRCDock::addIRCAdapter(IRCAdapterBase *pIRCAdapter)
69 {
70  auto pNewAdapterWidget = new IRCDockTabContents(this);
71 
72  connect(pNewAdapterWidget, SIGNAL(chatWindowCloseRequest(IRCDockTabContents*)), SLOT(chatWindowCloseRequestSlot(IRCDockTabContents*)));
73  connect(pNewAdapterWidget, SIGNAL(focusRequest(IRCDockTabContents*)), SLOT(tabFocusRequest(IRCDockTabContents*)));
74  connect(pNewAdapterWidget, SIGNAL(titleChange(IRCDockTabContents*)), SLOT(titleChange(IRCDockTabContents*)));
75  connect(pNewAdapterWidget, SIGNAL(newMessagePrinted()),
76  SLOT(titleChangeWithColorOfSenderIfNotFocused()));
77  connect(pNewAdapterWidget, SIGNAL(titleBlinkRequested()),
78  SLOT(titleChangeWithColorOfSenderIfNotFocused()));
79 
80  pNewAdapterWidget->setIRCAdapter(pIRCAdapter);
81  d->tabWidget->addTab(pNewAdapterWidget, pNewAdapterWidget->icon(), pNewAdapterWidget->title());
82  this->titleChange(pNewAdapterWidget);
83 
84  return pNewAdapterWidget;
85 }
86 
88 {
89  for (int i = 0; i < d->tabWidget->count(); ++i)
90  {
91  auto pWidget = (IRCDockTabContents *)d->tabWidget->widget(i);
92  pWidget->applyAppearanceSettings();
93  }
94 }
95 
96 void IRCDock::chatWindowCloseRequestSlot(IRCDockTabContents *pCaller)
97 {
98  int tabIndex = d->tabWidget->indexOf(pCaller);
99  if (tabIndex >= 0)
100  tabCloseRequestedSlot(tabIndex);
101 }
102 
103 void IRCDock::connectToNewNetwork(const IRCNetworkConnectionInfo &connectionInfo, bool bFocusOnNewTab)
104 {
105  IRCNetworkAdapter *pIRCNetworkAdapter = new IRCNetworkAdapter(connectionInfo);
106 
107  // Switch this to true only for debug.
108  pIRCNetworkAdapter->setEmitAllIRCMessagesEnabled(false);
109 
110  // Setup the UI tab for the new network.
111  IRCDockTabContents *pTab = addIRCAdapter(pIRCNetworkAdapter);
112 
113  // Connect to the network.
114  pIRCNetworkAdapter->connect();
115 
116  if (bFocusOnNewTab)
117  tabFocusRequest(pTab);
118 }
119 
120 bool IRCDock::hasTabFocus(const IRCDockTabContents *pTab) const
121 {
122  return this->d->tabWidget->currentWidget() == pTab;
123 }
124 
125 IRCNetworkAdapter *IRCDock::networkWithUiFocus()
126 {
127  auto pWidget = (IRCDockTabContents *)d->tabWidget->currentWidget();
128  if (pWidget == nullptr)
129  return nullptr;
130 
131  return pWidget->ircAdapter()->network();
132 }
133 
134 void IRCDock::performNetworkAutojoins()
135 {
136  IRCNetworkConnectionInfo connectionInfo;
137  connectionInfo.alternateNick = gIRCConfig.personal.alternativeNickname;
138  connectionInfo.nick = gIRCConfig.personal.nickname;
139  connectionInfo.realName = gIRCConfig.personal.fullName;
140  connectionInfo.userName = gIRCConfig.personal.userName;
141 
142  QList<IRCNetworkEntity> autojoinNetworks = ChatNetworksCfg().autoJoinNetworks();
143  for (const IRCNetworkEntity &network : autojoinNetworks)
144  {
145  connectionInfo.networkEntity = network;
146 
147  connectToNewNetwork(connectionInfo.autoFilled(), false);
148  }
149 }
150 
151 QString IRCDock::prefixMessage(IRCAdapterBase *pTargetChatWindow, IRCAdapterBase *pMessageSender, const QString &message)
152 {
153  if (pMessageSender != nullptr)
154  {
155  IRCNetworkAdapter *pTargetNetwork = pTargetChatWindow->network();
156  if (pTargetNetwork != pMessageSender)
157  return QString("%1: %2").arg(pMessageSender->title(), message);
158  }
159 
160  return message;
161 }
162 
163 void IRCDock::setupToolbar()
164 {
165  auto pToolBar = new QToolBar(this);
166  pToolBar->setMovable(false);
167  pToolBar->setOrientation(Qt::Vertical);
168 
169  d->toolBarConnect = new QAction(QIcon(":/icons/network-connect-3.png"), tr("Connect"), pToolBar);
170  d->toolBarOpenChatWindow = new QAction(QIcon(":/icons/irc_channel.png"), tr("Open chat window"), pToolBar);
171 
172  pToolBar->addAction(d->toolBarConnect);
173  pToolBar->addAction(d->toolBarOpenChatWindow);
174 
175  d->horizontalLayout->insertWidget(0, pToolBar);
176  connect(pToolBar, SIGNAL(actionTriggered(QAction*)), this, SLOT(toolBarAction(QAction*)));
177 }
178 
179 IRCSounds &IRCDock::sounds()
180 {
181  return d->pSounds;
182 }
183 
184 void IRCDock::tabCloseRequestedSlot(int index)
185 {
186  QWidget *pPageWidget = d->tabWidget->widget(index);
187  d->tabWidget->removeTab(index);
188 
189  delete pPageWidget;
190 }
191 
192 void IRCDock::tabCurrentChanged(int index)
193 {
194  if (index >= 0)
195  {
196  d->tabWidget->tabBarPublic()->setTabTextColor(index, "");
197  auto pTab = (IRCDockTabContents *) d->tabWidget->widget(index);
198  pTab->grabFocus();
199  }
200 }
201 
202 void IRCDock::tabFocusRequest(IRCDockTabContents *pCaller)
203 {
204  d->tabWidget->setCurrentWidget(pCaller);
205 }
206 
207 IRCDockTabContents *IRCDock::tabWithFocus()
208 {
209  if (d->tabWidget->currentWidget() != nullptr)
210  return static_cast<IRCDockTabContents *>(d->tabWidget->currentWidget());
211  return nullptr;
212 }
213 
214 void IRCDock::titleChange(IRCDockTabContents *caller)
215 {
216  int tabIndex = d->tabWidget->indexOf(caller);
217  if (tabIndex >= 0)
218  d->tabWidget->setTabText(tabIndex, caller->title());
219 }
220 
221 void IRCDock::titleChangeWithColorOfSenderIfNotFocused()
222 {
223  auto caller = static_cast<IRCDockTabContents *>(sender());
224  int tabIndex = d->tabWidget->indexOf(caller);
225  if (tabIndex >= 0)
226  {
227  d->tabWidget->setTabText(tabIndex, caller->title());
228  d->tabWidget->tabBarPublic()->setTabTextColor(tabIndex, caller->titleColor());
229  }
230 }
231 
232 void IRCDock::toolBarAction(QAction *pAction)
233 {
234  if (pAction == d->toolBarConnect)
235  {
236  IRCNetworkSelectionBox networkSelection(this);
237  if (networkSelection.exec() == QDialog::Accepted)
238  {
239  IRCNetworkConnectionInfo connectionInfo = networkSelection.networkConnectionInfo();
240  ChatNetworksCfg().setLastUsedNetwork(connectionInfo.networkEntity);
241 
242  // We will attempt to remember user credentials for further use.
243  gIRCConfig.personal.alternativeNickname = connectionInfo.alternateNick;
244  gIRCConfig.personal.nickname = connectionInfo.nick;
245  gIRCConfig.personal.fullName = connectionInfo.realName;
246  gIRCConfig.personal.userName = connectionInfo.userName;
247 
248  connectToNewNetwork(connectionInfo.autoFilled(), true);
249  }
250  }
251  else if (pAction == d->toolBarOpenChatWindow)
252  {
253  IRCNetworkAdapter *pNetwork = networkWithUiFocus();
254  if (pNetwork == nullptr)
255  QMessageBox::warning(nullptr, tr("Doomseeker IRC - Open chat window"), tr("Cannot obtain network connection adapter."));
256  else if (!pNetwork->isConnected())
257  QMessageBox::warning(nullptr, tr("Doomseeker IRC - Open chat window"), tr("You are not connected to this network."));
258  else
259  {
260  QString recipientName = QInputDialog::getText(nullptr, tr("Open chat window"), tr("Specify a channel or user name:"));
261  if (!recipientName.isEmpty())
262  pNetwork->openNewAdapter(recipientName);
263  }
264  }
265 }