23 #include "serverlist.h" 25 #include "configuration/doomseekerconfig.h" 26 #include "gui/remoteconsole.h" 27 #include "gui/models/serverlistcolumn.h" 28 #include "gui/models/serverlistmodel.h" 29 #include "gui/models/serverlistproxymodel.h" 30 #include "gui/widgets/serverlistcontextmenu.h" 31 #include "gui/widgets/serverlistview.h" 32 #include "refresher/refresher.h" 33 #include "serverapi/tooltips/servertooltip.h" 34 #include "serverapi/server.h" 35 #include "urlopener.h" 36 #include <QHeaderView> 37 #include <QMessageBox> 42 ServerList::ServerList(
ServerListView* serverTable, QWidget* pMainWindow)
43 : mainWindow(pMainWindow), model(NULL),
44 proxyModel(NULL), sortOrder(Qt::AscendingOrder),
45 sortIndex(-1), table(serverTable)
49 needsCleaning =
false;
54 ServerList::~ServerList()
56 saveColumnsWidthsSettings();
61 gConfig.serverFilter.info = filterInfo;
62 proxyModel->setFilterInfo(filterInfo);
66 bool ServerList::areColumnsWidthsSettingsChanged()
68 for(
int i = 0; i < NUM_SERVERLIST_COLUMNS; ++i)
70 if(ServerListColumns::columns[i].width != table->columnWidth(i))
79 void ServerList::cleanUp()
81 if (needsCleaning && mainWindow->isActiveWindow())
87 pModel->sortServers(sortIndex, sortOrder);
90 setCountryFlagsIfNotPresent();
91 needsCleaning =
false;
95 void ServerList::cleanUpForce()
101 void ServerList::clearAdditionalSorting()
103 proxyModel->clearAdditionalSorting();
106 void ServerList::columnHeaderClicked(
int index)
108 if (isSortingByColumn(index))
110 sortOrder = swappedCurrentSortOrder();
114 sortOrder = getColumnDefaultSortOrder(index);
120 QHeaderView* header = table->horizontalHeader();
121 header->setSortIndicator(sortIndex, sortOrder);
124 void ServerList::connectTableModelProxySlots()
126 QHeaderView* header = table->horizontalHeader();
127 this->connect(header, SIGNAL(sectionClicked(
int)), SLOT(columnHeaderClicked(
int)));
129 this->connect(table->selectionModel(),
130 SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
131 SLOT(itemSelected(QItemSelection)));
132 this->connect(table, SIGNAL(middleMouseClicked(QModelIndex, QPoint)),
133 SLOT(tableMiddleClicked(QModelIndex, QPoint)));
134 this->connect(table, SIGNAL(rightMouseClicked(QModelIndex, QPoint)),
135 SLOT(tableRightClicked(QModelIndex, QPoint)));
136 this->connect(table, SIGNAL(entered(QModelIndex)), SLOT(mouseEntered(QModelIndex)));
137 this->connect(table, SIGNAL(leftMouseDoubleClicked(QModelIndex, QPoint)),
138 SLOT(doubleClicked(QModelIndex)));
141 void ServerList::contextMenuAboutToHide()
143 sender()->deleteLater();
146 void ServerList::contextMenuTriggered(QAction* action)
149 ServerPtr server = contextMenu->server();
154 emit serverFilterModified(contextMenu->serverFilter());
157 switch (contextMenuResult)
163 case ServerListContextMenu::FindMissingWADs:
164 emit findMissingWADs(server);
167 case ServerListContextMenu::Join:
168 emit serverDoubleClicked(server);
171 case ServerListContextMenu::OpenRemoteConsole:
175 case ServerListContextMenu::OpenURL:
179 UrlOpener::instance()->open(server->webSite());
186 case ServerListContextMenu::Refresh:
190 case ServerListContextMenu::ShowJoinCommandLine:
191 emit displayServerJoinCommandLine(server);
194 case ServerListContextMenu::SortAdditionallyAscending:
195 sortAdditionally(contextMenu->modelIndex(), Qt::AscendingOrder);
198 case ServerListContextMenu::SortAdditionallyDescending:
199 sortAdditionally(contextMenu->modelIndex(), Qt::DescendingOrder);
202 case ServerListContextMenu::RemoveAdditionalSortingForColumn:
203 removeAdditionalSortingForColumn(contextMenu->modelIndex());
206 case ServerListContextMenu::ClearAdditionalSorting:
207 clearAdditionalSorting();
211 QMessageBox::warning(mainWindow, tr(
"Doomseeker - context menu warning"),
212 tr(
"Unhandled behavior in ServerList::contextMenuTriggered()"));
220 serverListModel->prepareHeaders();
221 return serverListModel;
227 this->connect(proxy, SIGNAL(additionalSortColumnsChanged()),
228 SLOT(updateHeaderTitles()));
229 this->connect(proxy, SIGNAL(additionalSortColumnsChanged()),
230 SLOT(saveAdditionalSortingConfig()));
231 proxy->setSourceModel(serverListModel);
232 proxy->setSortRole(ServerListModel::SLDT_SORT);
233 proxy->setSortCaseSensitivity(Qt::CaseInsensitive);
234 proxy->setFilterKeyColumn(IDServerName);
239 void ServerList::doubleClicked(
const QModelIndex& index)
241 emit serverDoubleClicked(serverFromIndex(index));
244 Qt::SortOrder ServerList::getColumnDefaultSortOrder(
int columnId)
247 return ServerListColumns::columns[columnId].defaultSortOrder;
250 bool ServerList::hasAtLeastOneServer()
const 252 return model->rowCount() > 0;
255 void ServerList::initCleanerTimer()
257 cleanerTimer.setInterval(200);
258 cleanerTimer.start();
259 connect(&cleanerTimer, SIGNAL( timeout() ),
this, SLOT ( cleanUp() ) );
262 bool ServerList::isAnyColumnSortedAdditionally()
const 264 return proxyModel->isAnyColumnSortedAdditionally();
267 bool ServerList::isSortingAdditionallyByColumn(
int column)
const 269 return proxyModel->isSortingAdditionallyByColumn(column);
272 bool ServerList::isSortingByColumn(
int columnIndex)
274 return sortIndex == columnIndex;
277 void ServerList::itemSelected(
const QItemSelection& selection)
279 QSortFilterProxyModel* pModel =
static_cast<QSortFilterProxyModel*
>(table->model());
280 QModelIndexList indexList = selection.indexes();
282 QList<ServerPtr> servers;
283 for(
int i = 0; i < indexList.count(); ++i)
285 QModelIndex realIndex = pModel->mapToSource(indexList[i]);
286 ServerPtr server = model->serverFromList(realIndex);
287 servers.append(server);
289 emit serversSelected(servers);
294 for (
int i = 0; i < model->rowCount(); ++i)
296 ServerPtr server = model->serverFromList(i);
297 server->lookupHost();
301 void ServerList::mouseEntered(
const QModelIndex& index)
303 QSortFilterProxyModel* pModel =
static_cast<QSortFilterProxyModel*
>(table->model());
304 QModelIndex realIndex = pModel->mapToSource(index);
305 ServerPtr server = model->serverFromList(realIndex);
311 switch(index.column())
314 tooltip = ServerTooltip::createPortToolTip(server);
318 tooltip = server->hostName(
true);
322 tooltip = ServerTooltip::createPlayersToolTip(server);
326 tooltip = ServerTooltip::createServerNameToolTip(server);
330 tooltip = ServerTooltip::createIwadToolTip(server);
334 tooltip = ServerTooltip::createPwadsToolTip(server);
342 QToolTip::showText(QCursor::pos(), tooltip, NULL);
345 void ServerList::prepareServerTable()
347 model = createModel();
348 proxyModel = createSortingProxy(model);
350 columnHeaderClicked(IDPlayers);
351 table->setModel(proxyModel);
352 table->setupTableProperties();
354 if(gConfig.doomseeker.serverListSortIndex >= 0)
356 sortIndex = gConfig.doomseeker.serverListSortIndex;
357 sortOrder =
static_cast<Qt::SortOrder
> (gConfig.doomseeker.serverListSortDirection);
360 connectTableModelProxySlots();
361 proxyModel->setAdditionalSortColumns(gConfig.doomseeker.additionalSortColumns());
364 void ServerList::redraw()
369 void ServerList::refreshSelected()
371 QItemSelectionModel* selectionModel = table->selectionModel();
372 QModelIndexList indexList = selectionModel->selectedRows();
374 for(
int i = 0; i < indexList.count(); ++i)
376 QModelIndex realIndex = proxyModel->mapToSource(indexList[i]);
377 gRefresher->registerServer(model->serverFromList(realIndex).data());
381 void ServerList::registerServer(ServerPtr server)
383 this->connect(server.data(), SIGNAL(updated(ServerPtr,
int)),
384 SLOT(onServerUpdated(ServerPtr)));
385 this->connect(server.data(), SIGNAL(begunRefreshing(ServerPtr)),
386 SLOT(onServerBegunRefreshing(ServerPtr)));
387 model->addServer(server);
388 emit serverRegistered(server);
391 void ServerList::removeServer(
const ServerPtr &server)
393 server->disconnect(
this);
394 model->removeServer(server);
395 emit serverDeregistered(server);
398 void ServerList::removeCustomServers()
400 foreach (ServerPtr server, model->customServers())
402 removeServer(server);
406 void ServerList::removeNonSpecialServers()
408 foreach (ServerPtr server, model->nonSpecialServers())
410 removeServer(server);
414 void ServerList::removeAdditionalSortingForColumn(
const QModelIndex &modelIndex)
416 proxyModel->removeAdditionalColumnSorting(modelIndex.column());
419 void ServerList::saveAdditionalSortingConfig()
421 gConfig.doomseeker.setAdditionalSortColumns(proxyModel->additionalSortColumns());
424 void ServerList::saveColumnsWidthsSettings()
426 gConfig.doomseeker.serverListColumnState = table->horizontalHeader()->saveState().toBase64();
427 gConfig.doomseeker.serverListSortIndex = sortIndex;
428 gConfig.doomseeker.serverListSortDirection = sortOrder;
431 QList<ServerPtr> ServerList::selectedServers()
const 433 QModelIndexList indexList = table->selectionModel()->selectedRows();
435 QList<ServerPtr> servers;
436 for(
int i = 0; i < indexList.count(); ++i)
438 QModelIndex realIndex = proxyModel->mapToSource(indexList[i]);
439 ServerPtr server = model->serverFromList(realIndex);
440 servers.append(server);
445 void ServerList::onServerBegunRefreshing(
const ServerPtr &server)
447 model->setRefreshing(server);
450 QList<ServerPtr> ServerList::servers()
const 452 return model->servers();
455 ServerPtr ServerList::serverFromIndex(
const QModelIndex &index)
457 QSortFilterProxyModel* pModel =
static_cast<QSortFilterProxyModel*
>(table->model());
458 QModelIndex indexReal = pModel->mapToSource(index);
459 return model->serverFromList(indexReal);
462 QList<ServerPtr> ServerList::serversForPlugin(
const EnginePlugin *plugin)
const 464 return model->serversForPlugin(plugin);
467 void ServerList::onServerUpdated(
const ServerPtr &server)
469 int rowIndex = model->findServerOnTheList(server.data());
472 rowIndex = model->updateServer(rowIndex, server);
476 rowIndex = model->addServer(server);
479 needsCleaning =
true;
480 emit serverInfoUpdated(server);
485 const bool FORCE =
true;
486 updateCountryFlags(!FORCE);
489 void ServerList::setGroupServersWithPlayersAtTop(
bool b)
491 proxyModel->setGroupServersWithPlayersAtTop(b);
494 void ServerList::sortAdditionally(
const QModelIndex &modelIndex, Qt::SortOrder order)
497 model->addAdditionalColumnSorting(modelIndex.column(), order);
500 Qt::SortOrder ServerList::swappedCurrentSortOrder()
502 return sortOrder == Qt::AscendingOrder ? Qt::DescendingOrder : Qt::AscendingOrder;
505 void ServerList::tableMiddleClicked(
const QModelIndex& index,
const QPoint& cursorPosition)
510 void ServerList::tableRightClicked(
const QModelIndex& index,
const QPoint& cursorPosition)
512 ServerPtr server = serverFromIndex(index);
515 proxyModel->filterInfo(), index,
this);
516 this->connect(contextMenu, SIGNAL(aboutToHide()), SLOT(contextMenuAboutToHide()));
517 this->connect(contextMenu, SIGNAL(triggered(QAction*)), SLOT(contextMenuTriggered(QAction*)));
519 QPoint displayPoint = table->viewport()->mapToGlobal(cursorPosition);
520 contextMenu->popup(displayPoint);
523 void ServerList::updateCountryFlags()
525 const bool FORCE =
true;
526 updateCountryFlags(FORCE);
529 void ServerList::updateCountryFlags(
bool force)
531 for (
int i = 0; i < model->rowCount(); ++i)
533 model->updateFlag(i, force);
537 void ServerList::updateHeaderTitles()
539 const QList<ColumnSort> &sortings = proxyModel->additionalSortColumns();
540 for (
int i = 0; i < ServerListColumnId::NUM_SERVERLIST_COLUMNS; ++i)
543 model->setHeaderData(i, Qt::Horizontal, QIcon(), Qt::DecorationRole);
545 QStringList labels = ServerListColumns::generateColumnHeaderLabels();
546 for (
int i = 0; i < sortings.size(); ++i)
549 labels[sort.columnId()] = QString(
"[%1] %2").arg(i + 1).arg(labels[sort.columnId()]);
550 QIcon icon = sort.order() == Qt::AscendingOrder ?
551 QIcon(
":/icons/ascending.png") :
552 QIcon(
":/icons/descending.png");
553 model->setHeaderData(sort.columnId(), Qt::Horizontal, icon, Qt::DecorationRole);
555 model->setHorizontalHeaderLabels(labels);
558 void ServerList::updateSearch(
const QString& search)
560 QRegExp pattern(QString(
"*") + search +
"*", Qt::CaseInsensitive, QRegExp::Wildcard);
561 proxyModel->setFilterRegExp(pattern);
Structure describing server filter.
void lookupHosts()
Looks up hosts for all available servers.
void setCountryFlagsIfNotPresent()
Sets country flags for servers that don't have flags present yet.