1 //=============================================================================
2 //
3 // File : OptionsWidget_proxy.cpp
4 // Creation date : Mon Jun 24 2000 22:02:11 by Szymon Stefanek
5 //
6 // This file is part of the KVIrc IRC client distribution
7 // Copyright (C) 2000-2010 Szymon Stefanek (pragma at kvirc dot net)
8 //
9 // This program is FREE software. You can redistribute it and/or
10 // modify it under the terms of the GNU General Public License
11 // as published by the Free Software Foundation; either version 2
12 // of the License, or (at your option) any later version.
13 //
14 // This program is distributed in the HOPE that it will be USEFUL,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 // See the GNU General Public License for more details.
18 //
19 // You should have received a copy of the GNU General Public License
20 // along with this program. If not, write to the Free Software Foundation,
21 // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 //
23 //=============================================================================
24
25 #include "OptionsWidget_proxy.h"
26
27 #include "KviLocale.h"
28 #include "KviIconManager.h"
29 #include "KviProxy.h"
30 #include "KviProxyDataBase.h"
31 #include "KviIpEditor.h"
32 #include "KviNetUtils.h"
33 #include "kvi_settings.h"
34 #include "KviOptions.h"
35 #include "KviTalGroupBox.h"
36 #include "KviTalToolTip.h"
37
38 #include <QLabel>
39 #include <QLineEdit>
40 #include <QComboBox>
41 #include <QCursor>
42 #include <QIcon>
43 #include <QToolButton>
44 #include <QMenu>
45
46 #include <memory>
47 #include <utility>
48 #include <vector>
49
ProxyOptionsTreeWidgetItem(QTreeWidget * parent,const QPixmap & pm,KviProxy * prx)50 ProxyOptionsTreeWidgetItem::ProxyOptionsTreeWidgetItem(QTreeWidget * parent, const QPixmap & pm, KviProxy * prx)
51 : QTreeWidgetItem(parent)
52 {
53 qDebug("Creating item");
54 setText(0, prx->hostname());
55 setIcon(0, QIcon(pm));
56 m_pProxyData = new KviProxy(*prx);
57 }
58
~ProxyOptionsTreeWidgetItem()59 ProxyOptionsTreeWidgetItem::~ProxyOptionsTreeWidgetItem()
60 {
61 qDebug("Deleting item");
62 delete m_pProxyData;
63 }
64
OptionsWidget_proxy(QWidget * parent)65 OptionsWidget_proxy::OptionsWidget_proxy(QWidget * parent)
66 : KviOptionsWidget(parent, "proxy_options_widget")
67 {
68 createLayout();
69
70 m_pUseProxySelector = addBoolSelector(0, 0, 1, 0, __tr2qs_ctx("Use proxy for all connections", "options"), KviOption_boolUseProxyHost);
71 QString szTip = __tr2qs_ctx("When enabled, the selected proxy will be used as the default for all connections. "
72 "An alternative option to define a specific per-server proxy, is also located "
73 "in the advanced server dialog in the connection tab.", "options");
74
75 mergeTip(m_pUseProxySelector, szTip);
76
77 m_pTreeWidget = new QTreeWidget(this);
78 addWidgetToLayout(m_pTreeWidget, 0, 1, 0, 1);
79 m_pTreeWidget->setHeaderLabel(__tr2qs_ctx("Proxy", "options"));
80 m_pTreeWidget->setRootIsDecorated(true);
81 m_pTreeWidget->setAllColumnsShowFocus(true);
82 m_pTreeWidget->setSelectionMode(QAbstractItemView::SingleSelection);
83
84 connect(m_pTreeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
85 this, SLOT(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
86 m_pTreeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
87 connect(m_pTreeWidget, SIGNAL(customContextMenuRequested(const QPoint &)),
88 this, SLOT(customContextMenuRequested(const QPoint &)));
89
90 QString tiptxt = __tr2qs_ctx("This is the list of available proxy servers.<br>"
91 "Right-click on the list to add or remove proxies.", "options");
92
93 mergeTip(m_pTreeWidget, tiptxt);
94 mergeTip(m_pTreeWidget->viewport(), tiptxt);
95
96 KviTalVBox * vbox = new KviTalVBox(this);
97 addWidgetToLayout(vbox, 1, 1, 1, 1);
98
99 QToolButton * tb = new QToolButton(vbox);
100 tb->setIcon(QIcon(*(g_pIconManager->getSmallIcon(KviIconManager::NewProxy))));
101 tb->setAutoRaise(true);
102 connect(tb, SIGNAL(clicked()), this, SLOT(newProxy()));
103 mergeTip(tb, __tr2qs_ctx("New proxy", "options"));
104
105 tb = new QToolButton(vbox);
106 tb->setIcon(QIcon(*(g_pIconManager->getSmallIcon(KviIconManager::Remove))));
107 tb->setAutoRaise(true);
108 connect(tb, SIGNAL(clicked()), this, SLOT(removeCurrent()));
109 mergeTip(tb, __tr2qs_ctx("Remove proxy", "options"));
110
111 QFrame * lll = new QFrame(vbox);
112 vbox->setStretchFactor(lll, 100);
113
114 KviTalGroupBox * gbox = addGroupBox(0, 2, 1, 2, Qt::Horizontal, __tr2qs_ctx("Configuration", "options"));
115
116 m_pProxyLabel = new QLabel(__tr2qs_ctx("Proxy:", "options"), gbox);
117 m_pProxyEdit = new QLineEdit(gbox);
118 m_pPortLabel = new QLabel(__tr2qs_ctx("Port:", "options"), gbox);
119 m_pPortEdit = new QLineEdit(gbox);
120 m_pIpLabel = new QLabel(__tr2qs_ctx("IP address:", "options"), gbox);
121 m_pIpEditor = new KviIpEditor(gbox, KviIpEditor::IPv4);
122 m_pUserLabel = new QLabel(__tr2qs_ctx("Username:", "options"), gbox);
123 m_pUserEdit = new QLineEdit(gbox);
124 m_pPassLabel = new QLabel(__tr2qs_ctx("Password:", "options"), gbox);
125 m_pPassEdit = new QLineEdit(gbox);
126 m_pProtocolLabel = new QLabel(__tr2qs_ctx("Protocol:", "options"), gbox);
127 m_pProtocolBox = new QComboBox(gbox);
128
129 QStringList l = KviProxy::getSupportedProtocolNames();
130
131 m_pProtocolBox->addItems(l);
132
133 m_pIPv6Check = new QCheckBox(__tr2qs_ctx("Use IPv6 protocol", "options"), gbox);
134 connect(m_pIPv6Check, SIGNAL(toggled(bool)), this, SLOT(ipV6CheckToggled(bool)));
135 #ifndef COMPILE_IPV6_SUPPORT
136 m_pIPv6Check->setEnabled(false);
137 #endif
138 m_pLastEditedItem = nullptr;
139
140 fillProxyList();
141
142 layout()->setRowStretch(0, 1);
143 layout()->setColumnStretch(0, 1);
144
145 m_pContextPopup = new QMenu(this);
146 }
147
enableDisableUseProxySelector()148 void OptionsWidget_proxy::enableDisableUseProxySelector()
149 {
150 m_pUseProxySelector->setEnabled(m_pTreeWidget->currentItem());
151 if(m_pTreeWidget->topLevelItemCount() < 1)
152 m_pUseProxySelector->setChecked(false);
153 }
154
ipV6CheckToggled(bool bEnabled)155 void OptionsWidget_proxy::ipV6CheckToggled(bool bEnabled)
156 {
157 m_pIpEditor->setAddressType(bEnabled ? KviIpEditor::IPv6 : KviIpEditor::IPv4);
158 }
159
fillProxyList()160 void OptionsWidget_proxy::fillProxyList()
161 {
162 ProxyOptionsTreeWidgetItem * prx;
163
164 std::vector<std::unique_ptr<KviProxy>> & l = g_pProxyDataBase->proxyList();
165
166 for(auto & p : l)
167 {
168 prx = new ProxyOptionsTreeWidgetItem(m_pTreeWidget, *(g_pIconManager->getSmallIcon(KviIconManager::Proxy)), p.get());
169 if(p.get() == g_pProxyDataBase->currentProxy())
170 {
171 prx->setSelected(true);
172 m_pTreeWidget->setCurrentItem(prx);
173 m_pTreeWidget->scrollToItem(prx);
174 }
175 }
176 if(!(g_pProxyDataBase->currentProxy()))
177 currentItemChanged(nullptr, nullptr);
178
179 enableDisableUseProxySelector();
180 }
181
currentItemChanged(QTreeWidgetItem * it,QTreeWidgetItem *)182 void OptionsWidget_proxy::currentItemChanged(QTreeWidgetItem * it, QTreeWidgetItem *)
183 {
184 if(m_pLastEditedItem)
185 saveLastItem();
186 m_pLastEditedItem = (ProxyOptionsTreeWidgetItem *)it;
187
188 m_pProxyLabel->setEnabled(m_pLastEditedItem);
189 m_pProxyEdit->setEnabled(m_pLastEditedItem);
190 m_pIpLabel->setEnabled(m_pLastEditedItem);
191 m_pIpEditor->setEnabled(m_pLastEditedItem);
192 m_pUserLabel->setEnabled(m_pLastEditedItem);
193 m_pUserEdit->setEnabled(m_pLastEditedItem);
194 m_pPassLabel->setEnabled(m_pLastEditedItem);
195 m_pPassEdit->setEnabled(m_pLastEditedItem);
196 m_pProtocolLabel->setEnabled(m_pLastEditedItem);
197 m_pProtocolBox->setEnabled(m_pLastEditedItem);
198 m_pPortLabel->setEnabled(m_pLastEditedItem);
199 m_pPortEdit->setEnabled(m_pLastEditedItem);
200
201 #ifdef COMPILE_IPV6_SUPPORT
202 m_pIPv6Check->setEnabled(m_pLastEditedItem);
203 #else
204 m_pIPv6Check->setEnabled(false);
205 #endif
206 if(m_pLastEditedItem)
207 {
208 m_pProxyEdit->setText(m_pLastEditedItem->m_pProxyData->hostname());
209
210 for(int i = 0; i < m_pProtocolBox->count(); i++)
211 {
212 KviCString txt = m_pProtocolBox->itemText(i);
213 if(kvi_strEqualCI(m_pLastEditedItem->m_pProxyData->protocolName().toUtf8().data(), txt.ptr()))
214 {
215 m_pProtocolBox->setCurrentIndex(i);
216 break;
217 }
218 }
219
220 #ifdef COMPILE_IPV6_SUPPORT
221 m_pIPv6Check->setChecked(m_pLastEditedItem->m_pProxyData->isIPv6());
222 m_pIpEditor->setAddressType(m_pLastEditedItem->m_pProxyData->isIPv6() ? KviIpEditor::IPv6 : KviIpEditor::IPv4);
223 #else
224 m_pIPv6Check->setChecked(false);
225 m_pIpEditor->setAddressType(KviIpEditor::IPv4);
226 #endif
227 if(!m_pIpEditor->setAddress(m_pLastEditedItem->m_pProxyData->ip()))
228 {
229 #ifdef COMPILE_IPV6_SUPPORT
230 m_pIpEditor->setAddress(m_pLastEditedItem->m_pProxyData->isIPv6() ? "0:0:0:0:0:0:0:0" : "0.0.0.0");
231 #else
232 m_pIpEditor->setAddress("0.0.0.0");
233 #endif
234 }
235
236 m_pUserEdit->setText(m_pLastEditedItem->m_pProxyData->user());
237 m_pPassEdit->setText(m_pLastEditedItem->m_pProxyData->pass());
238 KviCString tmp(KviCString::Format, "%u", m_pLastEditedItem->m_pProxyData->port());
239 m_pPortEdit->setText(tmp.ptr());
240 }
241 else
242 {
243 m_pProxyEdit->setText("");
244 m_pUserEdit->setText("");
245 m_pPassEdit->setText("");
246 m_pPortEdit->setText("");
247 m_pIpEditor->setAddress("0.0.0.0");
248 m_pIPv6Check->setEnabled(false);
249 }
250 enableDisableUseProxySelector();
251 }
252
saveLastItem()253 void OptionsWidget_proxy::saveLastItem()
254 {
255 if(m_pLastEditedItem)
256 {
257 QString tmp = m_pProxyEdit->text();
258 if(tmp.isEmpty())
259 tmp = "irc.unknown.net";
260
261 m_pLastEditedItem->setText(0, tmp);
262 m_pLastEditedItem->m_pProxyData->setHostname(tmp);
263 #ifdef COMPILE_IPV6_SUPPORT
264 m_pLastEditedItem->m_pProxyData->setIPv6(m_pIPv6Check->isChecked());
265 #else
266 m_pLastEditedItem->m_pProxyData->setIPv6(false);
267 #endif
268 m_pLastEditedItem->m_pProxyData->setIp("");
269
270 if(m_pIpEditor->isValid())
271 {
272 QString tmpAddr = m_pIpEditor->address();
273 #ifdef COMPILE_IPV6_SUPPORT
274 if(m_pIPv6Check->isChecked())
275 {
276 if(tmpAddr != "::" && KviNetUtils::isValidStringIPv6(tmpAddr))
277 m_pLastEditedItem->m_pProxyData->setIp(tmpAddr);
278 }
279 else
280 {
281 #endif
282 if(tmpAddr != "0.0.0.0" && KviNetUtils::isValidStringIp(tmpAddr))
283 m_pLastEditedItem->m_pProxyData->setIp(tmpAddr);
284 #ifdef COMPILE_IPV6_SUPPORT
285 }
286 #endif
287 }
288 m_pLastEditedItem->m_pProxyData->setPass(m_pPassEdit->text());
289 m_pLastEditedItem->m_pProxyData->setUser(m_pUserEdit->text());
290 tmp = m_pPortEdit->text();
291 bool bOk;
292 kvi_u32_t uPort = tmp.toUInt(&bOk);
293 if(!bOk)
294 uPort = 1080;
295 m_pLastEditedItem->m_pProxyData->setPort(uPort);
296 m_pLastEditedItem->m_pProxyData->setNamedProtocol(m_pProtocolBox->currentText());
297 }
298 }
299
commit()300 void OptionsWidget_proxy::commit()
301 {
302 saveLastItem();
303 g_pProxyDataBase->clear();
304
305 ProxyOptionsTreeWidgetItem * it;
306
307 for(int i = 0; i < m_pTreeWidget->topLevelItemCount(); i++)
308 {
309 it = (ProxyOptionsTreeWidgetItem *)m_pTreeWidget->topLevelItem(i);
310 QString tmp = it->text(0);
311 if(!tmp.isEmpty())
312 {
313 KviProxy *const proxy = new KviProxy(*(it->m_pProxyData));
314
315 g_pProxyDataBase->insertProxy(std::unique_ptr<KviProxy>(proxy));
316
317 if(it == m_pLastEditedItem)
318 g_pProxyDataBase->setCurrentProxy(proxy);
319 }
320 }
321
322 if(!g_pProxyDataBase->currentProxy() && !g_pProxyDataBase->proxyList().empty())
323 g_pProxyDataBase->setCurrentProxy(g_pProxyDataBase->proxyList().front().get());
324
325 KviOptionsWidget::commit();
326 }
327
customContextMenuRequested(const QPoint & pos)328 void OptionsWidget_proxy::customContextMenuRequested(const QPoint & pos)
329 {
330 QTreeWidgetItem * it = (QTreeWidgetItem *)m_pTreeWidget->itemAt(pos);
331 m_pContextPopup->clear();
332 m_pContextPopup->addAction(*(g_pIconManager->getSmallIcon(KviIconManager::NewProxy)), __tr2qs_ctx("&New Proxy", "options"), this, SLOT(newProxy()));
333 m_pContextPopup->addAction(*(g_pIconManager->getSmallIcon(KviIconManager::Remove)), __tr2qs_ctx("Re&move Proxy", "options"), this, SLOT(removeCurrent()))
334 ->setEnabled(it);
335 m_pContextPopup->popup(QCursor::pos());
336 }
337
newProxy()338 void OptionsWidget_proxy::newProxy()
339 {
340 KviProxy prx;
341 ProxyOptionsTreeWidgetItem * it = new ProxyOptionsTreeWidgetItem(m_pTreeWidget, *(g_pIconManager->getSmallIcon(KviIconManager::Proxy)), &prx);
342 it->setSelected(true);
343 m_pTreeWidget->setCurrentItem(it);
344 m_pTreeWidget->scrollToItem(it);
345 }
346
removeCurrent()347 void OptionsWidget_proxy::removeCurrent()
348 {
349 if(m_pLastEditedItem)
350 {
351 QTreeWidgetItem * tmp = m_pLastEditedItem;
352 m_pLastEditedItem = nullptr;
353 delete tmp;
354
355 QTreeWidgetItem * it = (QTreeWidgetItem *)m_pTreeWidget->topLevelItem(0);
356 if(it)
357 {
358 it->setSelected(true);
359 }
360 else
361 {
362 currentItemChanged(nullptr, nullptr);
363 }
364 }
365 }
366