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