| 1 | /** | 
 
 
 
 
 | 2 | * Copyright (C) 2017 - 2018 Fábio Bento (fabiobento512) | 
 
 
 
 
 | 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, const bool richText){ | 
 
 
 
 
 | 269 | QMessageBox msgBox; | 
 
 
 
 
 | 270 | if(richText){ | 
 
 
 
 
 | 271 | msgBox.setTextFormat(Qt::RichText); | 
 
 
 
 
 | 272 | } | 
 
 
 
 
 | 273 | msgBox.setIcon(QMessageBox::Information); | 
 
 
 
 
 | 274 | msgBox.setText(message); | 
 
 
 
 
 | 275 | msgBox.exec(); | 
 
 
 
 
 | 276 | } | 
 
 
 
 
 | 277 |  | 
 
 
 
 
 | 278 | void showWarning(const QString &message, const bool richText){ | 
 
 
 
 
 | 279 | QMessageBox msgBox; | 
 
 
 
 
 | 280 | if(richText){ | 
 
 
 
 
 | 281 | msgBox.setTextFormat(Qt::RichText); | 
 
 
 
 
 | 282 | } | 
 
 
 
 
 | 283 | msgBox.setIcon(QMessageBox::Warning); | 
 
 
 
 
 | 284 | msgBox.setText(message); | 
 
 
 
 
 | 285 | msgBox.exec(); | 
 
 
 
 
 | 286 | } | 
 
 
 
 
 | 287 |  | 
 
 
 
 
 | 288 | void showError(const QString &message, const bool richText){ | 
 
 
 
 
 | 289 | QMessageBox msgBox; | 
 
 
 
 
 | 290 | if(richText){ | 
 
 
 
 
 | 291 | msgBox.setTextFormat(Qt::RichText); | 
 
 
 
 
 | 292 | } | 
 
 
 
 
 | 293 | msgBox.setIcon(QMessageBox::Critical); | 
 
 
 
 
 | 294 | msgBox.setText(message); | 
 
 
 
 
 | 295 | msgBox.exec(); | 
 
 
 
 
 | 296 | } | 
 
 
 
 
 | 297 |  | 
 
 
 
 
 | 298 | bool showQuestion(QWidget * parent, QString message, QMessageBox::StandardButton standardButton){ | 
 
 
 
 
 | 299 | return QMessageBox::question (parent, "Are you sure?", message, QMessageBox::Yes | QMessageBox::No, standardButton)==QMessageBox::Yes; | 
 
 
 
 
 | 300 | } | 
 
 
 
 
 | 301 |  | 
 
 
 
 
 | 302 | QMessageBox::StandardButton showQuestionWithCancel(QWidget * parent, QString message, QMessageBox::StandardButton standardButton){ | 
 
 
 
 
 | 303 | return QMessageBox::question (parent, "Are you sure?", message, QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, standardButton); | 
 
 
 
 
 | 304 | } | 
 
 
 
 
 | 305 |  | 
 
 
 
 
 | 306 | QStringList multipleDirSelection(const QString &title){ | 
 
 
 
 
 | 307 | QFileDialog w; | 
 
 
 
 
 | 308 |  | 
 
 
 
 
 | 309 | // We need to use non native dialog, because native doesn't support multiple folder selection | 
 
 
 
 
 | 310 | w.setOption(QFileDialog::DontUseNativeDialog,true); | 
 
 
 
 
 | 311 |  | 
 
 
 
 
 | 312 | w.setFileMode(QFileDialog::DirectoryOnly); | 
 
 
 
 
 | 313 |  | 
 
 
 
 
 | 314 | w.setWindowTitle(title); | 
 
 
 
 
 | 315 |  | 
 
 
 
 
 | 316 | QTreeView *t = w.findChild<QTreeView*>(); | 
 
 
 
 
 | 317 |  | 
 
 
 
 
 | 318 | if (t) { | 
 
 
 
 
 | 319 | t->setSelectionMode(QAbstractItemView::MultiSelection); | 
 
 
 
 
 | 320 | } | 
 
 
 
 
 | 321 |  | 
 
 
 
 
 | 322 | if(w.exec()){ //if accepted | 
 
 
 
 
 | 323 | return w.selectedFiles(); | 
 
 
 
 
 | 324 | } | 
 
 
 
 
 | 325 | return QStringList(); //return empty | 
 
 
 
 
 | 326 | } | 
 
 
 
 
 | 327 |  | 
 
 
 
 
 | 328 | } | 
 
 
 
 
 | 329 | #endif | 
 
 
 
 
 | 330 |  | 
 
 
 
 
 | 331 | namespace Validation { | 
 
 
 
 
 | 332 |  | 
 
 
 
 
 | 333 | // Check if any string in the list is empty | 
 
 
 
 
 | 334 | bool checkEmptySpaces(QStringList toCheck){ | 
 
 
 
 
 | 335 | for (const QString ¤t : toCheck){ | 
 
 
 
 
 | 336 | if(current.trimmed().isEmpty()){ | 
 
 
 
 
 | 337 | return true; //There are empty spaces | 
 
 
 
 
 | 338 | } | 
 
 
 
 
 | 339 | } | 
 
 
 
 
 | 340 | return false; | 
 
 
 
 
 | 341 | } | 
 
 
 
 
 | 342 |  | 
 
 
 
 
 | 343 | bool checkIfIntegers(QStringList toCheck){ | 
 
 
 
 
 | 344 | for (const QString ¤t : toCheck){ | 
 
 
 
 
 | 345 | if(!isStringInteger(current)){ | 
 
 
 
 
 | 346 | return true; // Some aren't valid integers | 
 
 
 
 
 | 347 | } | 
 
 
 
 
 | 348 | } | 
 
 
 
 
 | 349 | return false; | 
 
 
 
 
 | 350 | } | 
 
 
 
 
 | 351 |  | 
 
 
 
 
 | 352 | bool checkIfDoubles(QStringList toCheck){ | 
 
 
 
 
 | 353 | for (const QString ¤t : toCheck){ | 
 
 
 
 
 | 354 | if(!isStringDouble(current)){ | 
 
 
 
 
 | 355 | return true; // Some aren't valid doubles | 
 
 
 
 
 | 356 | } | 
 
 
 
 
 | 357 | } | 
 
 
 
 
 | 358 | return false; | 
 
 
 
 
 | 359 | } | 
 
 
 
 
 | 360 |  | 
 
 
 
 
 | 361 | bool isStringInteger(QString myString){ | 
 
 
 
 
 | 362 | bool isNumber; | 
 
 
 
 
 | 363 |  | 
 
 
 
 
 | 364 | myString.toInt(&isNumber); //convert to int and see if it succeeds | 
 
 
 
 
 | 365 |  | 
 
 
 
 
 | 366 | return isNumber; | 
 
 
 
 
 | 367 | } | 
 
 
 
 
 | 368 |  | 
 
 
 
 
 | 369 | bool isStringDouble(QString myString){ | 
 
 
 
 
 | 370 | bool isDouble; | 
 
 
 
 
 | 371 |  | 
 
 
 
 
 | 372 | myString.toDouble(&isDouble); //convert to double and see if it succeeds | 
 
 
 
 
 | 373 |  | 
 
 
 
 
 | 374 | return isDouble; | 
 
 
 
 
 | 375 | } | 
 
 
 
 
 | 376 |  | 
 
 
 
 
 | 377 | } | 
 
 
 
 
 | 378 |  | 
 
 
 
 
 | 379 | namespace System { | 
 
 
 
 
 | 380 |  | 
 
 
 
 
 | 381 | #ifdef QT_GUI_LIB | 
 
 
 
 
 | 382 | // From here: http://stackoverflow.com/questions/17893328/qt-getting-the-screen-resolution-without-the-extended-monitor ty Chris | 
 
 
 
 
 | 383 | QRect getScreenResolution(){ | 
 
 
 
 
 | 384 | QDesktopWidget widget; | 
 
 
 
 
 | 385 | return widget.availableGeometry(widget.primaryScreen()); // or screenGeometry(), depending on your needs | 
 
 
 
 
 | 386 | } | 
 
 
 
 
 | 387 | #endif | 
 
 
 
 
 | 388 |  | 
 
 
 
 
 | 389 | } | 
 
 
 
 
 | 390 |  | 
 
 
 
 
 | 391 | #ifdef QT_GUI_LIB | 
 
 
 
 
 | 392 | namespace TableWidget { | 
 
 
 
 
 | 393 |  | 
 
 
 
 
 | 394 |  | 
 
 
 
 
 | 395 | void addRow(QTableWidget *myTable, QStringList &columns){ | 
 
 
 
 
 | 396 | //Get actual number rows | 
 
 
 
 
 | 397 | int twSize=myTable->rowCount(); | 
 
 
 
 
 | 398 |  | 
 
 
 
 
 | 399 | //increase the rows for the new item | 
 
 
 
 
 | 400 | myTable->setRowCount(twSize+1); | 
 
 
 
 
 | 401 |  | 
 
 
 
 
 | 402 | //Add to table and list to | 
 
 
 
 
 | 403 | for(int i=0; i<columns.size(); i++){ | 
 
 
 
 
 | 404 | QTableWidgetItem *newColumn = new QTableWidgetItem(columns[i]); | 
 
 
 
 
 | 405 | myTable->setItem(twSize,i,newColumn); | 
 
 
 
 
 | 406 | // Add a tooltip with with the cell content | 
 
 
 
 
 | 407 | myTable->item(twSize,i)->setToolTip(myTable->item(twSize,i)->text()); | 
 
 
 
 
 | 408 | } | 
 
 
 
 
 | 409 |  | 
 
 
 
 
 | 410 | } | 
 
 
 
 
 | 411 |  | 
 
 
 
 
 | 412 |  | 
 
 
 
 
 | 413 | QModelIndexList getSelectedRows(QTableWidget *myTable){ | 
 
 
 
 
 | 414 | return myTable->selectionModel()->selectedRows(); | 
 
 
 
 
 | 415 | } | 
 
 
 
 
 | 416 |  | 
 
 
 
 
 | 417 | QModelIndexList getCurrentRows(QTableWidget *myTable){ | 
 
 
 
 
 | 418 |  | 
 
 
 
 
 | 419 | QModelIndexList oldSelection = getSelectedRows(myTable); | 
 
 
 
 
 | 420 |  | 
 
 
 
 
 | 421 | myTable->selectAll(); | 
 
 
 
 
 | 422 |  | 
 
 
 
 
 | 423 | QModelIndexList allRows = getSelectedRows(myTable); | 
 
 
 
 
 | 424 |  | 
 
 
 
 
 | 425 | myTable->selectionModel()->clearSelection(); | 
 
 
 
 
 | 426 |  | 
 
 
 
 
 | 427 | // Restore old selection | 
 
 
 
 
 | 428 | for(const QModelIndex ¤tIndex : oldSelection){ | 
 
 
 
 
 | 429 | myTable->selectionModel()->select(currentIndex, QItemSelectionModel::Select | QItemSelectionModel::SelectionFlag::Rows); | 
 
 
 
 
 | 430 | } | 
 
 
 
 
 | 431 |  | 
 
 
 
 
 | 432 | return allRows; | 
 
 
 
 
 | 433 | } | 
 
 
 
 
 | 434 |  | 
 
 
 
 
 | 435 | int getNumberSelectedRows(QTableWidget *myTable){ | 
 
 
 
 
 | 436 | return getSelectedRows(myTable).size(); | 
 
 
 
 
 | 437 | } | 
 
 
 
 
 | 438 |  | 
 
 
 
 
 | 439 | void clearContents(QTableWidget *myTable, const QString ¬hingToClearMessage, const QString &questionToClear){ | 
 
 
 
 
 | 440 |  | 
 
 
 
 
 | 441 | if(myTable->rowCount()==0){ | 
 
 
 
 
 | 442 | Dialogs::showInfo(nothingToClearMessage); | 
 
 
 
 
 | 443 | return; | 
 
 
 
 
 | 444 | } | 
 
 
 
 
 | 445 |  | 
 
 
 
 
 | 446 | if(Dialogs::showQuestion(myTable, questionToClear)){ | 
 
 
 
 
 | 447 | clearContentsNoPrompt(myTable); | 
 
 
 
 
 | 448 | } | 
 
 
 
 
 | 449 |  | 
 
 
 
 
 | 450 | } | 
 
 
 
 
 | 451 |  | 
 
 
 
 
 | 452 | void clearContentsNoPrompt(QTableWidget *myTable){ | 
 
 
 
 
 | 453 | myTable->clearContents(); | 
 
 
 
 
 | 454 | myTable->setRowCount(0); | 
 
 
 
 
 | 455 | } | 
 
 
 
 
 | 456 |  | 
 
 
 
 
 | 457 | // Adapted from here: | 
 
 
 
 
 | 458 | // http://stackoverflow.com/questions/29176317/qtablewidget-checkbox-get-state-and-location | 
 
 
 
 
 | 459 | void addCheckBox(QTableWidget *myTable, int row, int column, QCheckBox *checkbox){ | 
 
 
 
 
 | 460 | if(checkbox == nullptr){ | 
 
 
 
 
 | 461 | checkbox = new QCheckBox(); | 
 
 
 
 
 | 462 | } | 
 
 
 
 
 | 463 |  | 
 
 
 
 
 | 464 | QWidget *auxLayoutWidget = new QWidget(myTable); | 
 
 
 
 
 | 465 |  | 
 
 
 
 
 | 466 | QHBoxLayout* checkBoxLayout = new QHBoxLayout(); | 
 
 
 
 
 | 467 | checkBoxLayout->setContentsMargins(0,0,0,0); | 
 
 
 
 
 | 468 | checkBoxLayout->addWidget(checkbox); | 
 
 
 
 
 | 469 | checkBoxLayout->setAlignment(Qt::AlignCenter); | 
 
 
 
 
 | 470 | checkBoxLayout->setSpacing(0); | 
 
 
 
 
 | 471 | auxLayoutWidget->setLayout(checkBoxLayout); | 
 
 
 
 
 | 472 |  | 
 
 
 
 
 | 473 | myTable->setCellWidget(row, column, auxLayoutWidget); | 
 
 
 
 
 | 474 | } | 
 
 
 
 
 | 475 |  | 
 
 
 
 
 | 476 | // Adapted from here: | 
 
 
 
 
 | 477 | // http://stackoverflow.com/questions/29176317/qtablewidget-checkbox-get-state-and-location | 
 
 
 
 
 | 478 | QCheckBox* getCheckBoxFromCell(QTableWidget *myTable, int row, int column){ | 
 
 
 
 
 | 479 | return dynamic_cast<QCheckBox*>(myTable->cellWidget(row, column)->findChild<QCheckBox *>()); | 
 
 
 
 
 | 480 | } | 
 
 
 
 
 | 481 |  | 
 
 
 
 
 | 482 | // Adapted from here: | 
 
 
 
 
 | 483 | // http://www.qtcentre.org/threads/3386-QTableWidget-move-row | 
 
 
 
 
 | 484 | // Thanks jpn | 
 
 
 
 
 | 485 | void swapRows(QTableWidget *myTable, const int indexSourceRow, const int indexDestinationRow, bool selectSwappedRow) | 
 
 
 
 
 | 486 | { | 
 
 
 
 
 | 487 | // takes and returns the whole row | 
 
 
 
 
 | 488 | auto takeRow = [&myTable](int row) -> QList<QTableWidgetItem*> | 
 
 
 
 
 | 489 | { | 
 
 
 
 
 | 490 | QList<QTableWidgetItem*> rowItems; | 
 
 
 
 
 | 491 | for (int col = 0; col < myTable->columnCount(); ++col) | 
 
 
 
 
 | 492 | { | 
 
 
 
 
 | 493 | rowItems << myTable->takeItem(row, col); | 
 
 
 
 
 | 494 | } | 
 
 
 
 
 | 495 | return rowItems; | 
 
 
 
 
 | 496 | }; | 
 
 
 
 
 | 497 |  | 
 
 
 
 
 | 498 | // sets the whole row | 
 
 
 
 
 | 499 | auto setRow = [&myTable](int row, const QList<QTableWidgetItem*>& rowItems) | 
 
 
 
 
 | 500 | { | 
 
 
 
 
 | 501 | for (int col = 0; col < myTable->columnCount(); ++col) | 
 
 
 
 
 | 502 | { | 
 
 
 
 
 | 503 | myTable->setItem(row, col, rowItems.at(col)); | 
 
 
 
 
 | 504 | } | 
 
 
 
 
 | 505 | }; | 
 
 
 
 
 | 506 |  | 
 
 
 
 
 | 507 | // take whole rows | 
 
 
 
 
 | 508 | QList<QTableWidgetItem*> sourceItems = takeRow(indexSourceRow); | 
 
 
 
 
 | 509 | QList<QTableWidgetItem*> destItems = takeRow(indexDestinationRow); | 
 
 
 
 
 | 510 |  | 
 
 
 
 
 | 511 | // set back in reverse order | 
 
 
 
 
 | 512 | setRow(indexSourceRow, destItems); | 
 
 
 
 
 | 513 | setRow(indexDestinationRow, sourceItems); | 
 
 
 
 
 | 514 |  | 
 
 
 
 
 | 515 | if(selectSwappedRow){ | 
 
 
 
 
 | 516 | myTable->selectRow(indexDestinationRow); | 
 
 
 
 
 | 517 | } | 
 
 
 
 
 | 518 | } | 
 
 
 
 
 | 519 |  | 
 
 
 
 
 | 520 | void deleteSelectedRows(QTableWidget *myTable){ | 
 
 
 
 
 | 521 | int size = myTable->selectionModel()->selectedRows().size(); | 
 
 
 
 
 | 522 |  | 
 
 
 
 
 | 523 | for(int i=0; i<size; i++){ | 
 
 
 
 
 | 524 | myTable->removeRow(myTable->selectionModel()->selectedRows().at(size-i-1).row()); | 
 
 
 
 
 | 525 | } | 
 
 
 
 
 | 526 | } | 
 
 
 
 
 | 527 |  | 
 
 
 
 
 | 528 | } | 
 
 
 
 
 | 529 | #endif | 
 
 
 
 
 | 530 |  | 
 
 
 
 
 | 531 | #ifdef QT_GUI_LIB | 
 
 
 
 
 | 532 | namespace StatusBar { | 
 
 
 
 
 | 533 |  | 
 
 
 
 
 | 534 | void showInfo(QStatusBar * const statusBar, const QString &message){ | 
 
 
 
 
 | 535 |  | 
 
 
 
 
 | 536 | QPalette myPalete = QPalette(); | 
 
 
 
 
 | 537 | myPalete.setColor( QPalette::WindowText, QColor(0,38,255)); | 
 
 
 
 
 | 538 | statusBar->setPalette( myPalete ); | 
 
 
 
 
 | 539 | statusBar->showMessage(message,10000); //display by 10 seconds | 
 
 
 
 
 | 540 |  | 
 
 
 
 
 | 541 | } | 
 
 
 
 
 | 542 |  | 
 
 
 
 
 | 543 | void showError(QStatusBar * const statusBar, const QString &message){ | 
 
 
 
 
 | 544 |  | 
 
 
 
 
 | 545 | QPalette myPalete = QPalette(); | 
 
 
 
 
 | 546 | myPalete.setColor( QPalette::WindowText, QColor(255,0,0)); | 
 
 
 
 
 | 547 | statusBar->setPalette( myPalete ); | 
 
 
 
 
 | 548 | statusBar->showMessage(message,10000); //display by 10 seconds | 
 
 
 
 
 | 549 |  | 
 
 
 
 
 | 550 | } | 
 
 
 
 
 | 551 |  | 
 
 
 
 
 | 552 | void showSuccess(QStatusBar * const statusBar,const QString &message){ | 
 
 
 
 
 | 553 |  | 
 
 
 
 
 | 554 | QPalette myPalete = QPalette(); | 
 
 
 
 
 | 555 | myPalete.setColor( QPalette::WindowText, QColor(0,150,0)); | 
 
 
 
 
 | 556 | statusBar->setPalette( myPalete ); | 
 
 
 
 
 | 557 | statusBar->showMessage(message,10000); //display by 10 seconds | 
 
 
 
 
 | 558 |  | 
 
 
 
 
 | 559 | } | 
 
 
 
 
 | 560 |  | 
 
 
 
 
 | 561 | } | 
 
 
 
 
 | 562 | #endif | 
 
 
 
 
 | 563 |  | 
 
 
 
 
 | 564 | } | 
 
 
 
 
 | 565 |  | 
 
 
 
 
 | 566 |  | 
 
 
 
 
 | 567 | /** | 
 
 
 
 
 | 568 | * Copyright (c) 2017 - 2018 Fábio Bento (fabiobento512) | 
 
 
 
 
 | 569 | * | 
 
 
 
 
 | 570 | * Permission is hereby granted, free of charge, to any person | 
 
 
 
 
 | 571 | * obtaining a copy of this software and associated documentation | 
 
 
 
 
 | 572 | * files (the "Software"), to deal in the Software without | 
 
 
 
 
 | 573 | * restriction, including without limitation the rights to use, | 
 
 
 
 
 | 574 | * copy, modify, merge, publish, distribute, sublicense, and/or sell | 
 
 
 
 
 | 575 | * copies of the Software, and to permit persons to whom the | 
 
 
 
 
 | 576 | * Software is furnished to do so, subject to the following | 
 
 
 
 
 | 577 | * conditions: | 
 
 
 
 
 | 578 | * | 
 
 
 
 
 | 579 | * The above copyright notice and this permission notice shall be | 
 
 
 
 
 | 580 | * included in all copies or substantial portions of the Software. | 
 
 
 
 
 | 581 | * | 
 
 
 
 
 | 582 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | 
 
 
 
 
 | 583 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES | 
 
 
 
 
 | 584 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | 
 
 
 
 
 | 585 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | 
 
 
 
 
 | 586 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | 
 
 
 
 
 | 587 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | 
 
 
 
 
 | 588 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | 
 
 
 
 
 | 589 | * OTHER DEALINGS IN THE SOFTWARE. | 
 
 
 
 
 | 590 | */ |