• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

IJHack / QtPass / 24610297828

18 Apr 2026 05:44PM UTC coverage: 21.908%. Remained the same
24610297828

push

github

web-flow
feat: add Spanish regional variants (#1040)

* fix: avoid deprecated invalidateFilter on Qt 6.5+

* feat: add Spanish regional variants

- Add Mexican Spanish (es_MX)
- Add Ecuadorian Spanish (es_EC)
- Add Argentine Spanish (es_AR)
- Add Uruguayan Spanish (es_UY)

All translations updated with regional verb conjugations for tuteo/voseo.

* fix: standardize verb forms across Spanish variants

- es_AR: change Instale→Instalá, Quiere→Querés, etc. (voseo)
- es_UY: change Instale→Instalá, Quiere→Querés, etc. (voseo)
- es_MX: change Instale→Instala, Quiere→Quieres, etc. (tuteo)
- es_EC: change Instale→Instala, Quiere→Quieres, etc. (tuteo)
- Fix 'edits' typo in es_MX → 'edites'

* fix: correct URL in es_AR (gnupg.org not gnug.org)

* fix: change formal to informal in es_MX (tuteo)

0 of 1 new or added line in 1 file covered. (0.0%)

10 existing lines in 2 files now uncovered.

1199 of 5473 relevant lines covered (21.91%)

8.58 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

53.78
/src/storemodel.cpp
1
// SPDX-FileCopyrightText: 2014 Anne Jan Brouwer
2
// SPDX-License-Identifier: GPL-3.0-or-later
3
#include "storemodel.h"
4
#include "qtpasssettings.h"
5

6
#include "util.h"
7
#include <QDebug>
8
#include <QFileSystemModel>
9
#include <QMessageBox>
10
#include <QMimeData>
11
#include <QRegularExpression>
12
#include <QtGlobal>
13
#include <utility>
14

15
auto operator<<(
1✔
16
    QDataStream &out,
17
    const dragAndDropInfoPasswordStore &dragAndDropInfoPasswordStore)
18
    -> QDataStream & {
19
  out << dragAndDropInfoPasswordStore.isDir
1✔
20
      << dragAndDropInfoPasswordStore.isFile
1✔
21
      << dragAndDropInfoPasswordStore.path;
1✔
22
  return out;
1✔
23
}
24

25
auto operator>>(QDataStream &in,
×
26
                dragAndDropInfoPasswordStore &dragAndDropInfoPasswordStore)
27
    -> QDataStream & {
28
  in >> dragAndDropInfoPasswordStore.isDir >>
×
29
      dragAndDropInfoPasswordStore.isFile >> dragAndDropInfoPasswordStore.path;
×
30
  return in;
×
31
}
32

33
/**
34
 * @brief StoreModel::StoreModel
35
 * SubClass of QSortFilterProxyModel via
36
 * http://www.qtcentre.org/threads/46471-QTreeView-Filter
37
 */
38
StoreModel::StoreModel() { fs = nullptr; }
19✔
39

40
/**
41
 * @brief StoreModel::filterAcceptsRow should row be shown, wrapper for
42
 * StoreModel::showThis method.
43
 * @param sourceRow
44
 * @param sourceParent
45
 * @return
46
 */
47
auto StoreModel::filterAcceptsRow(int sourceRow,
19✔
48
                                  const QModelIndex &sourceParent) const
49
    -> bool {
50
  QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
19✔
51
  return showThis(index);
19✔
52
}
53

54
/**
55
 * @brief StoreModel::showThis should a row be shown, based on our search
56
 * criteria.
57
 * @param index
58
 * @return
59
 */
60
auto StoreModel::showThis(const QModelIndex index) const -> bool {
44✔
61
  bool retVal = false;
62
  if (fs == nullptr) {
44✔
63
    return retVal;
64
  }
65
  // Gives you the info for number of childs with a parent
66
  if (sourceModel()->rowCount(index) > 0) {
43✔
67
    for (int nChild = 0; nChild < sourceModel()->rowCount(index); ++nChild) {
24✔
68
      QModelIndex childIndex = sourceModel()->index(nChild, 0, index);
24✔
69
      if (!childIndex.isValid()) {
70
        break;
71
      }
72
      retVal = showThis(childIndex);
24✔
73
      if (retVal) {
24✔
74
        break;
75
      }
76
    }
77
  } else {
78
    QModelIndex useIndex = sourceModel()->index(index.row(), 0, index.parent());
19✔
79
    QString path = fs->filePath(useIndex);
19✔
80
    path = QDir(store).relativeFilePath(path);
38✔
81
    if (path.startsWith(".git")) {
38✔
82
      return false;
83
    }
84
    path.replace(Util::endsWithGpg(), "");
18✔
85
    retVal = path.contains(filterRegularExpression());
18✔
86
  }
87
  return retVal;
88
}
89

90
/**
91
 * @brief StoreModel::setModelAndStore update the source model and store.
92
 * @param sourceModel
93
 * @param passStore
94
 */
95
void StoreModel::setModelAndStore(QFileSystemModel *sourceModel,
14✔
96
                                  QString passStore) {
97
  setSourceModel(sourceModel);
14✔
98
  fs = sourceModel;
14✔
99
  store = std::move(passStore);
100
}
14✔
101

102
void StoreModel::setStore(const QString &passStore) {
×
103
  store = passStore;
×
104
#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
NEW
105
  QSortFilterProxyModel::invalidateFilter();
×
106
#else
107
  invalidateFilter();
108
#endif
UNCOV
109
}
×
110

111
/**
112
 * @brief StoreModel::data don't show the .gpg at the end of a file.
113
 * @param index
114
 * @param role
115
 * @return
116
 */
117
auto StoreModel::data(const QModelIndex &index, int role) const -> QVariant {
2✔
118
  if (!index.isValid()) {
119
    return {};
120
  }
121

122
  QVariant initial_value;
123
  initial_value = QSortFilterProxyModel::data(index, role);
1✔
124

125
  if (role == Qt::DisplayRole) {
1✔
126
    QString name = initial_value.toString();
1✔
127
    name.replace(Util::endsWithGpg(), "");
1✔
128
    initial_value.setValue(name);
1✔
129
  }
130

131
  return initial_value;
1✔
132
}
1✔
133

134
/**
135
 * @brief StoreModel::supportedDropActions enable drop.
136
 * @return
137
 */
138
auto StoreModel::supportedDropActions() const -> Qt::DropActions {
1✔
139
  return Qt::CopyAction | Qt::MoveAction;
1✔
140
}
141

142
/**
143
 * @brief StoreModel::supportedDragActions enable drag.
144
 * @return
145
 */
146
auto StoreModel::supportedDragActions() const -> Qt::DropActions {
1✔
147
  return Qt::CopyAction | Qt::MoveAction;
1✔
148
}
149

150
/**
151
 * @brief StoreModel::flags
152
 * @param index
153
 * @return
154
 */
155
auto StoreModel::flags(const QModelIndex &index) const -> Qt::ItemFlags {
2✔
156
  Qt::ItemFlags defaultFlags = QSortFilterProxyModel::flags(index);
2✔
157

158
  if (index.isValid()) {
159
    return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | defaultFlags;
160
  }
161
  return Qt::ItemIsDropEnabled | defaultFlags;
1✔
162
}
163

164
/**
165
 * @brief StoreModel::mimeTypes
166
 * @return
167
 */
168
auto StoreModel::mimeTypes() const -> QStringList {
1✔
169
  QStringList types;
1✔
170
  types << "application/vnd+qtpass.dragAndDropInfoPasswordStore";
1✔
171
  return types;
1✔
172
}
173

174
/**
175
 * @brief StoreModel::mimeData
176
 * @param indexes
177
 * @return
178
 */
179
auto StoreModel::mimeData(const QModelIndexList &indexes) const -> QMimeData * {
1✔
180
  dragAndDropInfoPasswordStore info;
181

182
  QByteArray encodedData;
1✔
183
  // only use the first, otherwise we should enable multiselection
184
  QModelIndex index = indexes.at(0);
1✔
185
  if (index.isValid()) {
186
    QModelIndex useIndex = mapToSource(index);
1✔
187

188
    info.isDir = fs->fileInfo(useIndex).isDir();
1✔
189
    info.isFile = fs->fileInfo(useIndex).isFile();
1✔
190
    info.path = fs->fileInfo(useIndex).absoluteFilePath();
2✔
191
    QDataStream stream(&encodedData, QIODevice::WriteOnly);
1✔
192
    stream << info;
1✔
193
  }
1✔
194

195
  auto *mimeData = new QMimeData();
1✔
196
  mimeData->setData("application/vnd+qtpass.dragAndDropInfoPasswordStore",
2✔
197
                    encodedData);
198
  return mimeData;
1✔
199
}
200

201
/**
202
 * @brief StoreModel::canDropMimeData
203
 * @param data
204
 * @param action
205
 * @param row
206
 * @param column
207
 * @param parent
208
 * @return
209
 */
210
auto StoreModel::canDropMimeData(const QMimeData *data, Qt::DropAction action,
×
211
                                 int row, int column,
212
                                 const QModelIndex &parent) const -> bool {
213
#ifdef QT_DEBUG
214
  qDebug() << action << row;
215
#else
216
  Q_UNUSED(action)
217
  Q_UNUSED(row)
218
#endif
219

220
  QModelIndex useIndex =
221
      this->index(parent.row(), parent.column(), parent.parent());
×
222
  QByteArray encodedData =
223
      data->data("application/vnd+qtpass.dragAndDropInfoPasswordStore");
×
224
  QDataStream stream(&encodedData, QIODevice::ReadOnly);
×
225
  dragAndDropInfoPasswordStore info;
226
  stream >> info;
×
227
  if (!data->hasFormat("application/vnd+qtpass.dragAndDropInfoPasswordStore")) {
×
228
    return false;
229
  }
230

231
  if (column > 0) {
×
232
    return false;
233
  }
234

235
  // you can drop a folder on a folder
236
  if (fs->fileInfo(mapToSource(useIndex)).isDir() && info.isDir) {
×
237
    return true;
238
  }
239
  // you can drop a file on a folder
240
  if (fs->fileInfo(mapToSource(useIndex)).isDir() && info.isFile) {
×
241
    return true;
242
  }
243
  // you can drop a file on a file
244
  if (fs->fileInfo(mapToSource(useIndex)).isFile() && info.isFile) {
×
245
    return true;
246
  }
247

248
  return false;
249
}
×
250

251
/**
252
 * @brief StoreModel::dropMimeData
253
 * @param data
254
 * @param action
255
 * @param row
256
 * @param column
257
 * @param parent
258
 * @return
259
 */
260
auto StoreModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
×
261
                              int row, int column, const QModelIndex &parent)
262
    -> bool {
263
  if (!canDropMimeData(data, action, row, column, parent)) {
×
264
    return false;
265
  }
266

267
  if (action == Qt::IgnoreAction) {
×
268
    return true;
269
  }
270
  QByteArray encodedData =
271
      data->data("application/vnd+qtpass.dragAndDropInfoPasswordStore");
×
272

273
  QDataStream stream(&encodedData, QIODevice::ReadOnly);
×
274
  dragAndDropInfoPasswordStore info;
275
  stream >> info;
×
276
  QModelIndex destIndex =
277
      this->index(parent.row(), parent.column(), parent.parent());
×
278
  QFileInfo destFileinfo = fs->fileInfo(mapToSource(destIndex));
×
279
  QFileInfo srcFileInfo = QFileInfo(info.path);
×
280
  QString cleanedSrc = QDir::cleanPath(srcFileInfo.absoluteFilePath());
×
281
  QString cleanedDest = QDir::cleanPath(destFileinfo.absoluteFilePath());
×
282
  if (info.isDir) {
×
283
    // dropped dir onto dir
284
    if (destFileinfo.isDir()) {
×
285
      QDir destDir = QDir(cleanedDest).filePath(srcFileInfo.fileName());
×
286
      QString cleanedDestDir = QDir::cleanPath(destDir.absolutePath());
×
287
      if (action == Qt::MoveAction) {
×
288
        QtPassSettings::getPass()->Move(cleanedSrc, cleanedDestDir);
×
289
      } else if (action == Qt::CopyAction) {
×
290
        QtPassSettings::getPass()->Copy(cleanedSrc, cleanedDestDir);
×
291
      }
292
    }
×
293
  } else if (info.isFile) {
×
294
    // dropped file onto a directory
295
    if (destFileinfo.isDir()) {
×
296
      if (action == Qt::MoveAction) {
×
297
        QtPassSettings::getPass()->Move(cleanedSrc, cleanedDest);
×
298
      } else if (action == Qt::CopyAction) {
×
299
        QtPassSettings::getPass()->Copy(cleanedSrc, cleanedDest);
×
300
      }
301
    } else if (destFileinfo.isFile()) {
×
302
      // dropped file onto a file
303
      int answer = QMessageBox::question(
×
304
          nullptr, tr("force overwrite?"),
×
305
          tr("overwrite %1 with %2?").arg(cleanedDest, cleanedSrc),
×
306
          QMessageBox::Yes | QMessageBox::No);
307
      bool force = answer == QMessageBox::Yes;
×
308
      if (action == Qt::MoveAction) {
×
309
        QtPassSettings::getPass()->Move(cleanedSrc, cleanedDest, force);
×
310
      } else if (action == Qt::CopyAction) {
×
311
        QtPassSettings::getPass()->Copy(cleanedSrc, cleanedDest, force);
×
312
      }
313
    }
314
  }
315
  return true;
316
}
×
317

318
/**
319
 * @brief StoreModel::lessThan
320
 * @param source_left
321
 * @param source_right
322
 * @return
323
 */
324
auto StoreModel::lessThan(const QModelIndex &source_left,
2✔
325
                          const QModelIndex &source_right) const -> bool {
326
/* matches logic in QFileSystemModelSorter::compareNodes() */
327
#ifndef Q_OS_MAC
328
  if (fs && (source_left.column() == 0 || source_left.column() == 1)) {
2✔
329
    bool leftD = fs->isDir(source_left);
2✔
330
    bool rightD = fs->isDir(source_right);
2✔
331

332
    if (leftD ^ rightD) {
2✔
333
      return leftD;
334
    }
335
  }
336
#endif
337

338
  return QSortFilterProxyModel::lessThan(source_left, source_right);
1✔
339
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc