cfgfilepaths.cpp
1 //------------------------------------------------------------------------------
2 // cfgfilepaths.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 "cfgfilepaths.h"
24 #include "configuration/doomseekerconfig.h"
25 #include "pathfinder/filesearchpath.h"
26 #include "ui_cfgfilepaths.h"
27 #include <QFileDialog>
28 
29 static const int COL_PATH = 0;
30 static const int COL_RECURSE = 1;
31 static const int NUM_COLS = 2;
32 
33 DClass<CFGFilePaths> : public Ui::CFGFilePaths
34 {
35 };
36 
37 DPointered(CFGFilePaths)
38 
39 CFGFilePaths::CFGFilePaths(QWidget *parent)
40  : ConfigPage(parent)
41 {
42  d->setupUi(this);
43 
44  QStringList labels;
45  labels << CFGFilePaths::tr("Path") << CFGFilePaths::tr("Recurse");
46  d->tblFilePaths->setColumnCount(NUM_COLS);
47  d->tblFilePaths->setHorizontalHeaderLabels(labels);
48 
49  QHeaderView *header = d->tblFilePaths->horizontalHeader();
50  header->setSectionResizeMode(COL_PATH, QHeaderView::Stretch);
51  header->setSectionResizeMode(COL_RECURSE, QHeaderView::ResizeToContents);
52 
53  connect(d->btnAddWadPath, SIGNAL(clicked()), this, SLOT(btnAddWadPath_Click()));
54  connect(d->btnRemoveWadPath, SIGNAL(clicked()), this, SLOT(btnRemoveWadPath_Click()));
55  this->connect(d->tblFilePaths->itemDelegate(),
56  SIGNAL(closeEditor(QWidget*,QAbstractItemDelegate::EndEditHint)),
57  SIGNAL(validationRequested()));
58  d->tblFilePaths->connect(d->tblFilePaths,
59  &TableWidgetReorderable::rowsReordered,
60  &QTableWidget::resizeRowsToContents);
61 }
62 
63 CFGFilePaths::~CFGFilePaths()
64 {
65 }
66 
67 void CFGFilePaths::addPath(const FileSearchPath &fileSearchPath)
68 {
69  if (fileSearchPath.isValid())
70  return;
71 
72  if (!isPathAlreadyDefined(fileSearchPath.path()))
73  {
74  d->tblFilePaths->setSortingEnabled(false);
75  int newRow = d->tblFilePaths->rowCount();
76  d->tblFilePaths->insertRow(newRow);
77  auto path = new QTableWidgetItem(fileSearchPath.path());
78  path->setData(Qt::ToolTipRole, fileSearchPath.path());
79  auto recurse = new QTableWidgetItem();
80  recurse->setCheckState(fileSearchPath.isRecursive() ? Qt::Checked : Qt::Unchecked);
81  recurse->setData(Qt::TextAlignmentRole, Qt::AlignCenter);
82 
83  d->tblFilePaths->setItem(newRow, COL_PATH, path);
84  d->tblFilePaths->setItem(newRow, COL_RECURSE, recurse);
85  d->tblFilePaths->resizeRowsToContents();
86  d->tblFilePaths->setSortingEnabled(true);
87  }
88 }
89 
90 void CFGFilePaths::btnAddWadPath_Click()
91 {
92  QString strDir = QFileDialog::getExistingDirectory(this, tr("Doomseeker - Add wad path"));
93  addPath(strDir);
94  emit validationRequested();
95 }
96 
97 void CFGFilePaths::btnRemoveWadPath_Click()
98 {
99  QSet<int> uniqueRows;
100  for (auto *item : d->tblFilePaths->selectedItems())
101  uniqueRows.insert(item->row());
102  QList<int> rows = uniqueRows.values();
103  // Reverse the order of rows.
104  std::sort(rows.begin(), rows.end(), [](int a, int b) { return b < a; });
105  for (int row : rows)
106  d->tblFilePaths->removeRow(row);
107  emit validationRequested();
108 }
109 
110 QIcon CFGFilePaths::icon() const
111 {
112  return QApplication::style()->standardIcon(QStyle::SP_DirOpenIcon);
113 }
114 
115 bool CFGFilePaths::isPathAlreadyDefined(const QString &path)
116 {
117  Qt::CaseSensitivity caseSensitivity;
118 
119  #ifdef Q_OS_WIN32
120  caseSensitivity = Qt::CaseInsensitive;
121  #else
122  caseSensitivity = Qt::CaseSensitive;
123  #endif
124 
125  for (int i = 0; i < d->tblFilePaths->rowCount(); ++i)
126  {
127  QTableWidgetItem *item = d->tblFilePaths->item(i, COL_PATH);
128  QString dir = item->text();
129 
130  if (dir.compare(path, caseSensitivity) == 0)
131  return true;
132  }
133 
134  return false;
135 }
136 
138 {
139  const QList<FileSearchPath> &wadPaths = gConfig.doomseeker.wadPaths;
140  for (int i = 0; i < wadPaths.count(); ++i)
141  addPath(wadPaths[i]);
142 
143  d->cbTellMeWhereAreMyWads->setChecked(gConfig.doomseeker.bTellMeWhereAreTheWADsWhenIHoverCursorOverWADSColumn);
144  d->cbCheckTheIntegrityOfWads->setChecked(gConfig.doomseeker.bCheckTheIntegrityOfWads);
145 }
146 
148 {
149  QList<FileSearchPath> wadPaths;
150 
151  for (int i = 0; i < d->tblFilePaths->rowCount(); ++i)
152  {
153  QTableWidgetItem *itemPath = d->tblFilePaths->item(i, COL_PATH);
154  QTableWidgetItem *itemRecurse = d->tblFilePaths->item(i, COL_RECURSE);
155  FileSearchPath fileSearchPath(itemPath->text());
156  fileSearchPath.setRecursive(itemRecurse->checkState() == Qt::Checked);
157  wadPaths << fileSearchPath;
158  }
159 
160  gConfig.doomseeker.wadPaths = wadPaths;
161  gConfig.doomseeker.bTellMeWhereAreTheWADsWhenIHoverCursorOverWADSColumn = d->cbTellMeWhereAreMyWads->isChecked();
162  gConfig.doomseeker.bCheckTheIntegrityOfWads = d->cbCheckTheIntegrityOfWads->isChecked();
163 }
164 
166 {
167  bool allPathsValid = true;
168  for (int i = 0; i < d->tblFilePaths->rowCount(); ++i)
169  {
170  QTableWidgetItem *itemPath = d->tblFilePaths->item(i, COL_PATH);
171 
172  QString validationError = validatePath(itemPath->text());
173  bool valid = validationError.isEmpty();
174  allPathsValid = allPathsValid && valid;
175 
176  itemPath->setIcon(valid ? QIcon() : QIcon(":/icons/exclamation_16.png"));
177  itemPath->setToolTip(validationError);
178  }
179  return allPathsValid ? VALIDATION_OK : VALIDATION_ERROR;
180 }
181 
182 QString CFGFilePaths::validatePath(const QString &path) const
183 {
184  if (path.trimmed().isEmpty())
185  return tr("No path specified.");
186 
187  QFileInfo fileInfo(path.trimmed());
188  if (!fileInfo.exists())
189  return tr("Path doesn't exist.");
190 
191  if (!fileInfo.isDir())
192  return tr("Path is not a directory.");
193 
194  return QString();
195 }