cfgcustomservers.cpp
1 //------------------------------------------------------------------------------
2 // cfgcustomservers.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) 2009 "Zalewa" <zalewapl@gmail.com>
22 //------------------------------------------------------------------------------
23 #include "cfgcustomservers.h"
24 #include "configuration/doomseekerconfig.h"
25 #include "plugins/engineplugin.h"
26 #include "plugins/pluginloader.h"
27 #include "ui_cfgcustomservers.h"
28 #include <QHeaderView>
29 #include <QMessageBox>
30 #include <QStandardItemModel>
31 #include <QUrl>
32 
33 const // clear warnings
34 #include "unknownengine.xpm"
35 
36 DClass<CFGCustomServers> : public Ui::CFGCustomServers
37 {
38 public:
39  QStandardItemModel *model;
40 };
41 
42 DPointered(CFGCustomServers)
43 
44 CFGCustomServers::CFGCustomServers(QWidget *parent)
45  : ConfigPage(parent)
46 {
47  d->setupUi(this);
48 
49  connect(d->btnAdd, SIGNAL(clicked()), this, SLOT(add()));
50  connect(d->btnDisableSelected, SIGNAL(clicked()), this, SLOT(disableSelected()));
51  connect(d->btnEnableSelected, SIGNAL(clicked()), this, SLOT(enableSelected()));
52  connect(d->btnRemove, SIGNAL(clicked()), this, SLOT(remove()));
53  connect(d->btnSetEngine, SIGNAL(clicked()), this, SLOT(setEngine()));
54 
55  prepareEnginesComboBox();
56 }
57 
58 CFGCustomServers::~CFGCustomServers()
59 {
60 }
61 
62 void CFGCustomServers::add()
63 {
64  int pluginIndex = d->cboEngines->itemData(d->cboEngines->currentIndex()).toInt();
65  const EnginePlugin *plugin = gPlugins->info(pluginIndex);
66 
67  QString engineName = d->cboEngines->itemText(d->cboEngines->currentIndex());
68 
69  add(engineName, "", plugin->data()->defaultServerPort, true);
70 }
71 
72 void CFGCustomServers::add(const QString &engineName, const QString &host,
73  unsigned short port, bool enabled)
74 {
75  QList<QStandardItem *> record;
76 
77  auto engineItem = new QStandardItem();
78  setEngineOnItem(engineItem, engineName);
79 
80  QString portString = QString::number(port);
81 
82  record.append(engineItem);
83  record.append(new QStandardItem(host));
84  record.append(new QStandardItem(portString));
85 
86  auto enabledItem = new QStandardItem();
87  enabledItem->setCheckState(enabled ? Qt::Checked : Qt::Unchecked);
88  enabledItem->setCheckable(true);
89  enabledItem->setToolTip(tr("Toggle enabled state"));
90  record.append(enabledItem);
91 
92  d->model->appendRow(record);
93  d->tvServers->resizeRowsToContents();
94 }
95 
96 CFGCustomServers::CheckAndFixPorts CFGCustomServers::checkAndFixPorts(int firstRow, int lastRow)
97 {
98  CheckAndFixPorts returnValue = AllOk;
99  for (int rowIndex = firstRow; rowIndex <= lastRow; ++rowIndex)
100  {
101  if (!isPortCorrect(rowIndex))
102  {
103  returnValue = AtLeastOneFixed;
104 
105  setPortToDefault(rowIndex);
106  }
107  }
108 
109  return returnValue;
110 }
111 
112 void CFGCustomServers::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
113 {
114  const QString MESSAGE_TITLE = tr("Doomseeker - pinned servers");
115 
116  int leftmostColumn = topLeft.column();
117  int rightmostColumn = bottomRight.column();
118 
119  if (isPortColumnWithinRange(leftmostColumn, rightmostColumn))
120  {
121  switch (checkAndFixPorts(topLeft.row(), bottomRight.row()))
122  {
123  case AllOk:
124  // Ignore
125  break;
126 
127  case AtLeastOneFixed:
128  QMessageBox::warning(this, MESSAGE_TITLE, tr("Port must be within range 1 - 65535"));
129  break;
130 
131  default:
132  QMessageBox::warning(this, MESSAGE_TITLE, tr("Unimplemented behavior!"));
133  break;
134  }
135  }
136 }
137 
138 void CFGCustomServers::disableSelected()
139 {
140  setEnabledOnSelected(false);
141 }
142 
143 void CFGCustomServers::enableSelected()
144 {
145  setEnabledOnSelected(true);
146 }
147 
148 void CFGCustomServers::setEnabledOnSelected(bool enabled)
149 {
150  QItemSelectionModel *sel = d->tvServers->selectionModel();
151  QModelIndexList indexList = sel->selectedRows();
152 
153  QModelIndexList::iterator it;
154  for (it = indexList.begin(); it != indexList.end(); ++it)
155  {
156  QStandardItem *item = d->model->itemFromIndex(it->sibling(it->row(), EnabledIndex));
157  item->setCheckState(enabled ? Qt::Checked : Qt::Unchecked);
158  }
159 }
160 
161 const EnginePlugin *CFGCustomServers::getPluginInfoForRow(int rowIndex)
162 {
163  QStandardItem *itemEngine = d->model->item(rowIndex, EngineColumnIndex);
164  QString engineName = itemEngine->data().toString();
165  int pluginIndex = gPlugins->pluginIndexFromName(engineName);
166  return gPlugins->info(pluginIndex);
167 }
168 
169 bool CFGCustomServers::isPortColumnWithinRange(int leftmostColumnIndex, int rightmostColumnIndex)
170 {
171  return leftmostColumnIndex <= PortColumnIndex && rightmostColumnIndex >= PortColumnIndex;
172 }
173 
174 bool CFGCustomServers::isPortCorrect(int rowIndex)
175 {
176  const int MIN_PORT = 1;
177  const int MAX_PORT = 65535;
178 
179  QStandardItem *item = d->model->item(rowIndex, PortColumnIndex);
180  bool ok;
181  int port = item->text().toInt(&ok);
182 
183  return ok && port >= MIN_PORT && port <= MAX_PORT;
184 }
185 
186 void CFGCustomServers::prepareEnginesComboBox()
187 {
188  d->cboEngines->clear();
189 
190  for (unsigned i = 0; i < gPlugins->numPlugins(); ++i)
191  {
192  const EnginePlugin *plugin = gPlugins->info(i);
193  d->cboEngines->addItem(plugin->icon(), plugin->data()->name, i);
194  }
195 
196  if (d->cboEngines->count() > 0)
197  d->cboEngines->setCurrentIndex(0);
198 }
199 
200 void CFGCustomServers::prepareTable()
201 {
202  d->model = new QStandardItemModel(this);
203 
204  connect(d->model, SIGNAL(dataChanged(const QModelIndex&,const QModelIndex&)), this, SLOT(dataChanged(const QModelIndex&,const QModelIndex&)));
205 
206  QStringList labels;
207  labels << "" << tr("Host") << tr("Port") << "";
208  d->model->setHorizontalHeaderLabels(labels);
209 
210  d->tvServers->setModel(d->model);
211 
212  d->tvServers->setColumnWidth(EngineColumnIndex, 23);
213  d->tvServers->setColumnWidth(AddressColumnIndex, 180);
214  d->tvServers->setColumnWidth(PortColumnIndex, 60);
215  d->tvServers->setColumnWidth(EnabledIndex, 30);
216 
217  QList<ColumnIndices> fixedSizeColumns;
218  fixedSizeColumns << EngineColumnIndex << EnabledIndex;
219  for (ColumnIndices columnIdx : fixedSizeColumns)
220  d->tvServers->horizontalHeader()->setSectionResizeMode(columnIdx, QHeaderView::Fixed);
221  d->tvServers->horizontalHeader()->setHighlightSections(false);
222 
223  d->tvServers->verticalHeader()->hide();
224 }
225 
227 {
228  prepareTable();
229 
230  QList<CustomServerInfo> customServersList = gConfig.doomseeker.customServers.toList();
231  QList<CustomServerInfo>::iterator it;
232  for (it = customServersList.begin(); it != customServersList.end(); ++it)
233  add(it->engine, it->host, it->port, it->enabled);
234 }
235 
236 void CFGCustomServers::remove()
237 {
238  QItemSelectionModel *selModel = d->tvServers->selectionModel();
239  QModelIndexList indexList = selModel->selectedRows();
240  selModel->clear();
241 
242  QList<QStandardItem *> itemList;
243  for (int i = 0; i < indexList.count(); ++i)
244  itemList << d->model->item(indexList[i].row(), 0);
245 
246  for (int i = 0; i < itemList.count(); ++i)
247  {
248  QModelIndex index = d->model->indexFromItem(itemList[i]);
249  d->model->removeRow(index.row());
250  }
251 }
252 
254 {
255  gConfig.doomseeker.customServers = this->tableGetServers();
256 }
257 
258 void CFGCustomServers::setEngine()
259 {
260  QItemSelectionModel *sel = d->tvServers->selectionModel();
261  QModelIndexList indexList = sel->selectedRows();
262 
263  QModelIndexList::iterator it;
264  for (it = indexList.begin(); it != indexList.end(); ++it)
265  {
266  QStandardItem *item = d->model->itemFromIndex(*it);
267  QString engineName = d->cboEngines->itemText(d->cboEngines->currentIndex());
268  setEngineOnItem(item, engineName);
269  }
270 }
271 
272 void CFGCustomServers::setEngineOnItem(QStandardItem *item, const QString &engineName)
273 {
274  int engineId = gPlugins->pluginIndexFromName(engineName);
275 
276  item->setData(engineName);
277  item->setToolTip(engineName);
278  if (engineId >= 0)
279  {
280  const EnginePlugin *plugin = gPlugins->info(engineId);
281  item->setIcon(plugin->icon());
282  }
283  else
284  item->setIcon(QPixmap(unknownengine_xpm));
285 
286  item->setEditable(false);
287  item->setText("");
288 }
289 
290 void CFGCustomServers::setPortToDefault(int rowIndex)
291 {
292  const EnginePlugin *pluginInfo = getPluginInfoForRow(rowIndex);
293  QString defaultPort = QString::number(pluginInfo->data()->defaultServerPort);
294 
295  QStandardItem *itemPort = d->model->item(rowIndex, PortColumnIndex);
296  itemPort->setText(defaultPort);
297 }
298 
299 QVector<CustomServerInfo> CFGCustomServers::tableGetServers()
300 {
301  QVector<CustomServerInfo> servers;
302  for (int i = 0; i < d->model->rowCount(); ++i)
303  {
304  CustomServerInfo customServer;
305 
306  QStandardItem *item = d->model->item(i, EngineColumnIndex);
307  customServer.engine = item->data().toString();
308 
309  customServer.engineIndex = gPlugins->pluginIndexFromName(customServer.engine);
310 
311  item = d->model->item(i, AddressColumnIndex);
312  customServer.host = item->text();
313 
314  item = d->model->item(i, PortColumnIndex);
315  customServer.port = item->text().toUShort();
316 
317  item = d->model->item(i, EnabledIndex);
318  customServer.enabled = (item->checkState() == Qt::Checked);
319 
320  servers << customServer;
321  }
322 
323  return servers;
324 }