dockBuddiesList.cpp
1 //------------------------------------------------------------------------------
2 // dockBuddiesList.cpp
3 //------------------------------------------------------------------------------
4 //
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
9 //
10 // This program 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
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; 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 "Blzut3" <admin@maniacsvault.net>
22 //------------------------------------------------------------------------------
23 #include "dockBuddiesList.h"
24 #include "ui_addBuddyDlg.h"
25 #include "ui_dockBuddiesList.h"
26 #include "configuration/doomseekerconfig.h"
27 #include "serverapi/mastermanager.h"
28 #include "serverapi/playerslist.h"
29 #include "serverapi/server.h"
30 #include "patternlist.h"
31 #include "strings.h"
32 #include <QMenu>
33 #include <QMessageBox>
34 #include <QRegExp>
35 #include <QStandardItemModel>
36 
37 class BuddyLocationInfo
38 {
39 public:
40  BuddyLocationInfo(const Player &buddy, ServerPtr location);
41  ~BuddyLocationInfo();
42 
43  const Player &buddy() const;
44  ServerPtr location() const;
45 
46  bool operator==(const BuddyLocationInfo &other) const;
47 
48 private:
50 };
51 
52 DClass<DockBuddiesList> : public Ui::DockBuddiesList
53 {
54 public:
55  QList<BuddyLocationInfo> buddies;
56  QStandardItemModel *buddiesTableModel;
57  PatternList pBuddies;
58 };
59 
60 DPointered(DockBuddiesList)
61 
62 DockBuddiesList::DockBuddiesList(QWidget *parent)
63 : QDockWidget(parent), masterClient(NULL), save(false)
64 {
65  d->setupUi(this);
66  this->toggleViewAction()->setIcon(QIcon(":/icons/buddies.png"));
67 
68  // Set up the model
69  d->buddiesTableModel = new QStandardItemModel();
70 
71  // Not working yet.
72  QStringList columns;
73  columns << tr("ID");
74  columns << tr("Buddy");
75  columns << tr("Location");
76  d->buddiesTableModel->setHorizontalHeaderLabels(columns);
77 
78  d->buddiesTable->setModel(d->buddiesTableModel);
79  d->buddiesTable->setColumnHidden(0, true); // Hide the ID
80 
81  // Read config
82  const QVector<BuddyInfo>& buddies = gConfig.doomseeker.buddiesList;
83 
84  foreach (const BuddyInfo& buddy, buddies)
85  {
86  d->pBuddies << buddy.pattern;
87  d->patternsList->addItem(buddy.pattern.pattern());
88  }
89 
90  connect(d->addButton, SIGNAL( clicked() ), this, SLOT( addBuddy() ));
91  connect(d->buddiesTable, SIGNAL( doubleClicked(const QModelIndex &) ), this, SLOT( followBuddy(const QModelIndex &) ));
92  connect(d->deleteButton, SIGNAL( clicked() ), this, SLOT( deleteBuddy() ));
93  connect(d->patternsList, SIGNAL( customContextMenuRequested(const QPoint &) ), this, SLOT( patternsListContextMenu(const QPoint &) ));
94 }
95 
96 DockBuddiesList::~DockBuddiesList()
97 {
98  // See if we made any modification since modifying the setting will cause a
99  // write cycle.
100  if(!save)
101  return;
102 
103  gConfig.doomseeker.buddiesList.clear();
104  foreach (QRegExp pattern, d->pBuddies)
105  {
106  BuddyInfo buddyInfo;
107 
108  buddyInfo.pattern = pattern;
109  buddyInfo.patternType = pattern.patternSyntax() == QRegExp::Wildcard ? BuddyInfo::PT_BASIC : BuddyInfo::PT_ADVANCED;
110 
111  gConfig.doomseeker.buddiesList << buddyInfo;
112  }
113 }
114 
115 void DockBuddiesList::addBuddy()
116 {
117  AddBuddyDlg dlg;
118  int result = dlg.exec();
119  if(result != QDialog::Accepted)
120  return;
121 
122  QRegExp pattern(dlg.pattern(), Qt::CaseInsensitive, dlg.patternType() == BuddyInfo::PT_BASIC ? QRegExp::Wildcard : QRegExp::RegExp);
123 
124  if(pattern.isValid())
125  {
126  d->pBuddies << pattern;
127  scan(masterClient);
128  }
129 
130  d->patternsList->addItem(dlg.pattern());
131 
132  save = true;
133 }
134 
135 void DockBuddiesList::deleteBuddy()
136 {
137  // Do nothing if nothing is selected.
138  if(d->patternsList->selectionModel()->selectedIndexes().size() <= 0)
139  return;
140 
141  if(QMessageBox::warning(this, tr("Delete Buddy"), tr("Are you sure you want to delete this pattern?"), QMessageBox::Yes|QMessageBox::No, QMessageBox::Yes)
142  != QMessageBox::Yes)
143  return;
144 
145  QModelIndexList selection = d->patternsList->selectionModel()->selectedIndexes();
146  // We have to remove the bottom most row until they are all gone.
147  while(selection.size() > 0)
148  {
149  int largestIndex = 0;
150  for(int i = 1;i < selection.size();i++)
151  {
152  if(selection[i].row() > selection[largestIndex].row())
153  largestIndex = i;
154  }
155 
156  d->pBuddies.removeAt(selection[largestIndex].row());
157  delete d->patternsList->item(selection[largestIndex].row());
158  selection.removeAt(largestIndex); // remove index
159  }
160 
161  scan(masterClient);
162 
163  save = true;
164 }
165 
166 void DockBuddiesList::followBuddy(const QModelIndex &index)
167 {
168  // Folow the buddy into the server.
169  QString error;
170 
171  ServerPtr server = d->buddies[d->buddiesTableModel->item(index.row(), BLCID_ID)->data().toInt()].location();
172  emit joinServer(server);
173 }
174 
175 bool DockBuddiesList::hasBuddy(const ServerPtr &server)
176 {
177  foreach (const BuddyLocationInfo &location, d->buddies)
178  {
179  if (location.location() == server)
180  {
181  return true;
182  }
183  }
184  return false;
185 }
186 
187 void DockBuddiesList::patternsListContextMenu(const QPoint &pos) const
188 {
189  // First lets get the selection since that will determine the menu.
190  QModelIndexList selection = d->patternsList->selectionModel()->selectedIndexes();
191 
192  QMenu context;
193 
194  // Always have the add function.
195  QAction *addAction = context.addAction(tr("Add"));
196  connect(addAction, SIGNAL( triggered() ), this, SLOT( addBuddy() ));
197 
198  // if anything is selected allow the user to delete them.
199  if(selection.size() > 0)
200  {
201  QAction *deleteAction = context.addAction(tr("Delete"));
202  connect(deleteAction, SIGNAL( triggered() ), this, SLOT( deleteBuddy() ));
203  }
204 
205  // Finally show our menu.
206  context.exec(d->patternsList->mapToGlobal(pos));
207 }
208 
209 void DockBuddiesList::scan(const MasterManager *master)
210 {
211  if(master == NULL && masterClient == NULL)
212  return;
213  else if(master != masterClient && master != NULL)
214  { // If the master is new
215  masterClient = master;
216  }
217 
218  d->buddies.clear(); //empty list
219  foreach(ServerPtr server, masterClient->allServers())
220  {
221  if (!server->isKnown())
222  {
223  continue;
224  }
225  for(int i = 0; i < server->players().numClients(); ++i)
226  {
227  const Player player = server->player(i);
228  if (d->pBuddies.isExactMatchAny(player.nameColorTagsStripped()))
229  {
230  BuddyLocationInfo candidate(player, server);
231  if (!d->buddies.contains(candidate))
232  {
233  d->buddies << BuddyLocationInfo(player, server);
234  }
235  }
236  }
237  }
238 
239  // Populate list
240  d->buddiesTableModel->removeRows(0, d->buddiesTableModel->rowCount());
241  for(int i = 0;i < d->buddies.size();i++)
242  {
243  const BuddyLocationInfo &info = d->buddies[i];
244  QList<QStandardItem *> columns;
245 
246  for(int j = 0;j < HOW_MANY_BUDDIESLIST_COLUMNS;j++)
247  {
248  switch(j)
249  {
250  case BLCID_ID:
251  {
252  QStandardItem *item = new QStandardItem();
253  item->setData(i);
254  columns << item;
255  break;
256  }
257  case BLCID_BUDDY:
258  columns << new QStandardItem(info.buddy().nameColorTagsStripped());
259  break;
260  case BLCID_LOCATION:
261  columns << new QStandardItem(info.location()->name());
262  break;
263  default:
264  columns << new QStandardItem();
265  break;
266  }
267  }
268 
269  d->buddiesTableModel->appendRow(columns);
270  }
271 
272  // Fits rows to contents
273  d->buddiesTable->resizeRowsToContents();
274  emit scanCompleted();
275 }
276 
278 
279 DClass<AddBuddyDlg> : public Ui::AddBuddyDlg
280 {
281 };
282 
283 DPointered(AddBuddyDlg)
284 
285 AddBuddyDlg::AddBuddyDlg(QWidget *parent) : QDialog(parent)
286 {
287  d->setupUi(this);
288 
289  connect(d->buttonBox, SIGNAL( clicked(QAbstractButton *) ), this, SLOT( buttonBoxClicked(QAbstractButton *) ));
290 }
291 
292 AddBuddyDlg::~AddBuddyDlg()
293 {
294 }
295 
296 void AddBuddyDlg::buttonBoxClicked(QAbstractButton *button)
297 {
298  if(d->buttonBox->standardButton(button) == QDialogButtonBox::Ok)
299  {
300  if(patternType() == BuddyInfo::PT_ADVANCED)
301  {
302  QRegExp test(pattern());
303  if(!test.isValid())
304  {
305  QMessageBox::information(this, tr("Invalid Pattern"), tr("The pattern you have specified is not a valid regular expression."));
306  return;
307  }
308  }
309  accept();
310  }
311  else
312  reject();
313 }
314 
315 QString AddBuddyDlg::pattern() const
316 {
317  return d->patternBox->text();
318 }
319 
320 BuddyInfo::PatternType AddBuddyDlg::patternType() const
321 {
322  return d->basicPattern->isChecked() ? BuddyInfo::PT_BASIC : BuddyInfo::PT_ADVANCED;
323 }
324 
326 
327 DClass<BuddyLocationInfo>
328 {
329  public:
330  Player buddy;
331  ServerPtr server;
332 };
333 
334 DPointered(BuddyLocationInfo)
335 
336 BuddyLocationInfo::BuddyLocationInfo(const Player &buddy, ServerPtr location)
337 {
338  d->buddy = buddy;
339  d->server = location;
340 }
341 
342 BuddyLocationInfo::~BuddyLocationInfo()
343 {
344 }
345 
346 const Player &BuddyLocationInfo::buddy() const
347 {
348  return d->buddy;
349 }
350 
351 ServerPtr BuddyLocationInfo::location() const
352 {
353  return d->server;
354 }
355 
356 bool BuddyLocationInfo::operator==(const BuddyLocationInfo &other) const
357 {
358  return d->buddy == other.d->buddy
359  && d->server->address() == other.d->server->address()
360  && d->server->port() == other.d->server->port()
361  && d->server->plugin() == other.d->server->plugin();
362 }
QString nameColorTagsStripped() const
Definition: player.cpp:93
Data structure that holds information about players in a server.
Definition: player.h:37
Manager class for a number of MasterClient instances.
Definition: mastermanager.h:38