ViewVC Help
View File | Revision Log | View Changeset | Root Listing
root/Oni2/s10k/CommonUtils/util.cpp
(Generate patch)

Comparing s10k/CommonUtils/util.cpp (file contents):
Revision 1073 by s10k, Thu Oct 5 17:48:32 2017 UTC vs.
Revision 1095 by s10k, Sat Dec 30 14:30:28 2017 UTC

# Line 1 | Line 1
1 < /**
2 < * Copyright (C) 2017 - Fábio Bento (random-guy)
3 < *
4 < * This library is distributed under the MIT License. See notice at the end
5 < * of this file.
6 < *
7 < */
8 <
9 < #include "util.h"
10 <
11 < namespace Util{
12 <
13 < namespace FileSystem {
14 <
15 < QString normalizePath(QString path){
16 <    return path.replace("\\","/");
17 < }
18 <
19 < QString cutName(QString path){
20 <    return path.remove(0,path.lastIndexOf('/')).remove('"');
21 < }
22 <
23 < QString cutNameWithoutBackSlash(QString path){
24 <    return cutName(path).remove('/');
25 < }
26 <
27 < QString normalizeAndQuote(QString path){
28 <    return String::insertQuotes(normalizePath(path));
29 < }
30 <
31 < // Created from scratch
32 < bool copyDir(const QString &fromPath, QString toPath, const bool isRecursive){
33 <    QDir fromDir(fromPath);
34 <    QDir toDir(toPath);
35 <
36 <    if(!toDir.mkdir(fromDir.dirName())){ // create the folder in the destination
37 <        return false;
38 <    }
39 <
40 <    // Update toPath to include the folder from "fromPath"
41 <    toPath = toPath + "/" + fromDir.dirName();
42 <    toDir = QDir(toPath);
43 <
44 <    for(const QFileInfo &currFileInfo : fromDir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot)){
45 <
46 <        if(currFileInfo.isFile()){
47 <
48 <            QFile destFile(toPath + "/" + currFileInfo.fileName());
49 <
50 <            if(!QFile::copy(currFileInfo.absoluteFilePath(),toPath + "/" + currFileInfo.fileName())){
51 <                return false;
52 <            }
53 <        }
54 <        else if(isRecursive && currFileInfo.isDir() && currFileInfo.absoluteFilePath() != fromDir.absolutePath()){
55 <
56 <            if(!copyDir(currFileInfo.absoluteFilePath(), toPath, isRecursive)){
57 <                return false;
58 <            }
59 <        }
60 <    }
61 <
62 <    return true;
63 < }
64 <
65 < //Copied from here: http://stackoverflow.com/questions/2536524/copy-directory-using-qt (ty roop)
66 < bool rmDir(const QString &dirPath)
67 < {
68 <    QDir dir(dirPath);
69 <    if (!dir.exists())
70 <        return true;
71 <    foreach(const QFileInfo &info, dir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot)) {
72 <        if (info.isDir()) {
73 <            if (!rmDir(info.filePath()))
74 <                return false;
75 <        } else {
76 <            if (!dir.remove(info.fileName()))
77 <                return false;
78 <        }
79 <    }
80 <    QDir parentDir(QFileInfo(dirPath).path());
81 <    return parentDir.rmdir(QFileInfo(dirPath).fileName());
82 < }
83 <
84 < // Gets all files from a folder filtered by a given wildcard
85 < QStringList getFolderFilesByWildcard(const QString &entryFolder, const QString &wildcard, bool isRecursive){
86 <
87 <    QStringList filesFound; // result files with absolute path
88 <
89 <    QDirIterator it(entryFolder, QDir::Files, (isRecursive ? QDirIterator::Subdirectories : QDirIterator::NoIteratorFlags));
90 <
91 <    while (it.hasNext()){
92 <        filesFound << it.next();
93 <    }
94 <
95 <    return filterFilesByWildcard(filesFound, wildcard);
96 < }
97 <
98 < // Supports wildcards, and subdirectories with wildcard e.g.:
99 < // *.xml
100 < // /myXmls/*.xml
101 < //
102 < // online helper: https://regex101.com/
103 < QStringList filterFilesByWildcard(const QStringList &filePaths, const QString &wildcard){
104 <    QStringList resultFiles;
105 <    QString formattedWildcard;
106 <
107 <    if(wildcard.trimmed().isEmpty()){
108 <        return resultFiles;
109 <    }
110 <
111 <    formattedWildcard=normalizePath(wildcard); // Convert slashes to work in both mac and windows
112 <
113 <    // escape the string so '.' or '(' chars get correctly escaped
114 <    formattedWildcard = QRegularExpression::escape(formattedWildcard);
115 <
116 <    // replace * by the corresponding regex
117 <    formattedWildcard.replace("\\*",".*");
118 <
119 <    // replace ? by the corresponding regex
120 <    formattedWildcard.replace("\\?",".");
121 <
122 <    // if it doesn't start with any regex wildcard or a subdirectory slash, add a slash to beginning (so the file/folder matches at least the root folder)
123 <    // We use \\/ instead of / because it was escaped
124 <    if(!formattedWildcard.startsWith("\\/") && !formattedWildcard.startsWith(".*") && !formattedWildcard.startsWith(".")){
125 <        formattedWildcard = "\\/" + formattedWildcard;
126 <    }
127 <
128 <    // if it is a subdirectory add * to match
129 <    if(formattedWildcard.startsWith("\\/")){
130 <        formattedWildcard = ".*" + formattedWildcard;
131 <    }
132 <
133 <    formattedWildcard = "^" + formattedWildcard + "$"; // we want a full match (http://stackoverflow.com/a/5752852)
134 <
135 <    QRegularExpression regex(formattedWildcard);
136 <
137 <    for(const QString &currentFile : filePaths){
138 <
139 <        if(regex.match(currentFile).hasMatch()){
140 <            resultFiles << currentFile;
141 <        }
142 <
143 <    }
144 <
145 <    return resultFiles;
146 < }
147 <
148 < // Returns empty QString on failure.
149 < // Based from here: http://www.qtcentre.org/archive/index.php/t-35674.html (thanks wysota!)
150 < QString fileHash(const QString &fileName, QCryptographicHash::Algorithm hashAlgorithm)
151 < {
152 <
153 <    QCryptographicHash crypto(hashAlgorithm);
154 <    QFile file(fileName);
155 <    file.open(QFile::ReadOnly);
156 <    while(!file.atEnd()){
157 <        crypto.addData(file.read(8192));
158 <    }
159 <    QByteArray hash = crypto.result();
160 <
161 <    return QString(crypto.result().toHex());
162 <
163 < }
164 <
165 <
166 < /**
167 <  Gets application directory. In mac os gets the .app directory
168 <  **/
169 < QString getAppPath(){
170 < #ifdef Q_OS_MAC
171 <    QDir dir = QDir(QCoreApplication::applicationDirPath());
172 <    if(dir.absolutePath().contains(".app")){ // include bundle, but we don't want it
173 <        dir.cdUp();
174 <        dir.cdUp();
175 <        dir.cdUp();
176 <    }
177 <    return dir.absolutePath();
178 < #else
179 <    return  QDir::currentPath();
180 < #endif
181 < }
182 <
183 < bool backupFile(QString file){
184 <    return QFile::copy(file,file+".bak");
185 < }
186 <
187 < }
188 <
189 < namespace String {
190 <
191 < QString insertApostrophes(const QString &currString){
192 <    return "'"+currString+"'";
193 < }
194 <
195 < QString insertQuotes(const QString &currString){
196 <    return "\""+currString+"\"";
197 < }
198 <
199 < QString fullTrim(QString str) {
200 <
201 <    str = str.simplified(); //convert all invisible chars in normal whitespaces
202 <    str.replace( " ", "" );
203 <
204 <    return str;
205 < }
206 <
207 < QStringList substring(QString myString, QString separator, Qt::CaseSensitivity cs){
208 <    QStringList result = QStringList();
209 <    int currIdx=0, nextIdx=0;
210 <
211 <    while(true){
212 <        nextIdx=myString.indexOf(separator,currIdx,cs);
213 <        result << myString.mid(currIdx,nextIdx-currIdx);
214 <        if(nextIdx==-1) break;
215 <        currIdx=nextIdx+1;
216 <    }
217 <
218 <    return result;
219 < }
220 <
221 < QString normalizeDecimalSeparator(QString value){
222 <    return value.replace(',','.');
223 < }
224 <
225 < //Searches for the QString "toSearch" in the "myString" variable backward
226 < //Returns the index of the first match or -1 if not found
227 < int indexOfBackward(QString myString, QString toSearch, int from){
228 <    int myStringSize=myString.size();
229 <    int toSearchSize=toSearch.size();
230 <
231 <    if(from==-1){
232 <        from=myStringSize;
233 <    }
234 <
235 <    int i=from;
236 <
237 <    while(i>=0){
238 <        for(int j=toSearchSize-1; j>=0; j--){
239 <            i--;
240 <            if(myString.at(i)!=toSearch.at(j)){
241 <                break;
242 <            }
243 <            if(j==0){
244 <                return i;
245 <            }
246 <        }
247 <    }
248 <
249 <    return -1;
250 < }
251 <
252 < // no problem here with "temporary" cstr
253 < // https://stackoverflow.com/questions/1971183/when-does-c-allocate-deallocate-string-literals
254 < const char* boolToCstr(bool currentBoolean){
255 <    return currentBoolean ? "true" : "false";
256 < }
257 <
258 < }
259 <
260 < #ifdef QT_GUI_LIB
261 < namespace Dialogs {
262 <
263 < void showInfo(const QString &message){
264 <    QMessageBox msgBox;
265 <    msgBox.setIcon(QMessageBox::Information);
266 <    msgBox.setText(message);
267 <    msgBox.exec();
268 < }
269 <
270 < void showRichInfo(const QString &message){
271 <    QMessageBox msgBox;
272 <    msgBox.setTextFormat(Qt::RichText);
273 <    msgBox.setIcon(QMessageBox::Information);
274 <    msgBox.setText(message);
275 <    msgBox.exec();
276 < }
277 <
278 < void showWarning(const QString &message){
279 <    QMessageBox msgBox;
280 <    msgBox.setIcon(QMessageBox::Warning);
281 <    msgBox.setText(message);
282 <    msgBox.exec();
283 < }
284 <
285 < void showError(const QString &message){
286 <    QMessageBox msgBox;
287 <    msgBox.setIcon(QMessageBox::Critical);
288 <    msgBox.setText(message);
289 <    msgBox.exec();
290 < }
291 <
292 < void showRichError(const QString &message){
293 <    QMessageBox msgBox;
294 <    msgBox.setIcon(QMessageBox::Critical);
295 <    msgBox.setText(message);
296 <    msgBox.exec();
297 < }
298 <
299 < bool showQuestion(QWidget * parent, QString message, QMessageBox::StandardButton standardButton){
300 <    return QMessageBox::question (parent, "Are you sure?", message, QMessageBox::Yes | QMessageBox::No, standardButton)==QMessageBox::Yes;
301 < }
302 <
303 < QMessageBox::StandardButton showQuestionWithCancel(QWidget * parent, QString message, QMessageBox::StandardButton standardButton){
304 <    return QMessageBox::question (parent, "Are you sure?", message, QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, standardButton);
305 < }
306 <
307 < QStringList multipleDirSelection(const QString &title){
308 <    QFileDialog w;
309 <
310 <    // We need to use non native dialog, because native doesn't support multiple folder selection
311 <    w.setOption(QFileDialog::DontUseNativeDialog,true);
312 <
313 <    w.setFileMode(QFileDialog::DirectoryOnly);
314 <
315 <    w.setWindowTitle(title);
316 <
317 <    QTreeView *t = w.findChild<QTreeView*>();
318 <
319 <    if (t) {
320 <        t->setSelectionMode(QAbstractItemView::MultiSelection);
321 <    }
322 <
323 <    if(w.exec()){ //if accepted
324 <        return w.selectedFiles();
325 <    }
326 <    return QStringList(); //return empty
327 < }
328 <
329 < }
330 < #endif
331 <
332 < namespace Validation {
333 <
334 < // Check if any string in the list is empty
335 < bool checkEmptySpaces(QStringList toCheck){
336 <    foreach (QString current, toCheck){
337 <        if(current.trimmed().isEmpty()){
338 <            return true; //There are empty spaces
339 <        }
340 <    }
341 <    return false;
342 < }
343 <
344 < bool checkIfIntegers(QStringList toCheck){
345 <    foreach (QString current, toCheck){
346 <        if(!isStringInteger(current)){
347 <            return true; // Some aren't valid integers
348 <        }
349 <    }
350 <    return false;
351 < }
352 <
353 < bool checkIfDoubles(QStringList toCheck){
354 <    foreach (QString current, toCheck){
355 <        if(!isStringDouble(current)){
356 <            return true; // Some aren't valid doubles
357 <        }
358 <    }
359 <    return false;
360 < }
361 <
362 < bool isStringInteger(QString myString){
363 <    bool isNumber;
364 <
365 <    myString.toInt(&isNumber); //convert to int and see if it succeeds
366 <
367 <    return isNumber;
368 < }
369 <
370 < bool isStringDouble(QString myString){
371 <    bool isDouble;
372 <
373 <    myString.toDouble(&isDouble); //convert to double and see if it succeeds
374 <
375 <    return isDouble;
376 < }
377 <
378 < }
379 <
380 < namespace System {
381 <
382 < #ifdef QT_GUI_LIB
383 < // From here: http://stackoverflow.com/questions/17893328/qt-getting-the-screen-resolution-without-the-extended-monitor ty Chris
384 < QRect getScreenResolution(){
385 <    QDesktopWidget widget;
386 <    return widget.availableGeometry(widget.primaryScreen()); // or screenGeometry(), depending on your needs
387 < }
388 < #endif
389 <
390 < }
391 <
392 < #ifdef QT_GUI_LIB
393 < namespace TableWidget {
394 <
395 <
396 < void addRow(QTableWidget *myTable, QStringList &columns){
397 <    //Get actual number rows
398 <    int twSize=myTable->rowCount();
399 <
400 <    //increase the rows for the new item
401 <    myTable->setRowCount(twSize+1);
402 <
403 <    //Add to table and list to
404 <    for(int i=0; i<columns.size(); i++){
405 <        QTableWidgetItem *newColumn = new QTableWidgetItem(columns[i]);
406 <        myTable->setItem(twSize,i,newColumn);
407 <        // Add a tooltip with with the cell content
408 <        myTable->item(twSize,i)->setToolTip(myTable->item(twSize,i)->text());
409 <    }
410 <
411 < }
412 <
413 <
414 < QModelIndexList getSelectedRows(QTableWidget *myTable){
415 <    return myTable->selectionModel()->selectedRows();
416 < }
417 <
418 < QModelIndexList getCurrentRows(QTableWidget *myTable){
419 <
420 <    QModelIndexList oldSelection = getSelectedRows(myTable);
421 <
422 <    myTable->selectAll();
423 <
424 <    QModelIndexList allRows = getSelectedRows(myTable);
425 <
426 <    myTable->selectionModel()->clearSelection();
427 <
428 <    // Restore old selection
429 <    for(const QModelIndex &currentIndex : oldSelection){
430 <        myTable->selectionModel()->select(currentIndex, QItemSelectionModel::Select | QItemSelectionModel::SelectionFlag::Rows);
431 <    }
432 <
433 <    return allRows;
434 < }
435 <
436 < int getNumberSelectedRows(QTableWidget *myTable){
437 <    return getSelectedRows(myTable).size();
438 < }
439 <
440 < void clearContents(QTableWidget *myTable, const QString &nothingToClearMessage, const QString &questionToClear){
441 <
442 <    if(myTable->rowCount()==0){
443 <        Dialogs::showInfo(nothingToClearMessage);
444 <        return;
445 <    }
446 <
447 <    if(Dialogs::showQuestion(myTable, questionToClear)){
448 <        clearContentsNoPrompt(myTable);
449 <    }
450 <
451 < }
452 <
453 < void clearContentsNoPrompt(QTableWidget *myTable){
454 <    myTable->clearContents();
455 <    myTable->setRowCount(0);
456 < }
457 <
458 < // Adapted from here:
459 < // http://stackoverflow.com/questions/29176317/qtablewidget-checkbox-get-state-and-location
460 < void addCheckBox(QTableWidget *myTable, int row, int column, QCheckBox *checkbox){
461 <    if(checkbox == nullptr){
462 <        checkbox = new QCheckBox();
463 <    }
464 <
465 <    QWidget *auxLayoutWidget = new QWidget(myTable);
466 <
467 <    QHBoxLayout* checkBoxLayout = new QHBoxLayout();
468 <    checkBoxLayout->setContentsMargins(0,0,0,0);
469 <    checkBoxLayout->addWidget(checkbox);
470 <    checkBoxLayout->setAlignment(Qt::AlignCenter);
471 <    checkBoxLayout->setSpacing(0);
472 <    auxLayoutWidget->setLayout(checkBoxLayout);
473 <
474 <    myTable->setCellWidget(row, column, auxLayoutWidget);
475 < }
476 <
477 < // Adapted from here:
478 < // http://stackoverflow.com/questions/29176317/qtablewidget-checkbox-get-state-and-location
479 < QCheckBox* getCheckBoxFromCell(QTableWidget *myTable, int row, int column){
480 <    return dynamic_cast<QCheckBox*>(myTable->cellWidget(row, column)->findChild<QCheckBox *>());
481 < }
482 <
483 < // Adapted from here:
484 < // http://www.qtcentre.org/threads/3386-QTableWidget-move-row
485 < // Thanks jpn
486 < void swapRows(QTableWidget *myTable, const int indexSourceRow, const int indexDestinationRow, bool selectSwappedRow)
487 < {
488 <    // takes and returns the whole row
489 <    auto takeRow = [&myTable](int row) -> QList<QTableWidgetItem*>
490 <    {
491 <        QList<QTableWidgetItem*> rowItems;
492 <        for (int col = 0; col < myTable->columnCount(); ++col)
493 <        {
494 <            rowItems << myTable->takeItem(row, col);
495 <        }
496 <        return rowItems;
497 <    };
498 <
499 <    // sets the whole row
500 <    auto setRow = [&myTable](int row, const QList<QTableWidgetItem*>& rowItems)
501 <    {
502 <        for (int col = 0; col < myTable->columnCount(); ++col)
503 <        {
504 <            myTable->setItem(row, col, rowItems.at(col));
505 <        }
506 <    };
507 <
508 <    // take whole rows
509 <    QList<QTableWidgetItem*> sourceItems = takeRow(indexSourceRow);
510 <    QList<QTableWidgetItem*> destItems = takeRow(indexDestinationRow);
511 <
512 <    // set back in reverse order
513 <    setRow(indexSourceRow, destItems);
514 <    setRow(indexDestinationRow, sourceItems);
515 <
516 <    if(selectSwappedRow){
517 <        myTable->selectRow(indexDestinationRow);
518 <    }
519 < }
520 <
521 < void deleteSelectedRows(QTableWidget *myTable){
522 <    int size = myTable->selectionModel()->selectedRows().size();
523 <
524 <    for(int i=0; i<size; i++){
525 <        myTable->removeRow(myTable->selectionModel()->selectedRows().at(size-i-1).row());
526 <    }
527 < }
528 <
529 < }
530 < #endif
531 <
532 < #ifdef QT_GUI_LIB
533 < namespace StatusBar {
534 <
535 < void showError(QStatusBar * const statusBar, const QString &message){
536 <
537 <    QPalette myPalete = QPalette();
538 <    myPalete.setColor( QPalette::WindowText, QColor(255,0,0));
539 <    statusBar->setPalette( myPalete );
540 <    statusBar->showMessage(message,10000); //display by 10 seconds
541 <
542 < }
543 <
544 < void showSuccess(QStatusBar * const statusBar,const QString &message){
545 <
546 <    QPalette myPalete = QPalette();
547 <    myPalete.setColor( QPalette::WindowText, QColor(0,150,0));
548 <    statusBar->setPalette( myPalete );
549 <    statusBar->showMessage(message,10000); //display by 10 seconds
550 <
551 < }
552 <
553 < }
554 < #endif
555 <
556 < }
557 <
558 <
559 < /**
560 < * Copyright (c) 2017 - Fábio Bento (random-guy)
561 < *
562 < * Permission is hereby granted, free of charge, to any person
563 < * obtaining a copy of this software and associated documentation
564 < * files (the "Software"), to deal in the Software without
565 < * restriction, including without limitation the rights to use,
566 < * copy, modify, merge, publish, distribute, sublicense, and/or sell
567 < * copies of the Software, and to permit persons to whom the
568 < * Software is furnished to do so, subject to the following
569 < * conditions:
570 < *
571 < * The above copyright notice and this permission notice shall be
572 < * included in all copies or substantial portions of the Software.
573 < *
574 < * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
575 < * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
576 < * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
577 < * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
578 < * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
579 < * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
580 < * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
581 < * OTHER DEALINGS IN THE SOFTWARE.
582 < */
1 > /**
2 > * Copyright (C) 2017 - Fábio Bento (random-guy)
3 > *
4 > * This library is distributed under the MIT License. See notice at the end
5 > * of this file.
6 > *
7 > */
8 >
9 > #include "util.h"
10 >
11 > namespace Util{
12 >
13 > namespace FileSystem {
14 >
15 > QString normalizePath(QString path){
16 >    return path.replace("\\","/");
17 > }
18 >
19 > QString cutName(QString path){
20 >    return path.remove(0,path.lastIndexOf('/')).remove('"');
21 > }
22 >
23 > QString cutNameWithoutBackSlash(QString path){
24 >    return cutName(path).remove('/');
25 > }
26 >
27 > QString normalizeAndQuote(QString path){
28 >    return String::insertQuotes(normalizePath(path));
29 > }
30 >
31 > // Created from scratch
32 > bool copyDir(const QString &fromPath, QString toPath, const bool isRecursive){
33 >    QDir fromDir(fromPath);
34 >    QDir toDir(toPath);
35 >
36 >    if(!toDir.mkdir(fromDir.dirName())){ // create the folder in the destination
37 >        return false;
38 >    }
39 >
40 >    // Update toPath to include the folder from "fromPath"
41 >    toPath = toPath + "/" + fromDir.dirName();
42 >    toDir = QDir(toPath);
43 >
44 >    for(const QFileInfo &currFileInfo : fromDir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot)){
45 >
46 >        if(currFileInfo.isFile()){
47 >
48 >            QFile destFile(toPath + "/" + currFileInfo.fileName());
49 >
50 >            if(!QFile::copy(currFileInfo.absoluteFilePath(),toPath + "/" + currFileInfo.fileName())){
51 >                return false;
52 >            }
53 >        }
54 >        else if(isRecursive && currFileInfo.isDir() && currFileInfo.absoluteFilePath() != fromDir.absolutePath()){
55 >
56 >            if(!copyDir(currFileInfo.absoluteFilePath(), toPath, isRecursive)){
57 >                return false;
58 >            }
59 >        }
60 >    }
61 >
62 >    return true;
63 > }
64 >
65 > //Copied from here: http://stackoverflow.com/questions/2536524/copy-directory-using-qt (ty roop)
66 > bool rmDir(const QString &dirPath)
67 > {
68 >    QDir dir(dirPath);
69 >    if (!dir.exists())
70 >        return true;
71 >    for(const QFileInfo &info : dir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot)) {
72 >        if (info.isDir()) {
73 >            if (!rmDir(info.filePath()))
74 >                return false;
75 >        } else {
76 >            if (!dir.remove(info.fileName()))
77 >                return false;
78 >        }
79 >    }
80 >    QDir parentDir(QFileInfo(dirPath).path());
81 >    return parentDir.rmdir(QFileInfo(dirPath).fileName());
82 > }
83 >
84 > // Gets all files from a folder filtered by a given wildcard
85 > QStringList getFolderFilesByWildcard(const QString &entryFolder, const QString &wildcard, bool isRecursive){
86 >
87 >    QStringList filesFound; // result files with absolute path
88 >
89 >    QDirIterator it(entryFolder, QDir::Files, (isRecursive ? QDirIterator::Subdirectories : QDirIterator::NoIteratorFlags));
90 >
91 >    while (it.hasNext()){
92 >        filesFound << it.next();
93 >    }
94 >
95 >    return filterFilesByWildcard(filesFound, wildcard);
96 > }
97 >
98 > // Supports wildcards, and subdirectories with wildcard e.g.:
99 > // *.xml
100 > // /myXmls/*.xml
101 > //
102 > // online helper: https://regex101.com/
103 > QStringList filterFilesByWildcard(const QStringList &filePaths, const QString &wildcard){
104 >    QStringList resultFiles;
105 >    QString formattedWildcard;
106 >
107 >    if(wildcard.trimmed().isEmpty()){
108 >        return resultFiles;
109 >    }
110 >
111 >    formattedWildcard=normalizePath(wildcard); // Convert slashes to work in both mac and windows
112 >
113 >    // escape the string so '.' or '(' chars get correctly escaped
114 >    formattedWildcard = QRegularExpression::escape(formattedWildcard);
115 >
116 >    // replace * by the corresponding regex
117 >    formattedWildcard.replace("\\*",".*");
118 >
119 >    // replace ? by the corresponding regex
120 >    formattedWildcard.replace("\\?",".");
121 >
122 >    // if it doesn't start with any regex wildcard or a subdirectory slash, add a slash to beginning (so the file/folder matches at least the root folder)
123 >    // We use \\/ instead of / because it was escaped
124 >    if(!formattedWildcard.startsWith("\\/") && !formattedWildcard.startsWith(".*") && !formattedWildcard.startsWith(".")){
125 >        formattedWildcard = "\\/" + formattedWildcard;
126 >    }
127 >
128 >    // if it is a subdirectory add * to match
129 >    if(formattedWildcard.startsWith("\\/")){
130 >        formattedWildcard = ".*" + formattedWildcard;
131 >    }
132 >
133 >    formattedWildcard = "^" + formattedWildcard + "$"; // we want a full match (http://stackoverflow.com/a/5752852)
134 >
135 >    QRegularExpression regex(formattedWildcard);
136 >
137 >    for(const QString &currentFile : filePaths){
138 >
139 >        if(regex.match(currentFile).hasMatch()){
140 >            resultFiles << currentFile;
141 >        }
142 >
143 >    }
144 >
145 >    return resultFiles;
146 > }
147 >
148 > // Returns empty QString on failure.
149 > // Based from here: http://www.qtcentre.org/archive/index.php/t-35674.html (thanks wysota!)
150 > QString fileHash(const QString &fileName, QCryptographicHash::Algorithm hashAlgorithm)
151 > {
152 >
153 >    QCryptographicHash crypto(hashAlgorithm);
154 >    QFile file(fileName);
155 >    file.open(QFile::ReadOnly);
156 >    while(!file.atEnd()){
157 >        crypto.addData(file.read(8192));
158 >    }
159 >    QByteArray hash = crypto.result();
160 >
161 >    return QString(crypto.result().toHex());
162 >
163 > }
164 >
165 >
166 > /**
167 >  Gets application directory. In mac os gets the .app directory
168 >  **/
169 > QString getAppPath(){
170 > #ifdef Q_OS_MAC
171 >    QDir dir = QDir(QCoreApplication::applicationDirPath());
172 >    if(dir.absolutePath().contains(".app")){ // include bundle, but we don't want it
173 >        dir.cdUp();
174 >        dir.cdUp();
175 >        dir.cdUp();
176 >    }
177 >    return dir.absolutePath();
178 > #else
179 >    return  QDir::currentPath();
180 > #endif
181 > }
182 >
183 > bool backupFile(const QString &file, QString newFilename){
184 >        
185 >        if(newFilename.isEmpty()){
186 >                newFilename = file;
187 >        }
188 >        
189 >    return QFile::copy(file, newFilename+".bak");
190 > }
191 >
192 > }
193 >
194 > namespace String {
195 >
196 > QString insertApostrophes(const QString &currString){
197 >    return "'"+currString+"'";
198 > }
199 >
200 > QString insertQuotes(const QString &currString){
201 >    return "\""+currString+"\"";
202 > }
203 >
204 > QString fullTrim(QString str) {
205 >
206 >    str = str.simplified(); //convert all invisible chars in normal whitespaces
207 >    str.replace( " ", "" );
208 >
209 >    return str;
210 > }
211 >
212 > QStringList substring(QString myString, QString separator, Qt::CaseSensitivity cs){
213 >    QStringList result = QStringList();
214 >    int currIdx=0, nextIdx=0;
215 >
216 >    while(true){
217 >        nextIdx=myString.indexOf(separator,currIdx,cs);
218 >        result << myString.mid(currIdx,nextIdx-currIdx);
219 >        if(nextIdx==-1) break;
220 >        currIdx=nextIdx+1;
221 >    }
222 >
223 >    return result;
224 > }
225 >
226 > QString normalizeDecimalSeparator(QString value){
227 >    return value.replace(',','.');
228 > }
229 >
230 > //Searches for the QString "toSearch" in the "myString" variable backward
231 > //Returns the index of the first match or -1 if not found
232 > int indexOfBackward(QString myString, QString toSearch, int from){
233 >    int myStringSize=myString.size();
234 >    int toSearchSize=toSearch.size();
235 >
236 >    if(from==-1){
237 >        from=myStringSize;
238 >    }
239 >
240 >    int i=from;
241 >
242 >    while(i>=0){
243 >        for(int j=toSearchSize-1; j>=0; j--){
244 >            i--;
245 >            if(myString.at(i)!=toSearch.at(j)){
246 >                break;
247 >            }
248 >            if(j==0){
249 >                return i;
250 >            }
251 >        }
252 >    }
253 >
254 >    return -1;
255 > }
256 >
257 > // no problem here with "temporary" cstr
258 > // https://stackoverflow.com/questions/1971183/when-does-c-allocate-deallocate-string-literals
259 > const char* boolToCstr(bool currentBoolean){
260 >    return currentBoolean ? "true" : "false";
261 > }
262 >
263 > }
264 >
265 > #ifdef QT_GUI_LIB
266 > namespace Dialogs {
267 >
268 > void showInfo(const QString &message){
269 >    QMessageBox msgBox;
270 >    msgBox.setIcon(QMessageBox::Information);
271 >    msgBox.setText(message);
272 >    msgBox.exec();
273 > }
274 >
275 > void showRichInfo(const QString &message){
276 >    QMessageBox msgBox;
277 >    msgBox.setTextFormat(Qt::RichText);
278 >    msgBox.setIcon(QMessageBox::Information);
279 >    msgBox.setText(message);
280 >    msgBox.exec();
281 > }
282 >
283 > void showWarning(const QString &message){
284 >    QMessageBox msgBox;
285 >    msgBox.setIcon(QMessageBox::Warning);
286 >    msgBox.setText(message);
287 >    msgBox.exec();
288 > }
289 >
290 > void showError(const QString &message){
291 >    QMessageBox msgBox;
292 >    msgBox.setIcon(QMessageBox::Critical);
293 >    msgBox.setText(message);
294 >    msgBox.exec();
295 > }
296 >
297 > void showRichError(const QString &message){
298 >    QMessageBox msgBox;
299 >    msgBox.setIcon(QMessageBox::Critical);
300 >    msgBox.setText(message);
301 >    msgBox.exec();
302 > }
303 >
304 > bool showQuestion(QWidget * parent, QString message, QMessageBox::StandardButton standardButton){
305 >    return QMessageBox::question (parent, "Are you sure?", message, QMessageBox::Yes | QMessageBox::No, standardButton)==QMessageBox::Yes;
306 > }
307 >
308 > QMessageBox::StandardButton showQuestionWithCancel(QWidget * parent, QString message, QMessageBox::StandardButton standardButton){
309 >    return QMessageBox::question (parent, "Are you sure?", message, QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, standardButton);
310 > }
311 >
312 > QStringList multipleDirSelection(const QString &title){
313 >    QFileDialog w;
314 >
315 >    // We need to use non native dialog, because native doesn't support multiple folder selection
316 >    w.setOption(QFileDialog::DontUseNativeDialog,true);
317 >
318 >    w.setFileMode(QFileDialog::DirectoryOnly);
319 >
320 >    w.setWindowTitle(title);
321 >
322 >    QTreeView *t = w.findChild<QTreeView*>();
323 >
324 >    if (t) {
325 >        t->setSelectionMode(QAbstractItemView::MultiSelection);
326 >    }
327 >
328 >    if(w.exec()){ //if accepted
329 >        return w.selectedFiles();
330 >    }
331 >    return QStringList(); //return empty
332 > }
333 >
334 > }
335 > #endif
336 >
337 > namespace Validation {
338 >
339 > // Check if any string in the list is empty
340 > bool checkEmptySpaces(QStringList toCheck){
341 >    for (const QString &current : toCheck){
342 >        if(current.trimmed().isEmpty()){
343 >            return true; //There are empty spaces
344 >        }
345 >    }
346 >    return false;
347 > }
348 >
349 > bool checkIfIntegers(QStringList toCheck){
350 >    for (const QString &current : toCheck){
351 >        if(!isStringInteger(current)){
352 >            return true; // Some aren't valid integers
353 >        }
354 >    }
355 >    return false;
356 > }
357 >
358 > bool checkIfDoubles(QStringList toCheck){
359 >    for (const QString &current : toCheck){
360 >        if(!isStringDouble(current)){
361 >            return true; // Some aren't valid doubles
362 >        }
363 >    }
364 >    return false;
365 > }
366 >
367 > bool isStringInteger(QString myString){
368 >    bool isNumber;
369 >
370 >    myString.toInt(&isNumber); //convert to int and see if it succeeds
371 >
372 >    return isNumber;
373 > }
374 >
375 > bool isStringDouble(QString myString){
376 >    bool isDouble;
377 >
378 >    myString.toDouble(&isDouble); //convert to double and see if it succeeds
379 >
380 >    return isDouble;
381 > }
382 >
383 > }
384 >
385 > namespace System {
386 >
387 > #ifdef QT_GUI_LIB
388 > // From here: http://stackoverflow.com/questions/17893328/qt-getting-the-screen-resolution-without-the-extended-monitor ty Chris
389 > QRect getScreenResolution(){
390 >    QDesktopWidget widget;
391 >    return widget.availableGeometry(widget.primaryScreen()); // or screenGeometry(), depending on your needs
392 > }
393 > #endif
394 >
395 > }
396 >
397 > #ifdef QT_GUI_LIB
398 > namespace TableWidget {
399 >
400 >
401 > void addRow(QTableWidget *myTable, QStringList &columns){
402 >    //Get actual number rows
403 >    int twSize=myTable->rowCount();
404 >
405 >    //increase the rows for the new item
406 >    myTable->setRowCount(twSize+1);
407 >
408 >    //Add to table and list to
409 >    for(int i=0; i<columns.size(); i++){
410 >        QTableWidgetItem *newColumn = new QTableWidgetItem(columns[i]);
411 >        myTable->setItem(twSize,i,newColumn);
412 >        // Add a tooltip with with the cell content
413 >        myTable->item(twSize,i)->setToolTip(myTable->item(twSize,i)->text());
414 >    }
415 >
416 > }
417 >
418 >
419 > QModelIndexList getSelectedRows(QTableWidget *myTable){
420 >    return myTable->selectionModel()->selectedRows();
421 > }
422 >
423 > QModelIndexList getCurrentRows(QTableWidget *myTable){
424 >
425 >    QModelIndexList oldSelection = getSelectedRows(myTable);
426 >
427 >    myTable->selectAll();
428 >
429 >    QModelIndexList allRows = getSelectedRows(myTable);
430 >
431 >    myTable->selectionModel()->clearSelection();
432 >
433 >    // Restore old selection
434 >    for(const QModelIndex &currentIndex : oldSelection){
435 >        myTable->selectionModel()->select(currentIndex, QItemSelectionModel::Select | QItemSelectionModel::SelectionFlag::Rows);
436 >    }
437 >
438 >    return allRows;
439 > }
440 >
441 > int getNumberSelectedRows(QTableWidget *myTable){
442 >    return getSelectedRows(myTable).size();
443 > }
444 >
445 > void clearContents(QTableWidget *myTable, const QString &nothingToClearMessage, const QString &questionToClear){
446 >
447 >    if(myTable->rowCount()==0){
448 >        Dialogs::showInfo(nothingToClearMessage);
449 >        return;
450 >    }
451 >
452 >    if(Dialogs::showQuestion(myTable, questionToClear)){
453 >        clearContentsNoPrompt(myTable);
454 >    }
455 >
456 > }
457 >
458 > void clearContentsNoPrompt(QTableWidget *myTable){
459 >    myTable->clearContents();
460 >    myTable->setRowCount(0);
461 > }
462 >
463 > // Adapted from here:
464 > // http://stackoverflow.com/questions/29176317/qtablewidget-checkbox-get-state-and-location
465 > void addCheckBox(QTableWidget *myTable, int row, int column, QCheckBox *checkbox){
466 >    if(checkbox == nullptr){
467 >        checkbox = new QCheckBox();
468 >    }
469 >
470 >    QWidget *auxLayoutWidget = new QWidget(myTable);
471 >
472 >    QHBoxLayout* checkBoxLayout = new QHBoxLayout();
473 >    checkBoxLayout->setContentsMargins(0,0,0,0);
474 >    checkBoxLayout->addWidget(checkbox);
475 >    checkBoxLayout->setAlignment(Qt::AlignCenter);
476 >    checkBoxLayout->setSpacing(0);
477 >    auxLayoutWidget->setLayout(checkBoxLayout);
478 >
479 >    myTable->setCellWidget(row, column, auxLayoutWidget);
480 > }
481 >
482 > // Adapted from here:
483 > // http://stackoverflow.com/questions/29176317/qtablewidget-checkbox-get-state-and-location
484 > QCheckBox* getCheckBoxFromCell(QTableWidget *myTable, int row, int column){
485 >    return dynamic_cast<QCheckBox*>(myTable->cellWidget(row, column)->findChild<QCheckBox *>());
486 > }
487 >
488 > // Adapted from here:
489 > // http://www.qtcentre.org/threads/3386-QTableWidget-move-row
490 > // Thanks jpn
491 > void swapRows(QTableWidget *myTable, const int indexSourceRow, const int indexDestinationRow, bool selectSwappedRow)
492 > {
493 >    // takes and returns the whole row
494 >    auto takeRow = [&myTable](int row) -> QList<QTableWidgetItem*>
495 >    {
496 >        QList<QTableWidgetItem*> rowItems;
497 >        for (int col = 0; col < myTable->columnCount(); ++col)
498 >        {
499 >            rowItems << myTable->takeItem(row, col);
500 >        }
501 >        return rowItems;
502 >    };
503 >
504 >    // sets the whole row
505 >    auto setRow = [&myTable](int row, const QList<QTableWidgetItem*>& rowItems)
506 >    {
507 >        for (int col = 0; col < myTable->columnCount(); ++col)
508 >        {
509 >            myTable->setItem(row, col, rowItems.at(col));
510 >        }
511 >    };
512 >
513 >    // take whole rows
514 >    QList<QTableWidgetItem*> sourceItems = takeRow(indexSourceRow);
515 >    QList<QTableWidgetItem*> destItems = takeRow(indexDestinationRow);
516 >
517 >    // set back in reverse order
518 >    setRow(indexSourceRow, destItems);
519 >    setRow(indexDestinationRow, sourceItems);
520 >
521 >    if(selectSwappedRow){
522 >        myTable->selectRow(indexDestinationRow);
523 >    }
524 > }
525 >
526 > void deleteSelectedRows(QTableWidget *myTable){
527 >    int size = myTable->selectionModel()->selectedRows().size();
528 >
529 >    for(int i=0; i<size; i++){
530 >        myTable->removeRow(myTable->selectionModel()->selectedRows().at(size-i-1).row());
531 >    }
532 > }
533 >
534 > }
535 > #endif
536 >
537 > #ifdef QT_GUI_LIB
538 > namespace StatusBar {
539 >
540 > void showError(QStatusBar * const statusBar, const QString &message){
541 >
542 >    QPalette myPalete = QPalette();
543 >    myPalete.setColor( QPalette::WindowText, QColor(255,0,0));
544 >    statusBar->setPalette( myPalete );
545 >    statusBar->showMessage(message,10000); //display by 10 seconds
546 >
547 > }
548 >
549 > void showSuccess(QStatusBar * const statusBar,const QString &message){
550 >
551 >    QPalette myPalete = QPalette();
552 >    myPalete.setColor( QPalette::WindowText, QColor(0,150,0));
553 >    statusBar->setPalette( myPalete );
554 >    statusBar->showMessage(message,10000); //display by 10 seconds
555 >
556 > }
557 >
558 > }
559 > #endif
560 >
561 > }
562 >
563 >
564 > /**
565 > * Copyright (c) 2017 - Fábio Bento (random-guy)
566 > *
567 > * Permission is hereby granted, free of charge, to any person
568 > * obtaining a copy of this software and associated documentation
569 > * files (the "Software"), to deal in the Software without
570 > * restriction, including without limitation the rights to use,
571 > * copy, modify, merge, publish, distribute, sublicense, and/or sell
572 > * copies of the Software, and to permit persons to whom the
573 > * Software is furnished to do so, subject to the following
574 > * conditions:
575 > *
576 > * The above copyright notice and this permission notice shall be
577 > * included in all copies or substantial portions of the Software.
578 > *
579 > * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
580 > * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
581 > * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
582 > * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
583 > * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
584 > * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
585 > * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
586 > * OTHER DEALINGS IN THE SOFTWARE.
587 > */

Diff Legend

Removed lines
+ Added lines
< Changed lines (old)
> Changed lines (new)