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