--- s10k/CommonUtils/util.cpp 2017/10/05 17:48:32 1073 +++ s10k/CommonUtils/util.cpp 2017/12/30 14:30:28 1095 @@ -1,582 +1,587 @@ -/** - * Copyright (C) 2017 - Fábio Bento (random-guy) - * - * This library is distributed under the MIT License. See notice at the end - * of this file. - * - */ - -#include "util.h" - -namespace Util{ - -namespace FileSystem { - -QString normalizePath(QString path){ - return path.replace("\\","/"); -} - -QString cutName(QString path){ - return path.remove(0,path.lastIndexOf('/')).remove('"'); -} - -QString cutNameWithoutBackSlash(QString path){ - return cutName(path).remove('/'); -} - -QString normalizeAndQuote(QString path){ - return String::insertQuotes(normalizePath(path)); -} - -// Created from scratch -bool copyDir(const QString &fromPath, QString toPath, const bool isRecursive){ - QDir fromDir(fromPath); - QDir toDir(toPath); - - if(!toDir.mkdir(fromDir.dirName())){ // create the folder in the destination - return false; - } - - // Update toPath to include the folder from "fromPath" - toPath = toPath + "/" + fromDir.dirName(); - toDir = QDir(toPath); - - for(const QFileInfo &currFileInfo : fromDir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot)){ - - if(currFileInfo.isFile()){ - - QFile destFile(toPath + "/" + currFileInfo.fileName()); - - if(!QFile::copy(currFileInfo.absoluteFilePath(),toPath + "/" + currFileInfo.fileName())){ - return false; - } - } - else if(isRecursive && currFileInfo.isDir() && currFileInfo.absoluteFilePath() != fromDir.absolutePath()){ - - if(!copyDir(currFileInfo.absoluteFilePath(), toPath, isRecursive)){ - return false; - } - } - } - - return true; -} - -//Copied from here: http://stackoverflow.com/questions/2536524/copy-directory-using-qt (ty roop) -bool rmDir(const QString &dirPath) -{ - QDir dir(dirPath); - if (!dir.exists()) - return true; - foreach(const QFileInfo &info, dir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot)) { - if (info.isDir()) { - if (!rmDir(info.filePath())) - return false; - } else { - if (!dir.remove(info.fileName())) - return false; - } - } - QDir parentDir(QFileInfo(dirPath).path()); - return parentDir.rmdir(QFileInfo(dirPath).fileName()); -} - -// Gets all files from a folder filtered by a given wildcard -QStringList getFolderFilesByWildcard(const QString &entryFolder, const QString &wildcard, bool isRecursive){ - - QStringList filesFound; // result files with absolute path - - QDirIterator it(entryFolder, QDir::Files, (isRecursive ? QDirIterator::Subdirectories : QDirIterator::NoIteratorFlags)); - - while (it.hasNext()){ - filesFound << it.next(); - } - - return filterFilesByWildcard(filesFound, wildcard); -} - -// Supports wildcards, and subdirectories with wildcard e.g.: -// *.xml -// /myXmls/*.xml -// -// online helper: https://regex101.com/ -QStringList filterFilesByWildcard(const QStringList &filePaths, const QString &wildcard){ - QStringList resultFiles; - QString formattedWildcard; - - if(wildcard.trimmed().isEmpty()){ - return resultFiles; - } - - formattedWildcard=normalizePath(wildcard); // Convert slashes to work in both mac and windows - - // escape the string so '.' or '(' chars get correctly escaped - formattedWildcard = QRegularExpression::escape(formattedWildcard); - - // replace * by the corresponding regex - formattedWildcard.replace("\\*",".*"); - - // replace ? by the corresponding regex - formattedWildcard.replace("\\?","."); - - // 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) - // We use \\/ instead of / because it was escaped - if(!formattedWildcard.startsWith("\\/") && !formattedWildcard.startsWith(".*") && !formattedWildcard.startsWith(".")){ - formattedWildcard = "\\/" + formattedWildcard; - } - - // if it is a subdirectory add * to match - if(formattedWildcard.startsWith("\\/")){ - formattedWildcard = ".*" + formattedWildcard; - } - - formattedWildcard = "^" + formattedWildcard + "$"; // we want a full match (http://stackoverflow.com/a/5752852) - - QRegularExpression regex(formattedWildcard); - - for(const QString ¤tFile : filePaths){ - - if(regex.match(currentFile).hasMatch()){ - resultFiles << currentFile; - } - - } - - return resultFiles; -} - -// Returns empty QString on failure. -// Based from here: http://www.qtcentre.org/archive/index.php/t-35674.html (thanks wysota!) -QString fileHash(const QString &fileName, QCryptographicHash::Algorithm hashAlgorithm) -{ - - QCryptographicHash crypto(hashAlgorithm); - QFile file(fileName); - file.open(QFile::ReadOnly); - while(!file.atEnd()){ - crypto.addData(file.read(8192)); - } - QByteArray hash = crypto.result(); - - return QString(crypto.result().toHex()); - -} - - -/** - Gets application directory. In mac os gets the .app directory - **/ -QString getAppPath(){ -#ifdef Q_OS_MAC - QDir dir = QDir(QCoreApplication::applicationDirPath()); - if(dir.absolutePath().contains(".app")){ // include bundle, but we don't want it - dir.cdUp(); - dir.cdUp(); - dir.cdUp(); - } - return dir.absolutePath(); -#else - return QDir::currentPath(); -#endif -} - -bool backupFile(QString file){ - return QFile::copy(file,file+".bak"); -} - -} - -namespace String { - -QString insertApostrophes(const QString &currString){ - return "'"+currString+"'"; -} - -QString insertQuotes(const QString &currString){ - return "\""+currString+"\""; -} - -QString fullTrim(QString str) { - - str = str.simplified(); //convert all invisible chars in normal whitespaces - str.replace( " ", "" ); - - return str; -} - -QStringList substring(QString myString, QString separator, Qt::CaseSensitivity cs){ - QStringList result = QStringList(); - int currIdx=0, nextIdx=0; - - while(true){ - nextIdx=myString.indexOf(separator,currIdx,cs); - result << myString.mid(currIdx,nextIdx-currIdx); - if(nextIdx==-1) break; - currIdx=nextIdx+1; - } - - return result; -} - -QString normalizeDecimalSeparator(QString value){ - return value.replace(',','.'); -} - -//Searches for the QString "toSearch" in the "myString" variable backward -//Returns the index of the first match or -1 if not found -int indexOfBackward(QString myString, QString toSearch, int from){ - int myStringSize=myString.size(); - int toSearchSize=toSearch.size(); - - if(from==-1){ - from=myStringSize; - } - - int i=from; - - while(i>=0){ - for(int j=toSearchSize-1; j>=0; j--){ - i--; - if(myString.at(i)!=toSearch.at(j)){ - break; - } - if(j==0){ - return i; - } - } - } - - return -1; -} - -// no problem here with "temporary" cstr -// https://stackoverflow.com/questions/1971183/when-does-c-allocate-deallocate-string-literals -const char* boolToCstr(bool currentBoolean){ - return currentBoolean ? "true" : "false"; -} - -} - -#ifdef QT_GUI_LIB -namespace Dialogs { - -void showInfo(const QString &message){ - QMessageBox msgBox; - msgBox.setIcon(QMessageBox::Information); - msgBox.setText(message); - msgBox.exec(); -} - -void showRichInfo(const QString &message){ - QMessageBox msgBox; - msgBox.setTextFormat(Qt::RichText); - msgBox.setIcon(QMessageBox::Information); - msgBox.setText(message); - msgBox.exec(); -} - -void showWarning(const QString &message){ - QMessageBox msgBox; - msgBox.setIcon(QMessageBox::Warning); - msgBox.setText(message); - msgBox.exec(); -} - -void showError(const QString &message){ - QMessageBox msgBox; - msgBox.setIcon(QMessageBox::Critical); - msgBox.setText(message); - msgBox.exec(); -} - -void showRichError(const QString &message){ - QMessageBox msgBox; - msgBox.setIcon(QMessageBox::Critical); - msgBox.setText(message); - msgBox.exec(); -} - -bool showQuestion(QWidget * parent, QString message, QMessageBox::StandardButton standardButton){ - return QMessageBox::question (parent, "Are you sure?", message, QMessageBox::Yes | QMessageBox::No, standardButton)==QMessageBox::Yes; -} - -QMessageBox::StandardButton showQuestionWithCancel(QWidget * parent, QString message, QMessageBox::StandardButton standardButton){ - return QMessageBox::question (parent, "Are you sure?", message, QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, standardButton); -} - -QStringList multipleDirSelection(const QString &title){ - QFileDialog w; - - // We need to use non native dialog, because native doesn't support multiple folder selection - w.setOption(QFileDialog::DontUseNativeDialog,true); - - w.setFileMode(QFileDialog::DirectoryOnly); - - w.setWindowTitle(title); - - QTreeView *t = w.findChild(); - - if (t) { - t->setSelectionMode(QAbstractItemView::MultiSelection); - } - - if(w.exec()){ //if accepted - return w.selectedFiles(); - } - return QStringList(); //return empty -} - -} -#endif - -namespace Validation { - -// Check if any string in the list is empty -bool checkEmptySpaces(QStringList toCheck){ - foreach (QString current, toCheck){ - if(current.trimmed().isEmpty()){ - return true; //There are empty spaces - } - } - return false; -} - -bool checkIfIntegers(QStringList toCheck){ - foreach (QString current, toCheck){ - if(!isStringInteger(current)){ - return true; // Some aren't valid integers - } - } - return false; -} - -bool checkIfDoubles(QStringList toCheck){ - foreach (QString current, toCheck){ - if(!isStringDouble(current)){ - return true; // Some aren't valid doubles - } - } - return false; -} - -bool isStringInteger(QString myString){ - bool isNumber; - - myString.toInt(&isNumber); //convert to int and see if it succeeds - - return isNumber; -} - -bool isStringDouble(QString myString){ - bool isDouble; - - myString.toDouble(&isDouble); //convert to double and see if it succeeds - - return isDouble; -} - -} - -namespace System { - -#ifdef QT_GUI_LIB -// From here: http://stackoverflow.com/questions/17893328/qt-getting-the-screen-resolution-without-the-extended-monitor ty Chris -QRect getScreenResolution(){ - QDesktopWidget widget; - return widget.availableGeometry(widget.primaryScreen()); // or screenGeometry(), depending on your needs -} -#endif - -} - -#ifdef QT_GUI_LIB -namespace TableWidget { - - -void addRow(QTableWidget *myTable, QStringList &columns){ - //Get actual number rows - int twSize=myTable->rowCount(); - - //increase the rows for the new item - myTable->setRowCount(twSize+1); - - //Add to table and list to - for(int i=0; isetItem(twSize,i,newColumn); - // Add a tooltip with with the cell content - myTable->item(twSize,i)->setToolTip(myTable->item(twSize,i)->text()); - } - -} - - -QModelIndexList getSelectedRows(QTableWidget *myTable){ - return myTable->selectionModel()->selectedRows(); -} - -QModelIndexList getCurrentRows(QTableWidget *myTable){ - - QModelIndexList oldSelection = getSelectedRows(myTable); - - myTable->selectAll(); - - QModelIndexList allRows = getSelectedRows(myTable); - - myTable->selectionModel()->clearSelection(); - - // Restore old selection - for(const QModelIndex ¤tIndex : oldSelection){ - myTable->selectionModel()->select(currentIndex, QItemSelectionModel::Select | QItemSelectionModel::SelectionFlag::Rows); - } - - return allRows; -} - -int getNumberSelectedRows(QTableWidget *myTable){ - return getSelectedRows(myTable).size(); -} - -void clearContents(QTableWidget *myTable, const QString ¬hingToClearMessage, const QString &questionToClear){ - - if(myTable->rowCount()==0){ - Dialogs::showInfo(nothingToClearMessage); - return; - } - - if(Dialogs::showQuestion(myTable, questionToClear)){ - clearContentsNoPrompt(myTable); - } - -} - -void clearContentsNoPrompt(QTableWidget *myTable){ - myTable->clearContents(); - myTable->setRowCount(0); -} - -// Adapted from here: -// http://stackoverflow.com/questions/29176317/qtablewidget-checkbox-get-state-and-location -void addCheckBox(QTableWidget *myTable, int row, int column, QCheckBox *checkbox){ - if(checkbox == nullptr){ - checkbox = new QCheckBox(); - } - - QWidget *auxLayoutWidget = new QWidget(myTable); - - QHBoxLayout* checkBoxLayout = new QHBoxLayout(); - checkBoxLayout->setContentsMargins(0,0,0,0); - checkBoxLayout->addWidget(checkbox); - checkBoxLayout->setAlignment(Qt::AlignCenter); - checkBoxLayout->setSpacing(0); - auxLayoutWidget->setLayout(checkBoxLayout); - - myTable->setCellWidget(row, column, auxLayoutWidget); -} - -// Adapted from here: -// http://stackoverflow.com/questions/29176317/qtablewidget-checkbox-get-state-and-location -QCheckBox* getCheckBoxFromCell(QTableWidget *myTable, int row, int column){ - return dynamic_cast(myTable->cellWidget(row, column)->findChild()); -} - -// Adapted from here: -// http://www.qtcentre.org/threads/3386-QTableWidget-move-row -// Thanks jpn -void swapRows(QTableWidget *myTable, const int indexSourceRow, const int indexDestinationRow, bool selectSwappedRow) -{ - // takes and returns the whole row - auto takeRow = [&myTable](int row) -> QList - { - QList rowItems; - for (int col = 0; col < myTable->columnCount(); ++col) - { - rowItems << myTable->takeItem(row, col); - } - return rowItems; - }; - - // sets the whole row - auto setRow = [&myTable](int row, const QList& rowItems) - { - for (int col = 0; col < myTable->columnCount(); ++col) - { - myTable->setItem(row, col, rowItems.at(col)); - } - }; - - // take whole rows - QList sourceItems = takeRow(indexSourceRow); - QList destItems = takeRow(indexDestinationRow); - - // set back in reverse order - setRow(indexSourceRow, destItems); - setRow(indexDestinationRow, sourceItems); - - if(selectSwappedRow){ - myTable->selectRow(indexDestinationRow); - } -} - -void deleteSelectedRows(QTableWidget *myTable){ - int size = myTable->selectionModel()->selectedRows().size(); - - for(int i=0; iremoveRow(myTable->selectionModel()->selectedRows().at(size-i-1).row()); - } -} - -} -#endif - -#ifdef QT_GUI_LIB -namespace StatusBar { - -void showError(QStatusBar * const statusBar, const QString &message){ - - QPalette myPalete = QPalette(); - myPalete.setColor( QPalette::WindowText, QColor(255,0,0)); - statusBar->setPalette( myPalete ); - statusBar->showMessage(message,10000); //display by 10 seconds - -} - -void showSuccess(QStatusBar * const statusBar,const QString &message){ - - QPalette myPalete = QPalette(); - myPalete.setColor( QPalette::WindowText, QColor(0,150,0)); - statusBar->setPalette( myPalete ); - statusBar->showMessage(message,10000); //display by 10 seconds - -} - -} -#endif - -} - - -/** - * Copyright (c) 2017 - Fábio Bento (random-guy) - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ +/** + * Copyright (C) 2017 - Fábio Bento (random-guy) + * + * This library is distributed under the MIT License. See notice at the end + * of this file. + * + */ + +#include "util.h" + +namespace Util{ + +namespace FileSystem { + +QString normalizePath(QString path){ + return path.replace("\\","/"); +} + +QString cutName(QString path){ + return path.remove(0,path.lastIndexOf('/')).remove('"'); +} + +QString cutNameWithoutBackSlash(QString path){ + return cutName(path).remove('/'); +} + +QString normalizeAndQuote(QString path){ + return String::insertQuotes(normalizePath(path)); +} + +// Created from scratch +bool copyDir(const QString &fromPath, QString toPath, const bool isRecursive){ + QDir fromDir(fromPath); + QDir toDir(toPath); + + if(!toDir.mkdir(fromDir.dirName())){ // create the folder in the destination + return false; + } + + // Update toPath to include the folder from "fromPath" + toPath = toPath + "/" + fromDir.dirName(); + toDir = QDir(toPath); + + for(const QFileInfo &currFileInfo : fromDir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot)){ + + if(currFileInfo.isFile()){ + + QFile destFile(toPath + "/" + currFileInfo.fileName()); + + if(!QFile::copy(currFileInfo.absoluteFilePath(),toPath + "/" + currFileInfo.fileName())){ + return false; + } + } + else if(isRecursive && currFileInfo.isDir() && currFileInfo.absoluteFilePath() != fromDir.absolutePath()){ + + if(!copyDir(currFileInfo.absoluteFilePath(), toPath, isRecursive)){ + return false; + } + } + } + + return true; +} + +//Copied from here: http://stackoverflow.com/questions/2536524/copy-directory-using-qt (ty roop) +bool rmDir(const QString &dirPath) +{ + QDir dir(dirPath); + if (!dir.exists()) + return true; + for(const QFileInfo &info : dir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot)) { + if (info.isDir()) { + if (!rmDir(info.filePath())) + return false; + } else { + if (!dir.remove(info.fileName())) + return false; + } + } + QDir parentDir(QFileInfo(dirPath).path()); + return parentDir.rmdir(QFileInfo(dirPath).fileName()); +} + +// Gets all files from a folder filtered by a given wildcard +QStringList getFolderFilesByWildcard(const QString &entryFolder, const QString &wildcard, bool isRecursive){ + + QStringList filesFound; // result files with absolute path + + QDirIterator it(entryFolder, QDir::Files, (isRecursive ? QDirIterator::Subdirectories : QDirIterator::NoIteratorFlags)); + + while (it.hasNext()){ + filesFound << it.next(); + } + + return filterFilesByWildcard(filesFound, wildcard); +} + +// Supports wildcards, and subdirectories with wildcard e.g.: +// *.xml +// /myXmls/*.xml +// +// online helper: https://regex101.com/ +QStringList filterFilesByWildcard(const QStringList &filePaths, const QString &wildcard){ + QStringList resultFiles; + QString formattedWildcard; + + if(wildcard.trimmed().isEmpty()){ + return resultFiles; + } + + formattedWildcard=normalizePath(wildcard); // Convert slashes to work in both mac and windows + + // escape the string so '.' or '(' chars get correctly escaped + formattedWildcard = QRegularExpression::escape(formattedWildcard); + + // replace * by the corresponding regex + formattedWildcard.replace("\\*",".*"); + + // replace ? by the corresponding regex + formattedWildcard.replace("\\?","."); + + // 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) + // We use \\/ instead of / because it was escaped + if(!formattedWildcard.startsWith("\\/") && !formattedWildcard.startsWith(".*") && !formattedWildcard.startsWith(".")){ + formattedWildcard = "\\/" + formattedWildcard; + } + + // if it is a subdirectory add * to match + if(formattedWildcard.startsWith("\\/")){ + formattedWildcard = ".*" + formattedWildcard; + } + + formattedWildcard = "^" + formattedWildcard + "$"; // we want a full match (http://stackoverflow.com/a/5752852) + + QRegularExpression regex(formattedWildcard); + + for(const QString ¤tFile : filePaths){ + + if(regex.match(currentFile).hasMatch()){ + resultFiles << currentFile; + } + + } + + return resultFiles; +} + +// Returns empty QString on failure. +// Based from here: http://www.qtcentre.org/archive/index.php/t-35674.html (thanks wysota!) +QString fileHash(const QString &fileName, QCryptographicHash::Algorithm hashAlgorithm) +{ + + QCryptographicHash crypto(hashAlgorithm); + QFile file(fileName); + file.open(QFile::ReadOnly); + while(!file.atEnd()){ + crypto.addData(file.read(8192)); + } + QByteArray hash = crypto.result(); + + return QString(crypto.result().toHex()); + +} + + +/** + Gets application directory. In mac os gets the .app directory + **/ +QString getAppPath(){ +#ifdef Q_OS_MAC + QDir dir = QDir(QCoreApplication::applicationDirPath()); + if(dir.absolutePath().contains(".app")){ // include bundle, but we don't want it + dir.cdUp(); + dir.cdUp(); + dir.cdUp(); + } + return dir.absolutePath(); +#else + return QDir::currentPath(); +#endif +} + +bool backupFile(const QString &file, QString newFilename){ + + if(newFilename.isEmpty()){ + newFilename = file; + } + + return QFile::copy(file, newFilename+".bak"); +} + +} + +namespace String { + +QString insertApostrophes(const QString &currString){ + return "'"+currString+"'"; +} + +QString insertQuotes(const QString &currString){ + return "\""+currString+"\""; +} + +QString fullTrim(QString str) { + + str = str.simplified(); //convert all invisible chars in normal whitespaces + str.replace( " ", "" ); + + return str; +} + +QStringList substring(QString myString, QString separator, Qt::CaseSensitivity cs){ + QStringList result = QStringList(); + int currIdx=0, nextIdx=0; + + while(true){ + nextIdx=myString.indexOf(separator,currIdx,cs); + result << myString.mid(currIdx,nextIdx-currIdx); + if(nextIdx==-1) break; + currIdx=nextIdx+1; + } + + return result; +} + +QString normalizeDecimalSeparator(QString value){ + return value.replace(',','.'); +} + +//Searches for the QString "toSearch" in the "myString" variable backward +//Returns the index of the first match or -1 if not found +int indexOfBackward(QString myString, QString toSearch, int from){ + int myStringSize=myString.size(); + int toSearchSize=toSearch.size(); + + if(from==-1){ + from=myStringSize; + } + + int i=from; + + while(i>=0){ + for(int j=toSearchSize-1; j>=0; j--){ + i--; + if(myString.at(i)!=toSearch.at(j)){ + break; + } + if(j==0){ + return i; + } + } + } + + return -1; +} + +// no problem here with "temporary" cstr +// https://stackoverflow.com/questions/1971183/when-does-c-allocate-deallocate-string-literals +const char* boolToCstr(bool currentBoolean){ + return currentBoolean ? "true" : "false"; +} + +} + +#ifdef QT_GUI_LIB +namespace Dialogs { + +void showInfo(const QString &message){ + QMessageBox msgBox; + msgBox.setIcon(QMessageBox::Information); + msgBox.setText(message); + msgBox.exec(); +} + +void showRichInfo(const QString &message){ + QMessageBox msgBox; + msgBox.setTextFormat(Qt::RichText); + msgBox.setIcon(QMessageBox::Information); + msgBox.setText(message); + msgBox.exec(); +} + +void showWarning(const QString &message){ + QMessageBox msgBox; + msgBox.setIcon(QMessageBox::Warning); + msgBox.setText(message); + msgBox.exec(); +} + +void showError(const QString &message){ + QMessageBox msgBox; + msgBox.setIcon(QMessageBox::Critical); + msgBox.setText(message); + msgBox.exec(); +} + +void showRichError(const QString &message){ + QMessageBox msgBox; + msgBox.setIcon(QMessageBox::Critical); + msgBox.setText(message); + msgBox.exec(); +} + +bool showQuestion(QWidget * parent, QString message, QMessageBox::StandardButton standardButton){ + return QMessageBox::question (parent, "Are you sure?", message, QMessageBox::Yes | QMessageBox::No, standardButton)==QMessageBox::Yes; +} + +QMessageBox::StandardButton showQuestionWithCancel(QWidget * parent, QString message, QMessageBox::StandardButton standardButton){ + return QMessageBox::question (parent, "Are you sure?", message, QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, standardButton); +} + +QStringList multipleDirSelection(const QString &title){ + QFileDialog w; + + // We need to use non native dialog, because native doesn't support multiple folder selection + w.setOption(QFileDialog::DontUseNativeDialog,true); + + w.setFileMode(QFileDialog::DirectoryOnly); + + w.setWindowTitle(title); + + QTreeView *t = w.findChild(); + + if (t) { + t->setSelectionMode(QAbstractItemView::MultiSelection); + } + + if(w.exec()){ //if accepted + return w.selectedFiles(); + } + return QStringList(); //return empty +} + +} +#endif + +namespace Validation { + +// Check if any string in the list is empty +bool checkEmptySpaces(QStringList toCheck){ + for (const QString ¤t : toCheck){ + if(current.trimmed().isEmpty()){ + return true; //There are empty spaces + } + } + return false; +} + +bool checkIfIntegers(QStringList toCheck){ + for (const QString ¤t : toCheck){ + if(!isStringInteger(current)){ + return true; // Some aren't valid integers + } + } + return false; +} + +bool checkIfDoubles(QStringList toCheck){ + for (const QString ¤t : toCheck){ + if(!isStringDouble(current)){ + return true; // Some aren't valid doubles + } + } + return false; +} + +bool isStringInteger(QString myString){ + bool isNumber; + + myString.toInt(&isNumber); //convert to int and see if it succeeds + + return isNumber; +} + +bool isStringDouble(QString myString){ + bool isDouble; + + myString.toDouble(&isDouble); //convert to double and see if it succeeds + + return isDouble; +} + +} + +namespace System { + +#ifdef QT_GUI_LIB +// From here: http://stackoverflow.com/questions/17893328/qt-getting-the-screen-resolution-without-the-extended-monitor ty Chris +QRect getScreenResolution(){ + QDesktopWidget widget; + return widget.availableGeometry(widget.primaryScreen()); // or screenGeometry(), depending on your needs +} +#endif + +} + +#ifdef QT_GUI_LIB +namespace TableWidget { + + +void addRow(QTableWidget *myTable, QStringList &columns){ + //Get actual number rows + int twSize=myTable->rowCount(); + + //increase the rows for the new item + myTable->setRowCount(twSize+1); + + //Add to table and list to + for(int i=0; isetItem(twSize,i,newColumn); + // Add a tooltip with with the cell content + myTable->item(twSize,i)->setToolTip(myTable->item(twSize,i)->text()); + } + +} + + +QModelIndexList getSelectedRows(QTableWidget *myTable){ + return myTable->selectionModel()->selectedRows(); +} + +QModelIndexList getCurrentRows(QTableWidget *myTable){ + + QModelIndexList oldSelection = getSelectedRows(myTable); + + myTable->selectAll(); + + QModelIndexList allRows = getSelectedRows(myTable); + + myTable->selectionModel()->clearSelection(); + + // Restore old selection + for(const QModelIndex ¤tIndex : oldSelection){ + myTable->selectionModel()->select(currentIndex, QItemSelectionModel::Select | QItemSelectionModel::SelectionFlag::Rows); + } + + return allRows; +} + +int getNumberSelectedRows(QTableWidget *myTable){ + return getSelectedRows(myTable).size(); +} + +void clearContents(QTableWidget *myTable, const QString ¬hingToClearMessage, const QString &questionToClear){ + + if(myTable->rowCount()==0){ + Dialogs::showInfo(nothingToClearMessage); + return; + } + + if(Dialogs::showQuestion(myTable, questionToClear)){ + clearContentsNoPrompt(myTable); + } + +} + +void clearContentsNoPrompt(QTableWidget *myTable){ + myTable->clearContents(); + myTable->setRowCount(0); +} + +// Adapted from here: +// http://stackoverflow.com/questions/29176317/qtablewidget-checkbox-get-state-and-location +void addCheckBox(QTableWidget *myTable, int row, int column, QCheckBox *checkbox){ + if(checkbox == nullptr){ + checkbox = new QCheckBox(); + } + + QWidget *auxLayoutWidget = new QWidget(myTable); + + QHBoxLayout* checkBoxLayout = new QHBoxLayout(); + checkBoxLayout->setContentsMargins(0,0,0,0); + checkBoxLayout->addWidget(checkbox); + checkBoxLayout->setAlignment(Qt::AlignCenter); + checkBoxLayout->setSpacing(0); + auxLayoutWidget->setLayout(checkBoxLayout); + + myTable->setCellWidget(row, column, auxLayoutWidget); +} + +// Adapted from here: +// http://stackoverflow.com/questions/29176317/qtablewidget-checkbox-get-state-and-location +QCheckBox* getCheckBoxFromCell(QTableWidget *myTable, int row, int column){ + return dynamic_cast(myTable->cellWidget(row, column)->findChild()); +} + +// Adapted from here: +// http://www.qtcentre.org/threads/3386-QTableWidget-move-row +// Thanks jpn +void swapRows(QTableWidget *myTable, const int indexSourceRow, const int indexDestinationRow, bool selectSwappedRow) +{ + // takes and returns the whole row + auto takeRow = [&myTable](int row) -> QList + { + QList rowItems; + for (int col = 0; col < myTable->columnCount(); ++col) + { + rowItems << myTable->takeItem(row, col); + } + return rowItems; + }; + + // sets the whole row + auto setRow = [&myTable](int row, const QList& rowItems) + { + for (int col = 0; col < myTable->columnCount(); ++col) + { + myTable->setItem(row, col, rowItems.at(col)); + } + }; + + // take whole rows + QList sourceItems = takeRow(indexSourceRow); + QList destItems = takeRow(indexDestinationRow); + + // set back in reverse order + setRow(indexSourceRow, destItems); + setRow(indexDestinationRow, sourceItems); + + if(selectSwappedRow){ + myTable->selectRow(indexDestinationRow); + } +} + +void deleteSelectedRows(QTableWidget *myTable){ + int size = myTable->selectionModel()->selectedRows().size(); + + for(int i=0; iremoveRow(myTable->selectionModel()->selectedRows().at(size-i-1).row()); + } +} + +} +#endif + +#ifdef QT_GUI_LIB +namespace StatusBar { + +void showError(QStatusBar * const statusBar, const QString &message){ + + QPalette myPalete = QPalette(); + myPalete.setColor( QPalette::WindowText, QColor(255,0,0)); + statusBar->setPalette( myPalete ); + statusBar->showMessage(message,10000); //display by 10 seconds + +} + +void showSuccess(QStatusBar * const statusBar,const QString &message){ + + QPalette myPalete = QPalette(); + myPalete.setColor( QPalette::WindowText, QColor(0,150,0)); + statusBar->setPalette( myPalete ); + statusBar->showMessage(message,10000); //display by 10 seconds + +} + +} +#endif + +} + + +/** + * Copyright (c) 2017 - Fábio Bento (random-guy) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */