maplistselector.cpp
1 //------------------------------------------------------------------------------
2 // maplistselector.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) 2019 Pol Marcet Sardà <polmarcetsarda@gmail.com>
22 //------------------------------------------------------------------------------
23 #include "maplistselector.h"
24 
25 #include "commongui.h"
26 #include "modreader.h"
27 
28 #include <QFileInfo>
29 #include <QMenu>
30 #include <QScopedPointer>
31 #include <QSharedPointer>
32 #include <QTimer>
33 
34 MapEntry::MapEntry(const QString &name, const QString &originalFile, const bool &isIwad)
35 {
36  this->name = name;
37  this->originalFile = originalFile;
38  this->isIwad = isIwad;
39 }
40 
41 DClass<MapListSelector> : public Ui::MapListSelector
42 {
43 public:
44  QStringList paths;
45  QList<MapEntry> mapList;
46  QScopedPointer<QTimer> checkWadTimer;
47 };
48 
49 DPointeredNoCopy(MapListSelector)
50 
51 MapListSelector::MapListSelector(QWidget *parent) : QDialog(parent)
52 {
53  d->checkWadTimer.reset(new QTimer);
54 
55  d->setupUi(this);
57 
58  connect(d->checkWadTimer.data(), SIGNAL(timeout()), this, SLOT(performCheckStep()));
59 }
60 
61 MapListSelector::~MapListSelector()
62 {
63 }
64 
65 void MapListSelector::addPaths(const QStringList &paths)
66 {
67  d->paths << paths;
68  d->progressBar->setMaximum(d->progressBar->value() + paths.size());
69  setIfFinishedStateIsEnabled(false);
70  d->checkWadTimer->start(0);
71 }
72 
73 const QStringList MapListSelector::selectedMaps()
74 {
75  QStringList tempSelectedMapList;
76  for (int i = 0; i < d->listMapsWidget->count(); ++i)
77  {
78  QListWidgetItem *item = d->listMapsWidget->item(i);
79  if (item->checkState() == Qt::Checked)
80  tempSelectedMapList << item->text();
81  }
82  return tempSelectedMapList;
83 }
84 
85 void MapListSelector::performCheckStep()
86 {
87  if (d->paths.isEmpty())
88  {
89  d->checkWadTimer->stop();
90  setMapsOfCheckableList(d->mapList);
91  setIfFinishedStateIsEnabled(true);
92  return;
93  }
94  QString path = d->paths.takeFirst();
95  QSharedPointer<ModReader> modReader = ModReader::create(path);
96  if (!modReader.isNull() && modReader->load())
97  {
98  for (const QString &tempMap : modReader->getAllMaps())
99  {
100  addEntryToMapList(MapEntry(tempMap, QFile(path).fileName(), modReader->isIwad()));
101  }
102  }
103  d->progressBar->setValue(d->progressBar->value() + 1);
104 }
105 
106 void MapListSelector::addEntryToMapList(const MapEntry &newEntry)
107 {
108  bool equalEntryFound = false;
109  for (int i = 0; i < d->mapList.size(); ++i)
110  {
111  if (d->mapList[i].name == newEntry.name)
112  {
113  d->mapList.replace(i, newEntry);
114  equalEntryFound = true;
115  }
116  }
117  if (!equalEntryFound)
118  d->mapList.append(newEntry);
119 }
120 
121 void MapListSelector::setMapsOfCheckableList(const QList<MapEntry> &list)
122 {
123  d->listMapsWidget->clear();
124  for (const MapEntry &mapEntry : list)
125  {
126  auto item = new QListWidgetItem(mapEntry.name, d->listMapsWidget);
127  item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
128  item->setCheckState(Qt::Checked);
129  if (mapEntry.isIwad)
130  {
131  item->setBackground(Qt::lightGray);
132  item->setForeground(Qt::black);
133  }
134  item->setToolTip("File: " + mapEntry.originalFile);
135  }
136 }
137 
138 void MapListSelector::setIfFinishedStateIsEnabled(const bool &state)
139 {
140  d->btnAdd->setEnabled(state);
141  d->checkAll->setEnabled(state);
142  d->descriptionSelect->setVisible(state);
143  d->listMapsWidget->setVisible(state);
144  d->descriptionLoading->setVisible(!state);
145  d->progressBar->setVisible(!state);
146  adjustSize();
147 }
148 
149 void MapListSelector::accept()
150 {
151  done(Accepted);
152 }
153 
154 void MapListSelector::reject()
155 {
156  d->listMapsWidget->clear();
157  d->checkWadTimer->stop();
158  done(Rejected);
159 }
160 
161 void MapListSelector::selectAll()
162 {
163  Qt::CheckState checkState = d->checkAll->checkState();
164  for (int i = 0; i < d->listMapsWidget->count(); ++i)
165  d->listMapsWidget->item(i)->setCheckState(checkState);
166 }
167 
168 void MapListSelector::listItemChanged()
169 {
170  QStringList checkedMaps = selectedMaps();
171  if (checkedMaps.size() > 0 && checkedMaps.size() < d->listMapsWidget->count())
172  d->checkAll->setCheckState(Qt::PartiallyChecked);
173  else
174  {
175  d->checkAll->setCheckState((checkedMaps.size() == 0) ?
176  Qt::Unchecked : Qt::Checked);
177  }
178 }
179 
180 void MapListSelector::showContextMenu(const QPoint &pos)
181 {
182  QPoint globalPos = d->listMapsWidget->mapToGlobal(pos);
183 
184  QMenu myMenu;
185  myMenu.addAction(tr("Invert selection"), this, SLOT(invertSelection()));
186  myMenu.exec(globalPos);
187 }
188 
189 void MapListSelector::invertSelection()
190 {
191  for (int i = 0; i < d->listMapsWidget->count(); ++i)
192  {
193  QListWidgetItem *item = d->listMapsWidget->item(i);
194  if (item->isSelected())
195  item->setCheckState(item->checkState() == Qt::Unchecked ?
196  Qt::Checked : Qt::Unchecked);
197  }
198 }