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