VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/settings/machine/UIMachineSettingsPortForwardingDlg.cpp@ 37126

Last change on this file since 37126 was 33882, checked in by vboxsync, 14 years ago

FE/Qt: Global & Machine settings refactoring, part 1 (files & classes renaming).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Revision Author Id
File size: 25.2 KB
Line 
1/* $Id: UIMachineSettingsPortForwardingDlg.cpp 33882 2010-11-09 09:32:27Z vboxsync $ */
2/** @file
3 *
4 * VBox frontends: Qt4 GUI ("VirtualBox"):
5 * UIMachineSettingsPortForwardingDlg class implementation
6 */
7
8/*
9 * Copyright (C) 2010 Oracle Corporation
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.virtualbox.org. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 */
19
20/* Global includes */
21#include <QAction>
22#include <QHeaderView>
23#include <QPushButton>
24#include <QStyledItemDelegate>
25#include <QItemEditorFactory>
26#include <QComboBox>
27#include <QLineEdit>
28#include <QSpinBox>
29#include <QTimer>
30
31/* Local includes */
32#include "UIMachineSettingsPortForwardingDlg.h"
33#include "VBoxGlobal.h"
34#include "VBoxProblemReporter.h"
35#include "UIToolBar.h"
36#include "QITableView.h"
37#include "QIDialogButtonBox.h"
38#include "UIIconPool.h"
39#include <iprt/cidr.h>
40#include <math.h>
41
42/* IP validator: */
43class IPValidator : public QValidator
44{
45 Q_OBJECT;
46
47public:
48
49 IPValidator(QObject *pParent) : QValidator(pParent) {}
50 ~IPValidator() {}
51
52 QValidator::State validate(QString &strInput, int & /* iPos */) const
53 {
54 QString strStringToValidate(strInput);
55 strStringToValidate.remove(' ');
56 QString strDot("\\.");
57 QString strDigits("(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]?|0)");
58 QRegExp intRegExp(QString("^(%1?(%2(%1?(%2(%1?(%2%1?)?)?)?)?)?)?$").arg(strDigits).arg(strDot));
59 uint uNetwork, uMask;
60 if (strStringToValidate == "..." || RTCidrStrToIPv4(strStringToValidate.toLatin1().constData(), &uNetwork, &uMask) == VINF_SUCCESS)
61 return QValidator::Acceptable;
62 else if (intRegExp.indexIn(strStringToValidate) != -1)
63 return QValidator::Intermediate;
64 else
65 return QValidator::Invalid;
66 }
67};
68
69/* Name editor: */
70class NameEditor : public QLineEdit
71{
72 Q_OBJECT;
73 Q_PROPERTY(NameData name READ name WRITE setName USER true);
74
75public:
76
77 NameEditor(QWidget *pParent = 0) : QLineEdit(pParent)
78 {
79 setFrame(false);
80 setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
81 setValidator(new QRegExpValidator(QRegExp("[^,]*"), this));
82 }
83
84private:
85
86 void setName(NameData name)
87 {
88 setText(name);
89 }
90
91 NameData name() const
92 {
93 return text();
94 }
95};
96
97/* Protocol editor: */
98class ProtocolEditor : public QComboBox
99{
100 Q_OBJECT;
101 Q_PROPERTY(KNATProtocol protocol READ protocol WRITE setProtocol USER true);
102
103public:
104
105 ProtocolEditor(QWidget *pParent = 0) : QComboBox(pParent)
106 {
107 addItem(vboxGlobal().toString(KNATProtocol_UDP), QVariant::fromValue(KNATProtocol_UDP));
108 addItem(vboxGlobal().toString(KNATProtocol_TCP), QVariant::fromValue(KNATProtocol_TCP));
109 }
110
111private:
112
113 void setProtocol(KNATProtocol p)
114 {
115 for (int i = 0; i < count(); ++i)
116 {
117 if (itemData(i).value<KNATProtocol>() == p)
118 {
119 setCurrentIndex(i);
120 break;
121 }
122 }
123 }
124
125 KNATProtocol protocol() const
126 {
127 return itemData(currentIndex()).value<KNATProtocol>();
128 }
129};
130
131/* IP editor: */
132class IPEditor : public QLineEdit
133{
134 Q_OBJECT;
135 Q_PROPERTY(IpData ip READ ip WRITE setIp USER true);
136
137public:
138
139 IPEditor(QWidget *pParent = 0) : QLineEdit(pParent)
140 {
141 setFrame(false);
142 setAlignment(Qt::AlignCenter);
143 setValidator(new IPValidator(this));
144 setInputMask("000.000.000.000");
145 }
146
147private:
148
149 void setIp(IpData ip)
150 {
151 setText(ip);
152 }
153
154 IpData ip() const
155 {
156 return text() == "..." ? QString() : text();
157 }
158};
159
160/* Port editor: */
161class PortEditor : public QSpinBox
162{
163 Q_OBJECT;
164 Q_PROPERTY(PortData port READ port WRITE setPort USER true);
165
166public:
167
168 PortEditor(QWidget *pParent = 0) : QSpinBox(pParent)
169 {
170 setFrame(false);
171 setRange(0, (1 << (8 * sizeof(ushort))) - 1);
172 }
173
174private:
175
176 void setPort(PortData port)
177 {
178 setValue(port.value());
179 }
180
181 PortData port() const
182 {
183 return value();
184 }
185};
186
187/* Port forwarding data model: */
188class UIPortForwardingModel : public QAbstractTableModel
189{
190 Q_OBJECT;
191
192public:
193
194 /* Column names: */
195 enum UIPortForwardingDataType
196 {
197 UIPortForwardingDataType_Name,
198 UIPortForwardingDataType_Protocol,
199 UIPortForwardingDataType_HostIp,
200 UIPortForwardingDataType_HostPort,
201 UIPortForwardingDataType_GuestIp,
202 UIPortForwardingDataType_GuestPort,
203 UIPortForwardingDataType_Max
204 };
205
206 /* Port forwarding model constructor: */
207 UIPortForwardingModel(QObject *pParent = 0, const UIPortForwardingDataList &rules = UIPortForwardingDataList())
208 : QAbstractTableModel(pParent), m_dataList(rules) {}
209 /* Port forwarding model destructor: */
210 ~UIPortForwardingModel() {}
211
212 /* The list of chosen rules: */
213 const UIPortForwardingDataList& rules() const
214 {
215 return m_dataList;
216 }
217
218 /* Flags for model indexes: */
219 Qt::ItemFlags flags(const QModelIndex &index) const
220 {
221 /* Check index validness: */
222 if (!index.isValid())
223 return Qt::NoItemFlags;
224 /* All columns have similar flags: */
225 return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable;
226 }
227
228 /* Row count getter: */
229 int rowCount(const QModelIndex & parent = QModelIndex()) const
230 {
231 Q_UNUSED(parent);
232 return m_dataList.size();
233 }
234
235 /* Column count getter: */
236 int columnCount(const QModelIndex & parent = QModelIndex()) const
237 {
238 Q_UNUSED(parent);
239 return UIPortForwardingDataType_Max;
240 }
241
242 /* Get header data: */
243 QVariant headerData(int iSection, Qt::Orientation orientation, int iRole) const
244 {
245 /* Display role for horizontal header: */
246 if (iRole == Qt::DisplayRole && orientation == Qt::Horizontal)
247 {
248 /* Switch for different columns: */
249 switch (iSection)
250 {
251 case UIPortForwardingDataType_Name: return tr("Name");
252 case UIPortForwardingDataType_Protocol: return tr("Protocol");
253 case UIPortForwardingDataType_HostIp: return tr("Host IP");
254 case UIPortForwardingDataType_HostPort: return tr("Host Port");
255 case UIPortForwardingDataType_GuestIp: return tr("Guest IP");
256 case UIPortForwardingDataType_GuestPort: return tr("Guest Port");
257 default: break;
258 }
259 }
260 /* Return wrong value: */
261 return QVariant();
262 }
263
264 /* Get index data: */
265 QVariant data(const QModelIndex &index, int iRole) const
266 {
267 /* Check index validness: */
268 if (!index.isValid())
269 return QVariant();
270 /* Switch for different roles: */
271 switch (iRole)
272 {
273 /* Display role: */
274 case Qt::DisplayRole:
275 {
276 /* Switch for different columns: */
277 switch (index.column())
278 {
279 case UIPortForwardingDataType_Name: return m_dataList[index.row()].name;
280 case UIPortForwardingDataType_Protocol: return vboxGlobal().toString(m_dataList[index.row()].protocol);
281 case UIPortForwardingDataType_HostIp: return m_dataList[index.row()].hostIp;
282 case UIPortForwardingDataType_HostPort: return m_dataList[index.row()].hostPort.value();
283 case UIPortForwardingDataType_GuestIp: return m_dataList[index.row()].guestIp;
284 case UIPortForwardingDataType_GuestPort: return m_dataList[index.row()].guestPort.value();
285 default: return QVariant();
286 }
287 }
288 /* Edit role: */
289 case Qt::EditRole:
290 {
291 /* Switch for different columns: */
292 switch (index.column())
293 {
294 case UIPortForwardingDataType_Name: return QVariant::fromValue(m_dataList[index.row()].name);
295 case UIPortForwardingDataType_Protocol: return QVariant::fromValue(m_dataList[index.row()].protocol);
296 case UIPortForwardingDataType_HostIp: return QVariant::fromValue(m_dataList[index.row()].hostIp);
297 case UIPortForwardingDataType_HostPort: return QVariant::fromValue(m_dataList[index.row()].hostPort);
298 case UIPortForwardingDataType_GuestIp: return QVariant::fromValue(m_dataList[index.row()].guestIp);
299 case UIPortForwardingDataType_GuestPort: return QVariant::fromValue(m_dataList[index.row()].guestPort);
300 default: return QVariant();
301 }
302 }
303 /* Alignment role: */
304 case Qt::TextAlignmentRole:
305 {
306 /* Switch for different columns: */
307 switch (index.column())
308 {
309 case UIPortForwardingDataType_Name:
310 case UIPortForwardingDataType_Protocol:
311 case UIPortForwardingDataType_HostPort:
312 case UIPortForwardingDataType_GuestPort:
313 return (int)(Qt::AlignLeft | Qt::AlignVCenter);
314 case UIPortForwardingDataType_HostIp:
315 case UIPortForwardingDataType_GuestIp:
316 return Qt::AlignCenter;
317 default: return QVariant();
318 }
319 }
320 case Qt::SizeHintRole:
321 {
322 /* Switch for different columns: */
323 switch (index.column())
324 {
325 case UIPortForwardingDataType_HostIp:
326 case UIPortForwardingDataType_GuestIp:
327 return QSize(QApplication::fontMetrics().width(" 888.888.888.888 "), QApplication::fontMetrics().height());
328 default: return QVariant();
329 }
330 }
331 default: break;
332 }
333 /* Return wrong value: */
334 return QVariant();
335 }
336
337 /* Set index data: */
338 bool setData(const QModelIndex &index, const QVariant &value, int iRole = Qt::EditRole)
339 {
340 /* Check index validness: */
341 if (!index.isValid() || iRole != Qt::EditRole)
342 return false;
343 /* Switch for different columns: */
344 switch (index.column())
345 {
346 case UIPortForwardingDataType_Name:
347 m_dataList[index.row()].name = value.value<NameData>();
348 emit dataChanged(index, index);
349 return true;
350 case UIPortForwardingDataType_Protocol:
351 m_dataList[index.row()].protocol = value.value<KNATProtocol>();
352 emit dataChanged(index, index);
353 return true;
354 case UIPortForwardingDataType_HostIp:
355 m_dataList[index.row()].hostIp = value.value<IpData>();
356 emit dataChanged(index, index);
357 return true;
358 case UIPortForwardingDataType_HostPort:
359 m_dataList[index.row()].hostPort = value.value<PortData>();
360 emit dataChanged(index, index);
361 return true;
362 case UIPortForwardingDataType_GuestIp:
363 m_dataList[index.row()].guestIp = value.value<IpData>();
364 emit dataChanged(index, index);
365 return true;
366 case UIPortForwardingDataType_GuestPort:
367 m_dataList[index.row()].guestPort = value.value<PortData>();
368 emit dataChanged(index, index);
369 return true;
370 default: return false;
371 }
372 /* Return false value: */
373 return false;
374 }
375
376 /* Add/Copy rule: */
377 void addRule(const QModelIndex &index)
378 {
379 beginInsertRows(QModelIndex(), m_dataList.size(), m_dataList.size());
380 /* Search for existing "Rule [NUMBER]" record: */
381 uint uMaxIndex = 0;
382 QString strTemplate("Rule %1");
383 QRegExp regExp(strTemplate.arg("(\\d+)"));
384 for (int i = 0; i < m_dataList.size(); ++i)
385 if (regExp.indexIn(m_dataList[i].name) > -1)
386 uMaxIndex = regExp.cap(1).toUInt() > uMaxIndex ? regExp.cap(1).toUInt() : uMaxIndex;
387 /* If index is valid => copy data: */
388 if (index.isValid())
389 m_dataList << UIPortForwardingData(strTemplate.arg(++uMaxIndex), m_dataList[index.row()].protocol,
390 m_dataList[index.row()].hostIp, m_dataList[index.row()].hostPort,
391 m_dataList[index.row()].guestIp, m_dataList[index.row()].guestPort);
392 /* If index is NOT valid => use default values: */
393 else
394 m_dataList << UIPortForwardingData(strTemplate.arg(++uMaxIndex), KNATProtocol_TCP,
395 QString(""), 0, QString(""), 0);
396 endInsertRows();
397 }
398
399 /* Delete rule: */
400 void delRule(const QModelIndex &index)
401 {
402 if (!index.isValid())
403 return;
404 beginRemoveRows(QModelIndex(), index.row(), index.row());
405 m_dataList.removeAt(index.row());
406 endRemoveRows();
407 }
408
409private:
410
411 /* Data container: */
412 UIPortForwardingDataList m_dataList;
413};
414
415/* Port forwarding dialog constructor: */
416UIMachineSettingsPortForwardingDlg::UIMachineSettingsPortForwardingDlg(QWidget *pParent,
417 const UIPortForwardingDataList &rules)
418 : QIWithRetranslateUI<QIDialog>(pParent)
419 , fIsTableDataChanged(false)
420 , m_pTableView(0)
421 , m_pToolBar(0)
422 , m_pButtonBox(0)
423 , m_pModel(0)
424 , m_pAddAction(0)
425 , m_pCopyAction(0)
426 , m_pDelAction(0)
427{
428#ifdef Q_WS_MAC
429 setWindowFlags(Qt::Sheet);
430#endif /* Q_WS_MAC */
431
432 /* Set dialog icon: */
433 setWindowIcon(UIIconPool::iconSetFull(QSize(32, 32), QSize(16, 16), ":/nw_32px.png", ":/nw_16px.png"));
434
435 /* Create table: */
436 m_pTableView = new QITableView(this);
437 m_pTableView->setTabKeyNavigation(false);
438 m_pTableView->verticalHeader()->hide();
439 m_pTableView->verticalHeader()->setDefaultSectionSize((int)m_pTableView->verticalHeader()->minimumSectionSize() * 1.33);
440 m_pTableView->setSelectionMode(QAbstractItemView::SingleSelection);
441 m_pTableView->setContextMenuPolicy(Qt::CustomContextMenu);
442 m_pTableView->installEventFilter(this);
443 connect(m_pTableView, SIGNAL(sigCurrentChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(sltCurrentChanged()));
444 connect(m_pTableView, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(sltShowTableContexMenu(const QPoint &)));
445
446 /* Create actions: */
447 m_pAddAction = new QAction(this);
448 m_pCopyAction = new QAction(this);
449 m_pDelAction = new QAction(this);
450 m_pAddAction->setShortcut(QKeySequence("Ins"));
451 m_pDelAction->setShortcut(QKeySequence("Del"));
452 m_pAddAction->setIcon(UIIconPool::iconSet(":/controller_add_16px.png", ":/controller_add_disabled_16px.png"));
453 m_pCopyAction->setIcon(UIIconPool::iconSet(":/controller_add_16px.png", ":/controller_add_disabled_16px.png"));
454 m_pDelAction->setIcon(UIIconPool::iconSet(":/controller_remove_16px.png", ":/controller_remove_disabled_16px.png"));
455 connect(m_pAddAction, SIGNAL(triggered(bool)), this, SLOT(sltAddRule()));
456 connect(m_pCopyAction, SIGNAL(triggered(bool)), this, SLOT(sltCopyRule()));
457 connect(m_pDelAction, SIGNAL(triggered(bool)), this, SLOT(sltDelRule()));
458
459 /* Create toolbar: */
460 m_pToolBar = new UIToolBar(this);
461 m_pToolBar->setIconSize(QSize(16, 16));
462 m_pToolBar->setOrientation(Qt::Vertical);
463 m_pToolBar->addAction(m_pAddAction);
464 m_pToolBar->addAction(m_pDelAction);
465
466 /* Create table & toolbar layout: */
467 QHBoxLayout *pTableAndToolbarLayout = new QHBoxLayout;
468 pTableAndToolbarLayout->setSpacing(1);
469 pTableAndToolbarLayout->addWidget(m_pTableView);
470 pTableAndToolbarLayout->addWidget(m_pToolBar);
471
472 /* Create buttonbox: */
473 m_pButtonBox = new QIDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, this);
474 connect(m_pButtonBox->button(QDialogButtonBox::Ok), SIGNAL(clicked()), this, SLOT(accept()));
475 connect(m_pButtonBox->button(QDialogButtonBox::Cancel), SIGNAL(clicked()), this, SLOT(reject()));
476
477 /* Create main layout: */
478 QVBoxLayout *pMainLayout = new QVBoxLayout;
479 this->setLayout(pMainLayout);
480 pMainLayout->addLayout(pTableAndToolbarLayout);
481 pMainLayout->addWidget(m_pButtonBox);
482
483 /* Create model: */
484 m_pModel = new UIPortForwardingModel(this, rules);
485 connect(m_pModel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(sltTableDataChanged()));
486 connect(m_pModel, SIGNAL(rowsInserted(const QModelIndex &, int, int)), this, SLOT(sltTableDataChanged()));
487 connect(m_pModel, SIGNAL(rowsRemoved(const QModelIndex &, int, int)), this, SLOT(sltTableDataChanged()));
488 m_pTableView->setModel(m_pModel);
489
490 /* Register delegates editors: */
491 if (QAbstractItemDelegate *pAbstractItemDelegate = m_pTableView->itemDelegate())
492 {
493 if (QStyledItemDelegate *pStyledItemDelegate = qobject_cast<QStyledItemDelegate*>(pAbstractItemDelegate))
494 {
495 /* Create new item editor factory: */
496 QItemEditorFactory *pNewItemEditorFactory = new QItemEditorFactory;
497
498 /* Register name type: */
499 int iNameId = qRegisterMetaType<NameData>();
500 /* Register name editor: */
501 QStandardItemEditorCreator<NameEditor> *pNameEditorItemCreator = new QStandardItemEditorCreator<NameEditor>();
502 /* Link name type & editor: */
503 pNewItemEditorFactory->registerEditor((QVariant::Type)iNameId, pNameEditorItemCreator);
504
505 /* Register protocol type: */
506 int iProtocolId = qRegisterMetaType<KNATProtocol>();
507 /* Register protocol editor: */
508 QStandardItemEditorCreator<ProtocolEditor> *pProtocolEditorItemCreator = new QStandardItemEditorCreator<ProtocolEditor>();
509 /* Link protocol type & editor: */
510 pNewItemEditorFactory->registerEditor((QVariant::Type)iProtocolId, pProtocolEditorItemCreator);
511
512 /* Register ip type: */
513 int iIpId = qRegisterMetaType<IpData>();
514 /* Register ip editor: */
515 QStandardItemEditorCreator<IPEditor> *pIpEditorItemCreator = new QStandardItemEditorCreator<IPEditor>();
516 /* Link ip type & editor: */
517 pNewItemEditorFactory->registerEditor((QVariant::Type)iIpId, pIpEditorItemCreator);
518
519 /* Register port type: */
520 int iPortId = qRegisterMetaType<PortData>();
521 /* Register port editor: */
522 QStandardItemEditorCreator<PortEditor> *pPortEditorItemCreator = new QStandardItemEditorCreator<PortEditor>();
523 /* Link port type & editor: */
524 pNewItemEditorFactory->registerEditor((QVariant::Type)iPortId, pPortEditorItemCreator);
525
526 /* Set newly created item editor factory for table delegate: */
527 pStyledItemDelegate->setItemEditorFactory(pNewItemEditorFactory);
528 }
529 }
530
531 /* Retranslate dialog: */
532 retranslateUi();
533
534 /* Minimum Size: */
535 setMinimumSize(600, 300);
536}
537
538/* Port forwarding dialog destructor: */
539UIMachineSettingsPortForwardingDlg::~UIMachineSettingsPortForwardingDlg()
540{
541}
542
543const UIPortForwardingDataList& UIMachineSettingsPortForwardingDlg::rules() const
544{
545 return m_pModel->rules();
546}
547
548/* Add rule slot: */
549void UIMachineSettingsPortForwardingDlg::sltAddRule()
550{
551 m_pModel->addRule(QModelIndex());
552 m_pTableView->setFocus();
553 m_pTableView->setCurrentIndex(m_pModel->index(m_pModel->rowCount() - 1, 0));
554 sltCurrentChanged();
555 sltAdjustTable();
556}
557
558/* Copy rule slot: */
559void UIMachineSettingsPortForwardingDlg::sltCopyRule()
560{
561 m_pModel->addRule(m_pTableView->currentIndex());
562 m_pTableView->setFocus();
563 m_pTableView->setCurrentIndex(m_pModel->index(m_pModel->rowCount() - 1, 0));
564 sltCurrentChanged();
565 sltAdjustTable();
566}
567
568/* Del rule slot: */
569void UIMachineSettingsPortForwardingDlg::sltDelRule()
570{
571 m_pModel->delRule(m_pTableView->currentIndex());
572 m_pTableView->setFocus();
573 sltCurrentChanged();
574 sltAdjustTable();
575}
576
577/* Table data change handler: */
578void UIMachineSettingsPortForwardingDlg::sltTableDataChanged()
579{
580 fIsTableDataChanged = true;
581}
582
583/* Table index-change handler: */
584void UIMachineSettingsPortForwardingDlg::sltCurrentChanged()
585{
586 bool fTableFocused = m_pTableView->hasFocus();
587 bool fTableChildrenFocused = m_pTableView->findChildren<QWidget*>().contains(QApplication::focusWidget());
588 bool fTableOrChildrenFocused = fTableFocused || fTableChildrenFocused;
589 m_pCopyAction->setEnabled(m_pTableView->currentIndex().isValid() && fTableOrChildrenFocused);
590 m_pDelAction->setEnabled(m_pTableView->currentIndex().isValid() && fTableOrChildrenFocused);
591}
592
593/* Table context-menu handler: */
594void UIMachineSettingsPortForwardingDlg::sltShowTableContexMenu(const QPoint &pos)
595{
596 /* Prepare context menu: */
597 QMenu menu(m_pTableView);
598 /* If some index is currently selected: */
599 if (m_pTableView->indexAt(pos).isValid())
600 {
601 menu.addAction(m_pCopyAction);
602 menu.addAction(m_pDelAction);
603 }
604 /* If no valid index selected: */
605 else
606 {
607 menu.addAction(m_pAddAction);
608 }
609 menu.exec(m_pTableView->viewport()->mapToGlobal(pos));
610}
611
612/* Adjusts table column's sizes: */
613void UIMachineSettingsPortForwardingDlg::sltAdjustTable()
614{
615 m_pTableView->horizontalHeader()->setStretchLastSection(false);
616 /* If table is NOT empty: */
617 if (m_pModel->rowCount())
618 {
619 /* Resize table to contents size-hint and emit a spare place for first column: */
620 m_pTableView->resizeColumnsToContents();
621 uint uFullWidth = m_pTableView->viewport()->width();
622 for (uint u = 1; u < UIPortForwardingModel::UIPortForwardingDataType_Max; ++u)
623 uFullWidth -= m_pTableView->horizontalHeader()->sectionSize(u);
624 m_pTableView->horizontalHeader()->resizeSection(UIPortForwardingModel::UIPortForwardingDataType_Name, uFullWidth);
625 }
626 /* If table is empty: */
627 else
628 {
629 /* Resize table columns to be equal in size: */
630 uint uFullWidth = m_pTableView->viewport()->width();
631 for (uint u = 0; u < UIPortForwardingModel::UIPortForwardingDataType_Max; ++u)
632 m_pTableView->horizontalHeader()->resizeSection(u, uFullWidth / UIPortForwardingModel::UIPortForwardingDataType_Max);
633 }
634 m_pTableView->horizontalHeader()->setStretchLastSection(true);
635}
636
637void UIMachineSettingsPortForwardingDlg::accept()
638{
639 /* Validate table: */
640 for (int i = 0; i < m_pModel->rowCount(); ++i)
641 {
642 if (m_pModel->data(m_pModel->index(i, UIPortForwardingModel::UIPortForwardingDataType_HostPort), Qt::EditRole).value<PortData>().value() == 0 ||
643 m_pModel->data(m_pModel->index(i, UIPortForwardingModel::UIPortForwardingDataType_GuestPort), Qt::EditRole).value<PortData>().value() == 0)
644 {
645 vboxProblem().warnAboutIncorrectPort(this);
646 return;
647 }
648 }
649 /* Base class accept() slot: */
650 QIWithRetranslateUI<QIDialog>::accept();
651}
652
653void UIMachineSettingsPortForwardingDlg::reject()
654{
655 /* Check if table data was changed: */
656 if (fIsTableDataChanged && !vboxProblem().confirmCancelingPortForwardingDialog(this))
657 return;
658 /* Base class reject() slot: */
659 QIWithRetranslateUI<QIDialog>::reject();
660}
661
662/* UI Retranslation slot: */
663void UIMachineSettingsPortForwardingDlg::retranslateUi()
664{
665 /* Set window title: */
666 setWindowTitle(tr("Port Forwarding Rules"));
667
668 /* Table translations: */
669 m_pTableView->setWhatsThis(tr("This table contains a list of port forwarding rules."));
670
671 /* Set action's text: */
672 m_pAddAction->setText(tr("Insert new rule"));
673 m_pCopyAction->setText(tr("Copy selected rule"));
674 m_pDelAction->setText(tr("Delete selected rule"));
675 m_pAddAction->setWhatsThis(tr("This button adds new port forwarding rule."));
676 m_pDelAction->setWhatsThis(tr("This button deletes selected port forwarding rule."));
677 m_pAddAction->setToolTip(QString("%1 (%2)").arg(m_pAddAction->text()).arg(m_pAddAction->shortcut().toString()));
678 m_pDelAction->setToolTip(QString("%1 (%2)").arg(m_pDelAction->text()).arg(m_pDelAction->shortcut().toString()));
679}
680
681/* Extended event-handler: */
682bool UIMachineSettingsPortForwardingDlg::eventFilter(QObject *pObj, QEvent *pEvent)
683{
684 /* Process table: */
685 if (pObj == m_pTableView)
686 {
687 /* Switch for different event-types: */
688 switch (pEvent->type())
689 {
690 case QEvent::FocusIn:
691 case QEvent::FocusOut:
692 /* Update actions: */
693 sltCurrentChanged();
694 break;
695 case QEvent::Show:
696 case QEvent::Resize:
697 {
698 /* Instant table adjusting: */
699 sltAdjustTable();
700 /* Delayed table adjusting: */
701 QTimer::singleShot(0, this, SLOT(sltAdjustTable()));
702 break;
703 }
704 default:
705 break;
706 }
707 }
708 /* Continue with base-class processing: */
709 return QIWithRetranslateUI<QIDialog>::eventFilter(pObj, pEvent);
710}
711
712#include "UIMachineSettingsPortForwardingDlg.moc"
713
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use