| 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 ¤tFile : 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 ¤tIndex : 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 ¬hingToClearMessage, 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 ¤tFile : 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 ¤t : 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 ¤t : 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 ¤t : 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 ¤tIndex : 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 ¬hingToClearMessage, 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 | > | */ |