diff --git a/src/controllers/dlgprefcontroller.cpp b/src/controllers/dlgprefcontroller.cpp index d6db5c042296..d3a2ae4a0383 100644 --- a/src/controllers/dlgprefcontroller.cpp +++ b/src/controllers/dlgprefcontroller.cpp @@ -681,7 +681,8 @@ QString DlgPrefController::askForMappingName(const QString& prefilledName) const "special characters."); QString fileExistsLabel = tr("A mapping file with that name already exists."); // Only allow the name to contain letters, numbers, whitespaces and _-+()/ - const QRegExp rxRemove = QRegExp("[^[(a-zA-Z0-9\\_\\-\\+\\(\\)\\/|\\s]"); + const QRegularExpression rxRemove = QRegularExpression( + QStringLiteral("[^[(a-zA-Z0-9\\_\\-\\+\\(\\)\\/|\\s]")); // Choose a new file (base) name bool validMappingName = false; diff --git a/src/controllers/midi/portmidienumerator.cpp b/src/controllers/midi/portmidienumerator.cpp index 36cbcd5f799f..a92018f0b4c0 100644 --- a/src/controllers/midi/portmidienumerator.cpp +++ b/src/controllers/midi/portmidienumerator.cpp @@ -2,7 +2,7 @@ #include -#include +#include #include "controllers/midi/portmidicontroller.h" #include "moc_portmidienumerator.cpp" @@ -20,44 +20,33 @@ bool recognizeDevice(const PmDeviceInfo& deviceInfo) { .startsWith(kMidiThroughPortPrefix, Qt::CaseInsensitive); } -} // namespace +// Some platforms format MIDI device names as "deviceName MIDI ###" where +// ### is the instance # of the device. Therefore we want to link two +// devices that have an equivalent "deviceName" and ### section. +const QRegularExpression kMidiDeviceNameRegex(QStringLiteral("^(.*) MIDI (\\d+)( .*)?$")); -PortMidiEnumerator::PortMidiEnumerator() { - PmError err = Pm_Initialize(); - // Based on reading the source, it's not possible for this to fail. - if (err != pmNoError) { - qWarning() << "PortMidi error:" << Pm_GetErrorText(err); - } -} +const QRegularExpression kInputRegex(QStringLiteral("^(.*) in (\\d+)( .*)?$")); +const QRegularExpression kOutputRegex(QStringLiteral("^(.*) out (\\d+)( .*)?$")); -PortMidiEnumerator::~PortMidiEnumerator() { - qDebug() << "Deleting PortMIDI devices..."; - QListIterator dev_it(m_devices); - while (dev_it.hasNext()) { - delete dev_it.next(); - } - PmError err = Pm_Terminate(); - // Based on reading the source, it's not possible for this to fail. - if (err != pmNoError) { - qWarning() << "PortMidi error:" << Pm_GetErrorText(err); - } -} +// This is a broad pattern that matches a text blob followed by a numeral +// potentially followed by non-numeric text. The non-numeric requirement is +// meant to avoid corner cases around devices with names like "Hercules RMX +// 2" where we would potentially confuse the number in the device name as +// the ordinal index of the device. +const QRegularExpression kDeviceNameRegex(QStringLiteral("^(.*) (\\d+)( [^0-9]+)?$")); -bool namesMatchMidiPattern(const QString& input_name, +bool namesMatchRegexes(const QRegularExpression& kInputRegex, + const QString& input_name, + const QRegularExpression& kOutputRegex, const QString& output_name) { - // Some platforms format MIDI device names as "deviceName MIDI ###" where - // ### is the instance # of the device. Therefore we want to link two - // devices that have an equivalent "deviceName" and ### section. - QRegExp deviceNamePattern("^(.*) MIDI (\\d+)( .*)?$"); - - int inputMatch = deviceNamePattern.indexIn(input_name); - if (inputMatch == 0) { - QString inputDeviceName = deviceNamePattern.cap(1); - QString inputDeviceIndex = deviceNamePattern.cap(2); - int outputMatch = deviceNamePattern.indexIn(output_name); - if (outputMatch == 0) { - QString outputDeviceName = deviceNamePattern.cap(1); - QString outputDeviceIndex = deviceNamePattern.cap(2); + QRegularExpressionMatch inputMatch = kInputRegex.match(input_name); + if (inputMatch.hasMatch()) { + QString inputDeviceName = inputMatch.captured(1); + QString inputDeviceIndex = inputMatch.captured(2); + QRegularExpressionMatch outputMatch = kOutputRegex.match(output_name); + if (outputMatch.hasMatch()) { + QString outputDeviceName = outputMatch.captured(1); + QString outputDeviceIndex = outputMatch.captured(2); if (outputDeviceName.compare(inputDeviceName, Qt::CaseInsensitive) == 0 && outputDeviceIndex == inputDeviceIndex) { return true; @@ -67,53 +56,19 @@ bool namesMatchMidiPattern(const QString& input_name, return false; } +bool namesMatchMidiPattern(const QString& input_name, + const QString& output_name) { + return namesMatchRegexes(kMidiDeviceNameRegex, input_name, kMidiDeviceNameRegex, output_name); +} + bool namesMatchInOutPattern(const QString& input_name, const QString& output_name) { - QString basePattern = "^(.*) %1 (\\d+)( .*)?$"; - QRegExp inputPattern(basePattern.arg("in")); - QRegExp outputPattern(basePattern.arg("out")); - - int inputMatch = inputPattern.indexIn(input_name); - if (inputMatch == 0) { - QString inputDeviceName = inputPattern.cap(1); - QString inputDeviceIndex = inputPattern.cap(2); - int outputMatch = outputPattern.indexIn(output_name); - if (outputMatch == 0) { - QString outputDeviceName = outputPattern.cap(1); - QString outputDeviceIndex = outputPattern.cap(2); - if (outputDeviceName.compare(inputDeviceName, Qt::CaseInsensitive) == 0 && - outputDeviceIndex == inputDeviceIndex) { - return true; - } - } - } - return false; + return namesMatchRegexes(kInputRegex, input_name, kOutputRegex, output_name); } bool namesMatchPattern(const QString& input_name, const QString& output_name) { - // This is a broad pattern that matches a text blob followed by a numeral - // potentially followed by non-numeric text. The non-numeric requirement is - // meant to avoid corner cases around devices with names like "Hercules RMX - // 2" where we would potentially confuse the number in the device name as - // the ordinal index of the device. - QRegExp deviceNamePattern("^(.*) (\\d+)( [^0-9]+)?$"); - - int inputMatch = deviceNamePattern.indexIn(input_name); - if (inputMatch == 0) { - QString inputDeviceName = deviceNamePattern.cap(1); - QString inputDeviceIndex = deviceNamePattern.cap(2); - int outputMatch = deviceNamePattern.indexIn(output_name); - if (outputMatch == 0) { - QString outputDeviceName = deviceNamePattern.cap(1); - QString outputDeviceIndex = deviceNamePattern.cap(2); - if (outputDeviceName.compare(inputDeviceName, Qt::CaseInsensitive) == 0 && - outputDeviceIndex == inputDeviceIndex) { - return true; - } - } - } - return false; + return namesMatchRegexes(kDeviceNameRegex, input_name, kDeviceNameRegex, output_name); } bool namesMatchAllowableEdgeCases(const QString& input_name, @@ -129,6 +84,29 @@ bool namesMatchAllowableEdgeCases(const QString& input_name, return false; } +} // namespace + +PortMidiEnumerator::PortMidiEnumerator() { + PmError err = Pm_Initialize(); + // Based on reading the source, it's not possible for this to fail. + if (err != pmNoError) { + qWarning() << "PortMidi error:" << Pm_GetErrorText(err); + } +} + +PortMidiEnumerator::~PortMidiEnumerator() { + qDebug() << "Deleting PortMIDI devices..."; + QListIterator dev_it(m_devices); + while (dev_it.hasNext()) { + delete dev_it.next(); + } + PmError err = Pm_Terminate(); + // Based on reading the source, it's not possible for this to fail. + if (err != pmNoError) { + qWarning() << "PortMidi error:" << Pm_GetErrorText(err); + } +} + bool shouldLinkInputToOutput(const QString& input_name, const QString& output_name) { // Early exit. diff --git a/src/effects/effectsmanager.cpp b/src/effects/effectsmanager.cpp index 7b7049d8a909..151e1336fd15 100644 --- a/src/effects/effectsmanager.cpp +++ b/src/effects/effectsmanager.cpp @@ -1,6 +1,7 @@ #include "effects/effectsmanager.h" #include +#include #include #include "effects/effectchainmanager.h" @@ -19,6 +20,7 @@ namespace { constexpr QChar kEffectGroupSeparator = '_'; constexpr QChar kGroupClose = ']'; const unsigned int kEffectMessagPipeFifoSize = 2048; +const QRegularExpression kIntRegex(QStringLiteral(".*(\\d+).*")); } // anonymous namespace EffectsManager::EffectsManager(QObject* pParent, @@ -256,8 +258,6 @@ EffectRackPointer EffectsManager::getEffectRack(const QString& group) { EffectSlotPointer EffectsManager::getEffectSlot( const QString& group) { - QRegExp intRegEx(".*(\\d+).*"); - QStringList parts = group.split(kEffectGroupSeparator); EffectRackPointer pRack = getEffectRack(parts.at(0) + kGroupClose); @@ -267,8 +267,8 @@ EffectSlotPointer EffectsManager::getEffectSlot( EffectChainSlotPointer pChainSlot; if (parts.at(0) == "[EffectRack1") { - intRegEx.indexIn(parts.at(1)); - pChainSlot = pRack->getEffectChainSlot(intRegEx.cap(1).toInt() - 1); + QRegularExpressionMatch match = kIntRegex.match(parts.at(1)); + pChainSlot = pRack->getEffectChainSlot(match.captured(1).toInt() - 1); } else { // Assume a PerGroupRack const QString chainGroup = @@ -285,9 +285,9 @@ EffectSlotPointer EffectsManager::getEffectSlot( return EffectSlotPointer(); } - intRegEx.indexIn(parts.at(2)); + QRegularExpressionMatch match = kIntRegex.match(parts.at(2)); EffectSlotPointer pEffectSlot = - pChainSlot->getEffectSlot(intRegEx.cap(1).toInt() - 1); + pChainSlot->getEffectSlot(match.captured(1).toInt() - 1); return pEffectSlot; } @@ -299,10 +299,9 @@ EffectParameterSlotPointer EffectsManager::getEffectParameterSlot( return EffectParameterSlotPointer(); } - QRegExp intRegEx(".*(\\d+).*"); - intRegEx.indexIn(configKey.item); + QRegularExpressionMatch match = kIntRegex.match(configKey.item); EffectParameterSlotPointer pParameterSlot = - pEffectSlot->getEffectParameterSlot(intRegEx.cap(1).toInt() - 1); + pEffectSlot->getEffectParameterSlot(match.captured(1).toInt() - 1); return pParameterSlot; } @@ -314,10 +313,9 @@ EffectButtonParameterSlotPointer EffectsManager::getEffectButtonParameterSlot( return EffectButtonParameterSlotPointer(); } - QRegExp intRegEx(".*(\\d+).*"); - intRegEx.indexIn(configKey.item); + QRegularExpressionMatch match = kIntRegex.match(configKey.item); EffectButtonParameterSlotPointer pParameterSlot = - pEffectSlot->getEffectButtonParameterSlot(intRegEx.cap(1).toInt() - 1); + pEffectSlot->getEffectButtonParameterSlot(match.captured(1).toInt() - 1); return pParameterSlot; } diff --git a/src/engine/sidechain/shoutconnection.cpp b/src/engine/sidechain/shoutconnection.cpp index d6d2db18fbc2..2e86b4570080 100644 --- a/src/engine/sidechain/shoutconnection.cpp +++ b/src/engine/sidechain/shoutconnection.cpp @@ -38,6 +38,9 @@ const int kMaxNetworkCache = 491520; // 10 s mp3 @ 192 kbit/s // http://wiki.shoutcast.com/wiki/SHOUTcast_DNAS_Server_2 const int kMaxShoutFailures = 3; +const QRegularExpression kArtistOrTitleRegex(QStringLiteral("\\$artist|\\$title")); +const QRegularExpression kArtistRegex(QStringLiteral("\\$artist")); + const mixxx::Logger kLogger("ShoutConnection"); } // namespace @@ -842,13 +845,12 @@ void ShoutConnection::updateMetaData() { do { // find the next occurrence replaceIndex = metadataFinal.indexOf( - QRegExp("\\$artist|\\$title"), - replaceIndex); + kArtistOrTitleRegex, + replaceIndex); if (replaceIndex != -1) { if (metadataFinal.indexOf( - QRegExp("\\$artist"), replaceIndex) - == replaceIndex) { + kArtistRegex, replaceIndex) == replaceIndex) { metadataFinal.replace(replaceIndex, 7, artist); // skip to the end of the replacement replaceIndex += artist.length(); diff --git a/src/library/basetrackcache.h b/src/library/basetrackcache.h index 1aeb5dc945d5..22624ec39f85 100644 --- a/src/library/basetrackcache.h +++ b/src/library/basetrackcache.h @@ -108,7 +108,7 @@ class BaseTrackCache : public QObject { const QVariant& val1, const QVariant& val2) const; bool trackMatches(const TrackPointer& pTrack, - const QRegExp& matcher) const; + const QRegularExpression& matcher) const; bool trackMatchesNumeric(const TrackPointer& pTrack, const QStringList& numberMatchers) const; bool trackMatchesNamedString(const TrackPointer& pTrack, diff --git a/src/library/coverartutils.cpp b/src/library/coverartutils.cpp index 59d49c64f7c9..e024f79320d5 100644 --- a/src/library/coverartutils.cpp +++ b/src/library/coverartutils.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include "sources/soundsourceproxy.h" @@ -56,8 +57,8 @@ QImage CoverArtUtils::extractEmbeddedCover( //static QList CoverArtUtils::findPossibleCoversInFolder(const QString& folder) { // Search for image files in the track directory. - QRegExp coverArtFilenames(supportedCoverArtExtensionsRegex(), - Qt::CaseInsensitive); + QRegularExpression coverArtFilenames(supportedCoverArtExtensionsRegex(), + QRegularExpression::CaseInsensitiveOption); QDirIterator it(folder, QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot); QFile currentFile; @@ -66,8 +67,8 @@ QList CoverArtUtils::findPossibleCoversInFolder(const QString& folder while (it.hasNext()) { it.next(); currentFileInfo = it.fileInfo(); - if (currentFileInfo.isFile() && - coverArtFilenames.indexIn(currentFileInfo.fileName()) != -1) { + const QRegularExpressionMatch match = coverArtFilenames.match(currentFileInfo.fileName()); + if (currentFileInfo.isFile() && match.hasMatch()) { possibleCovers.append(currentFileInfo); } } diff --git a/src/library/dao/trackdao.cpp b/src/library/dao/trackdao.cpp index 95f796f051ff..03e0be89cf4b 100644 --- a/src/library/dao/trackdao.cpp +++ b/src/library/dao/trackdao.cpp @@ -5,7 +5,6 @@ #include #include #include -#include #include #include diff --git a/src/library/proxytrackmodel.cpp b/src/library/proxytrackmodel.cpp index f926a7b29f18..8579b4eb9e9b 100644 --- a/src/library/proxytrackmodel.cpp +++ b/src/library/proxytrackmodel.cpp @@ -141,7 +141,7 @@ bool ProxyTrackModel::filterAcceptsRow(int sourceRow, dynamic_cast(m_pTrackModel); bool rowMatches = false; - QRegExp filter = filterRegExp(); + QRegularExpression filter = filterRegularExpression(); QListIterator iter(filterColumns); while (!rowMatches && iter.hasNext()) { diff --git a/src/library/scanner/libraryscanner.cpp b/src/library/scanner/libraryscanner.cpp index 7be52d6f6721..72bb4816b0ef 100644 --- a/src/library/scanner/libraryscanner.cpp +++ b/src/library/scanner/libraryscanner.cpp @@ -200,10 +200,10 @@ void LibraryScanner::slotStartScan() { QSet trackLocations = m_trackDao.getAllTrackLocations(); QHash directoryHashes = m_libraryHashDao.getDirectoryHashes(); - QRegExp extensionFilter(SoundSourceProxy::getSupportedFileNamesRegex()); - QRegExp coverExtensionFilter = - QRegExp(CoverArtUtils::supportedCoverArtExtensionsRegex(), - Qt::CaseInsensitive); + QRegularExpression extensionFilter(SoundSourceProxy::getSupportedFileNamesRegex()); + QRegularExpression coverExtensionFilter = + QRegularExpression(CoverArtUtils::supportedCoverArtExtensionsRegex(), + QRegularExpression::CaseInsensitiveOption); QStringList directoryBlacklist = ScannerUtil::getDirectoryBlacklist(); m_scannerGlobal = ScannerGlobalPointer( diff --git a/src/library/scanner/recursivescandirectorytask.cpp b/src/library/scanner/recursivescandirectorytask.cpp index 3c8e8152c3bb..67a9cf733f44 100644 --- a/src/library/scanner/recursivescandirectorytask.cpp +++ b/src/library/scanner/recursivescandirectorytask.cpp @@ -43,11 +43,11 @@ void RecursiveScanDirectoryTask::run() { QCryptographicHash hasher(QCryptographicHash::Sha256); - // TODO(rryan) benchmark QRegExp copy versus QMutex/QRegExp in ScannerGlobal + // TODO(rryan) benchmark QRegularExpression copy versus QMutex/QRegularExpression in ScannerGlobal // versus slicing the extension off and checking for set/list containment. - QRegExp supportedExtensionsRegex = + QRegularExpression supportedExtensionsRegex = m_scannerGlobal->supportedExtensionsRegex(); - QRegExp supportedCoverExtensionsRegex = + QRegularExpression supportedCoverExtensionsRegex = m_scannerGlobal->supportedCoverExtensionsRegex(); while (it.hasNext()) { @@ -56,11 +56,17 @@ void RecursiveScanDirectoryTask::run() { if (currentFileInfo.isFile()) { const QString& fileName = currentFileInfo.fileName(); - if (supportedExtensionsRegex.indexIn(fileName) != -1) { + const QRegularExpressionMatch supportedExtensionsMatch = + supportedExtensionsRegex.match(fileName); + if (supportedExtensionsMatch.hasMatch()) { hasher.addData(currentFile.toUtf8()); filesToImport.push_back(currentFileInfo); - } else if (supportedCoverExtensionsRegex.indexIn(fileName) != -1) { - possibleCovers.push_back(currentFileInfo); + } else { + const QRegularExpressionMatch supportedCoverExtensionsMatch = + supportedCoverExtensionsRegex.match(fileName); + if (supportedCoverExtensionsMatch.hasMatch()) { + possibleCovers.push_back(currentFileInfo); + } } } else { // File is a directory diff --git a/src/library/scanner/scannerglobal.h b/src/library/scanner/scannerglobal.h index 18aaa4ad4574..82687e9a6858 100644 --- a/src/library/scanner/scannerglobal.h +++ b/src/library/scanner/scannerglobal.h @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include #include @@ -19,8 +19,8 @@ class ScannerGlobal { public: ScannerGlobal(const QSet& trackLocations, const QHash& directoryHashes, - const QRegExp& supportedExtensionsMatcher, - const QRegExp& supportedCoverExtensionsMatcher, + const QRegularExpression& supportedExtensionsMatcher, + const QRegularExpression& supportedCoverExtensionsMatcher, const QStringList& directoriesBlacklist) : m_trackLocations(trackLocations), m_directoryHashes(directoryHashes), @@ -51,7 +51,7 @@ class ScannerGlobal { return m_directoriesBlacklist.contains(directoryPath); } - const QRegExp& supportedExtensionsRegex() const { + const QRegularExpression& supportedExtensionsRegex() const { return m_supportedExtensionsMatcher; } @@ -77,20 +77,22 @@ class ScannerGlobal { return m_directoriesUnhashed; } - // TODO(rryan) test whether tasks should create their own QRegExp. + // TODO(rryan) test whether tasks should create their own QRegularExpression. bool isAudioFileSupported(const QString& fileName) const { const auto locker = lockMutex(&m_supportedExtensionsMatcherMutex); - return m_supportedExtensionsMatcher.indexIn(fileName) != -1; + QRegularExpressionMatch match = m_supportedCoverExtensionsMatcher.match(fileName); + return match.hasMatch(); } - const QRegExp& supportedCoverExtensionsRegex() const { + const QRegularExpression& supportedCoverExtensionsRegex() const { return m_supportedCoverExtensionsMatcher; } - // TODO(rryan) test whether tasks should create their own QRegExp. + // TODO(rryan) test whether tasks should create their own QRegularExpression. bool isCoverFileSupported(const QString& fileName) const { const auto locker = lockMutex(&m_supportedCoverExtensionsMatcherMutex); - return m_supportedCoverExtensionsMatcher.indexIn(fileName) != -1; + QRegularExpressionMatch match = m_supportedCoverExtensionsMatcher.match(fileName); + return match.hasMatch(); } bool shouldCancel() const { @@ -159,10 +161,10 @@ class ScannerGlobal { QHash m_directoryHashes; mutable QMutex m_supportedExtensionsMatcherMutex; - QRegExp m_supportedExtensionsMatcher; + QRegularExpression m_supportedExtensionsMatcher; mutable QMutex m_supportedCoverExtensionsMatcherMutex; - QRegExp m_supportedCoverExtensionsMatcher; + QRegularExpression m_supportedCoverExtensionsMatcher; // This set will grow during a scan by successively // inserting the canonical paths of directories that diff --git a/src/library/searchquery.cpp b/src/library/searchquery.cpp index 32266cdafaf2..027c011f9c37 100644 --- a/src/library/searchquery.cpp +++ b/src/library/searchquery.cpp @@ -1,5 +1,6 @@ #include "library/searchquery.h" +#include #include #include "library/dao/trackschema.h" @@ -10,6 +11,19 @@ #include "util/db/dbconnection.h" #include "util/db/sqllikewildcards.h" +namespace { +const QRegularExpression kDurationRegex(QStringLiteral("^(\\d+)(m|:)?([0-5]?\\d)?s?$")); + +// The ordering of operator alternatives separated by '|' is crucial to avoid incomplete +// partial matches, e.g. by capturing "<" + "=" + instead of "<=" + ! +// +// See also: https://perldoc.perl.org/perlre +// > Alternatives are tried from left to right, so the first alternative found for which +// > the entire expression matches, is the one that is chosen. This means that alternatives +// > are not necessarily greedy. +const QRegularExpression kNumericOperatorRegex(QStringLiteral("^(<=|>=|=|<|>)(.*)$")); +} // namespace + QVariant getTrackValueForColumn(const TrackPointer& pTrack, const QString& column) { if (column == LIBRARYTABLE_ARTIST) { return pTrack->getArtist(); @@ -287,10 +301,10 @@ void NumericFilterNode::init(QString argument) { return; } - QRegExp operatorMatcher("^(>|>=|=|<|<=)(.*)$"); - if (operatorMatcher.indexIn(argument) != -1) { - m_operator = operatorMatcher.cap(1); - argument = operatorMatcher.cap(2); + QRegularExpressionMatch match = kNumericOperatorRegex.match(argument); + if (match.hasMatch()) { + m_operator = match.captured(1); + argument = match.captured(2); } bool parsed = false; @@ -411,8 +425,8 @@ DurationFilterNode::DurationFilterNode( } double DurationFilterNode::parse(const QString& arg, bool* ok) { - QRegExp regex("^(\\d*)(m|:)?([0-6]?\\d)?s?$"); - if (regex.indexIn(arg) == -1) { + QRegularExpressionMatch match = kDurationRegex.match(arg); + if (!match.hasMatch()) { *ok = false; return 0; } @@ -421,15 +435,14 @@ double DurationFilterNode::parse(const QString& arg, bool* ok) { // seconds are in the 4th entry. If you don't believe me or this doesn't // work anymore because we changed our Qt version just have a look at caps. // -- (kain88, Aug 2014) - QStringList caps = regex.capturedTexts(); double m = 0; double s = 0; // if only a number is entered parse as seconds - if (caps.at(3).isEmpty() && caps.at(2).isEmpty()) { - s = caps.at(1).toDouble(ok); + if (match.captured(3).isEmpty() && match.captured(2).isEmpty()) { + s = match.captured(1).toDouble(ok); } else { - m = caps.at(1).toDouble(ok); - s = caps.at(3).toDouble(); + m = match.captured(1).toDouble(ok); + s = match.captured(3).toDouble(); } if (!*ok) { diff --git a/src/library/searchquery.h b/src/library/searchquery.h index bf6125d007ad..b6fa1ee7504a 100644 --- a/src/library/searchquery.h +++ b/src/library/searchquery.h @@ -2,7 +2,6 @@ #define SEARCHQUERY_H #include -#include #include #include #include diff --git a/src/library/searchqueryparser.cpp b/src/library/searchqueryparser.cpp index 756f4326d1a3..a5c7740c3a2a 100644 --- a/src/library/searchqueryparser.cpp +++ b/src/library/searchqueryparser.cpp @@ -58,10 +58,12 @@ SearchQueryParser::SearchQueryParser(TrackCollection* pTrackCollection) m_allFilters.append(m_numericFilters); m_allFilters.append(m_specialFilters); - m_fuzzyMatcher = QRegExp(QString("^~(%1)$").arg(m_allFilters.join("|"))); - m_textFilterMatcher = QRegExp(QString("^-?(%1):(.*)$").arg(m_textFilters.join("|"))); - m_numericFilterMatcher = QRegExp(QString("^-?(%1):(.*)$").arg(m_numericFilters.join("|"))); - m_specialFilterMatcher = QRegExp(QString("^[~-]?(%1):(.*)$").arg(m_specialFilters.join("|"))); + m_fuzzyMatcher = QRegularExpression(QString("^~(%1)$").arg(m_allFilters.join("|"))); + m_textFilterMatcher = QRegularExpression(QString("^-?(%1):(.*)$").arg(m_textFilters.join("|"))); + m_numericFilterMatcher = QRegularExpression( + QString("^-?(%1):(.*)$").arg(m_numericFilters.join("|"))); + m_specialFilterMatcher = QRegularExpression( + QString("^[~-]?(%1):(.*)$").arg(m_specialFilters.join("|"))); } SearchQueryParser::~SearchQueryParser() { @@ -140,12 +142,16 @@ void SearchQueryParser::parseTokens(QStringList tokens, bool negate = token.startsWith(kNegatePrefix); std::unique_ptr pNode; - if (m_fuzzyMatcher.indexIn(token) != -1) { + const QRegularExpressionMatch fuzzyMatch = m_fuzzyMatcher.match(token); + const QRegularExpressionMatch textFilterMatch = m_textFilterMatcher.match(token); + const QRegularExpressionMatch numericFilterMatch = m_numericFilterMatcher.match(token); + const QRegularExpressionMatch specialFilterMatch = m_specialFilterMatcher.match(token); + if (fuzzyMatch.hasMatch()) { // TODO(XXX): implement this feature. - } else if (m_textFilterMatcher.indexIn(token) != -1) { - QString field = m_textFilterMatcher.cap(1); + } else if (textFilterMatch.hasMatch()) { + QString field = textFilterMatch.captured(1); QString argument = getTextArgument( - m_textFilterMatcher.cap(2), &tokens); + textFilterMatch.captured(2), &tokens); if (argument == kMissingFieldSearchTerm) { qDebug() << "argument explicit empty"; @@ -168,10 +174,11 @@ void SearchQueryParser::parseTokens(QStringList tokens, m_fieldToSqlColumns[field], argument); } } - } else if (m_numericFilterMatcher.indexIn(token) != -1) { - QString field = m_numericFilterMatcher.cap(1); + } else if (numericFilterMatch.hasMatch()) { + QString field = numericFilterMatch.captured(1); QString argument = getTextArgument( - m_numericFilterMatcher.cap(2), &tokens).trimmed(); + numericFilterMatch.captured(2), &tokens) + .trimmed(); if (!argument.isEmpty()) { if (argument == kMissingFieldSearchTerm) { @@ -182,11 +189,12 @@ void SearchQueryParser::parseTokens(QStringList tokens, m_fieldToSqlColumns[field], argument); } } - } else if (m_specialFilterMatcher.indexIn(token) != -1) { + } else if (specialFilterMatch.hasMatch()) { bool fuzzy = token.startsWith(kFuzzyPrefix); - QString field = m_specialFilterMatcher.cap(1); + QString field = specialFilterMatch.captured(1); QString argument = getTextArgument( - m_specialFilterMatcher.cap(2), &tokens).trimmed(); + specialFilterMatch.captured(2), &tokens) + .trimmed(); if (!argument.isEmpty()) { if (field == "key") { mixxx::track::io::key::ChromaticKey key = diff --git a/src/library/searchqueryparser.h b/src/library/searchqueryparser.h index 9878149c0a7b..e6f6599c8391 100644 --- a/src/library/searchqueryparser.h +++ b/src/library/searchqueryparser.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include @@ -36,11 +36,11 @@ class SearchQueryParser { QStringList m_allFilters; QHash m_fieldToSqlColumns; - QRegExp m_fuzzyMatcher; - QRegExp m_textFilterMatcher; - QRegExp m_crateFilterMatcher; - QRegExp m_numericFilterMatcher; - QRegExp m_specialFilterMatcher; + QRegularExpression m_fuzzyMatcher; + QRegularExpression m_textFilterMatcher; + QRegularExpression m_crateFilterMatcher; + QRegularExpression m_numericFilterMatcher; + QRegularExpression m_specialFilterMatcher; DISALLOW_COPY_AND_ASSIGN(SearchQueryParser); }; diff --git a/src/preferences/broadcastprofile.cpp b/src/preferences/broadcastprofile.cpp index 4bf00a59d772..0640c485792d 100644 --- a/src/preferences/broadcastprofile.cpp +++ b/src/preferences/broadcastprofile.cpp @@ -1,10 +1,10 @@ #include #include #include -#include -#include +#include #include #include +#include #ifdef __QTKEYCHAIN__ #include @@ -79,9 +79,10 @@ const QString kDefaultStreamDesc = const QString kDefaultStreamGenre = QObject::tr("Live Mix"); constexpr bool kDefaultStreamPublic = false; -const QRegExp kForbiddenChars = - QRegExp("[<>:\"\\/|?*\\\\]|(\\.\\.)" - "|CON|AUX|PRN|COM(\\d+)|LPT(\\d+)|NUL"); +const QRegularExpression kForbiddenChars = + QRegularExpression(QStringLiteral( + "[<>:\"\\/|?*\\\\]|(\\.\\.)" + "|CON|AUX|PRN|COM(\\d+)|LPT(\\d+)|NUL")); const mixxx::Logger kLogger("BroadcastProfile"); } // anonymous namespace diff --git a/src/preferences/colorpalettesettings.cpp b/src/preferences/colorpalettesettings.cpp index 227019449122..8fdcf0a785ae 100644 --- a/src/preferences/colorpalettesettings.cpp +++ b/src/preferences/colorpalettesettings.cpp @@ -1,5 +1,7 @@ #include "preferences/colorpalettesettings.h" +#include + #include "util/color/predefinedcolorpalettes.h" namespace { @@ -7,7 +9,7 @@ const mixxx::RgbColor kColorBlack(0x000000); const QString kColorPaletteConfigGroup = QStringLiteral("[Config]"); const QString kColorPaletteGroupStart = QStringLiteral("[ColorPalette "); const QString kColorPaletteGroupEnd = QStringLiteral("]"); -const QRegExp kColorPaletteGroupNameRegex(QStringLiteral("^\\[ColorPalette (.+)\\]$")); +const QRegularExpression kColorPaletteGroupNameRegex(QStringLiteral("^\\[ColorPalette (.+)\\]$")); const QString kColorPaletteHotcueIndicesConfigItem = QStringLiteral("hotcue_indices"); const QString kColorPaletteHotcueIndicesConfigSeparator = QStringLiteral(" "); const QString kColorPaletteGroup = QStringLiteral("[ColorPalette %1]"); @@ -166,9 +168,9 @@ QSet ColorPaletteSettings::getColorPaletteNames() const { QSet names; const QSet groups = m_pConfig->getGroups(); for (const auto& group : groups) { - int pos = kColorPaletteGroupNameRegex.indexIn(group); - if (pos > -1) { - names.insert(kColorPaletteGroupNameRegex.cap(1)); + const QRegularExpressionMatch match = kColorPaletteGroupNameRegex.match(group); + if (match.hasMatch()) { + names.insert(match.captured(1)); } } return names; diff --git a/src/skin/legacy/legacyskin.cpp b/src/skin/legacy/legacyskin.cpp index 8880b9faf5cb..90d7675e4c7a 100644 --- a/src/skin/legacy/legacyskin.cpp +++ b/src/skin/legacy/legacyskin.cpp @@ -5,7 +5,8 @@ namespace { -const QRegExp kMinSizeRegExp("(\\d+), *(\\d+)<"); +const QRegularExpression kMinSizeRegExp(QStringLiteral("(\\d+), *(\\d+)<")); +const QRegularExpression kDigitRegex(QStringLiteral("\\d")); const QString kSkinManifestFileName(QStringLiteral("skin.xml")); } // namespace @@ -89,22 +90,24 @@ bool LegacySkin::fitsScreenSize(const QScreen& screen) const { if (file.open(QFile::ReadOnly | QFile::Text)) { QTextStream in(&file); bool found_size = false; + QRegularExpressionMatch match; while (!in.atEnd()) { - if (kMinSizeRegExp.indexIn(in.readLine()) != -1) { + match = kMinSizeRegExp.match(in.readLine()); + if (match.hasMatch()) { found_size = true; break; } } if (found_size) { - return !(kMinSizeRegExp.cap(1).toInt() > screenSize.width() || - kMinSizeRegExp.cap(2).toInt() > screenSize.height()); + return !(match.captured(1).toInt() > screenSize.width() || + match.captured(2).toInt() > screenSize.height()); } } // If regex failed, fall back to skin name parsing. - QString skinName = name().left(name().indexOf(QRegExp("\\d"))); + QString skinName = name().left(name().indexOf(kDigitRegex)); QString resName = name().right(name().count() - skinName.count()); - QString res = resName.left(resName.lastIndexOf(QRegExp("\\d")) + 1); + QString res = resName.left(resName.lastIndexOf(kDigitRegex) + 1); QString skinWidth = res.left(res.indexOf("x")); QString skinHeight = res.right(res.count() - skinWidth.count() - 1); return skinWidth.toInt() <= screenSize.width() && diff --git a/src/skin/legacy/skincontext.h b/src/skin/legacy/skincontext.h index 06ecdd2f6237..d8d353003b37 100644 --- a/src/skin/legacy/skincontext.h +++ b/src/skin/legacy/skincontext.h @@ -1,20 +1,19 @@ #pragma once -#include - +#include +#include +#include #include +#include #include -#include -#include -#include #include -#include +#include #include "preferences/usersettings.h" #include "skin/legacy/pixmapsource.h" #include "util/color/color.h" -#include "widget/wsingletoncontainer.h" #include "widget/wpixmapstore.h" +#include "widget/wsingletoncontainer.h" #define SKIN_WARNING(node, context) (context).logWarning(__FILE__, __LINE__, (node)) @@ -236,7 +235,7 @@ class SkinContext { return m_pSharedState->singletons.getSingletonWidget(objectName); } - const QRegExp& getHookRegex() const { + const QRegularExpression& getHookRegex() const { return m_hookRx; } @@ -281,7 +280,7 @@ class SkinContext { std::shared_ptr m_pSharedState; QHash m_variables; - QRegExp m_hookRx; + QRegularExpression m_hookRx; double m_scaleFactor; }; diff --git a/src/sources/soundsourceproxy.cpp b/src/sources/soundsourceproxy.cpp index cc7732340162..7d1d1724840d 100644 --- a/src/sources/soundsourceproxy.cpp +++ b/src/sources/soundsourceproxy.cpp @@ -1,6 +1,7 @@ #include "sources/soundsourceproxy.h" #include +#include #include #include "sources/audiosourcetrackproxy.h" @@ -46,7 +47,7 @@ //Static memory allocation /*static*/ mixxx::SoundSourceProviderRegistry SoundSourceProxy::s_soundSourceProviders; /*static*/ QStringList SoundSourceProxy::s_supportedFileNamePatterns; -/*static*/ QRegExp SoundSourceProxy::s_supportedFileNamesRegex; +/*static*/ QRegularExpression SoundSourceProxy::s_supportedFileNamesRegex; namespace { @@ -243,8 +244,8 @@ bool SoundSourceProxy::registerProviders() { // Build regular expression of supported file extensions QString supportedFileExtensionsRegex( RegexUtils::fileExtensionsRegex(supportedFileExtensions)); - s_supportedFileNamesRegex = - QRegExp(supportedFileExtensionsRegex, Qt::CaseInsensitive); + s_supportedFileNamesRegex = QRegularExpression(supportedFileExtensionsRegex, + QRegularExpression::CaseInsensitiveOption); return true; } diff --git a/src/sources/soundsourceproxy.h b/src/sources/soundsourceproxy.h index 0a26cac367a9..679e30daa724 100644 --- a/src/sources/soundsourceproxy.h +++ b/src/sources/soundsourceproxy.h @@ -29,7 +29,7 @@ class SoundSourceProxy { static const QStringList& getSupportedFileNamePatterns() { return s_supportedFileNamePatterns; } - static const QRegExp& getSupportedFileNamesRegex() { + static const QRegularExpression& getSupportedFileNamesRegex() { return s_supportedFileNamesRegex; } @@ -165,7 +165,7 @@ class SoundSourceProxy { private: static mixxx::SoundSourceProviderRegistry s_soundSourceProviders; static QStringList s_supportedFileNamePatterns; - static QRegExp s_supportedFileNamesRegex; + static QRegularExpression s_supportedFileNamesRegex; friend class TrackCollectionManager; static ExportTrackMetadataResult exportTrackMetadataBeforeSaving( diff --git a/src/test/searchqueryparsertest.cpp b/src/test/searchqueryparsertest.cpp index ae333c6a67da..25b9893e9059 100644 --- a/src/test/searchqueryparsertest.cpp +++ b/src/test/searchqueryparsertest.cpp @@ -682,6 +682,12 @@ TEST_F(SearchQueryParserTest, HumanReadableDurationSearchWithOperators) { EXPECT_STREQ( qPrintable(QString("duration >= 63")), qPrintable(pQuery->toSql())); + + // Seconds out of range + pQuery = m_parser.parseQuery("duration:>=1:60", searchColumns, ""); + pTrack->setDuration(60); + EXPECT_FALSE(pQuery->match(pTrack)); + EXPECT_TRUE(pQuery->toSql().isEmpty()); } TEST_F(SearchQueryParserTest, HumanReadableDurationSearchwithRangeFilter) { diff --git a/src/track/keyutils.cpp b/src/track/keyutils.cpp index 6189d3bb12c6..5d020f597882 100644 --- a/src/track/keyutils.cpp +++ b/src/track/keyutils.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include "util/math.h" @@ -15,19 +15,28 @@ using mixxx::track::io::key::ChromaticKey; using mixxx::track::io::key::ChromaticKey_IsValid; +// All of these regular expressions need exact matching. +// QRegularExpression::anchoredPattern cannot be used because Mixxx supports Qt < 5.15, so +// instead do what QRegularExpression::anchoredPattern by wrapping each regex in \\A(?: ... )\\z + // OpenKey notation, the numbers 1-12 followed by d (dur, major) or m (moll, minor). -static const QString s_openKeyPattern("^\\s*(1[0-2]|[1-9])([dm])\\s*$"); +static const QRegularExpression s_openKeyRegex(QStringLiteral( + "\\A(?:^\\s*(1[0-2]|[1-9])([dm])\\s*$)\\z"), + QRegularExpression::CaseInsensitiveOption); // Lancelot notation, the numbers 1-12 followed by a (minor) or b (major). -static const QString s_lancelotKeyPattern("^\\s*(1[0-2]|[1-9])([ab])\\s*$"); +static const QRegularExpression s_lancelotKeyRegex( + QStringLiteral("\\A(?:^\\s*(1[0-2]|[1-9])([ab])\\s*$)\\z"), + QRegularExpression::CaseInsensitiveOption); // a-g followed by any number of sharps or flats, optionally followed by // a scale spec (m = minor, min, maj) // anchor the pattern so we don't get accidental sub-string matches // (?:or)? allows unabbreviated major|minor without capturing -static const QString s_keyPattern = QString::fromUtf8( - "^\\s*([a-g])([#♯b♭]*)" - "(min(?:or)?|maj(?:or)?|m)?\\s*$"); +static const QRegularExpression s_keyRegex(QString::fromUtf8( + "\\A(?:^\\s*([a-g])([#♯b♭]*)" + "(min(?:or)?|maj(?:or)?|m)?\\s*$)\\z"), + QRegularExpression::CaseInsensitiveOption); static const QString s_sharpSymbol = QString::fromUtf8("♯"); //static const QString s_flatSymbol = QString::fromUtf8("♭"); @@ -264,26 +273,26 @@ ChromaticKey KeyUtils::guessKeyFromText(const QString& text) { } } - QRegExp openKeyMatcher(s_openKeyPattern, Qt::CaseInsensitive); - if (openKeyMatcher.exactMatch(trimmed)) { + QRegularExpressionMatch openKeyMatch = s_openKeyRegex.match(trimmed); + if (openKeyMatch.hasMatch()) { bool ok = false; - int openKeyNumber = openKeyMatcher.cap(1).toInt(&ok); + int openKeyNumber = openKeyMatch.captured(1).toInt(&ok); // Regex should mean this never happens. if (!ok || openKeyNumber < 1 || openKeyNumber > 12) { return mixxx::track::io::key::INVALID; } - bool major = openKeyMatcher.cap(2) - .compare("d", Qt::CaseInsensitive) == 0; + bool major = openKeyMatch.captured(2) + .compare("d", Qt::CaseInsensitive) == 0; return openKeyNumberToKey(openKeyNumber, major); } - QRegExp lancelotKeyMatcher(s_lancelotKeyPattern, Qt::CaseInsensitive); - if (lancelotKeyMatcher.exactMatch(trimmed)) { + QRegularExpressionMatch lancelotMatch = s_lancelotKeyRegex.match(trimmed); + if (lancelotMatch.hasMatch()) { bool ok = false; - int lancelotNumber = lancelotKeyMatcher.cap(1).toInt(&ok); + int lancelotNumber = lancelotMatch.captured(1).toInt(&ok); // Regex should mean this never happens. if (!ok || lancelotNumber < 1 || lancelotNumber > 12) { @@ -292,24 +301,24 @@ ChromaticKey KeyUtils::guessKeyFromText(const QString& text) { int openKeyNumber = lancelotNumberToOpenKeyNumber(lancelotNumber); - bool major = lancelotKeyMatcher.cap(2) - .compare("b", Qt::CaseInsensitive) == 0; + bool major = lancelotMatch.captured(2) + .compare("b", Qt::CaseInsensitive) == 0; return openKeyNumberToKey(openKeyNumber, major); } - QRegExp keyMatcher(s_keyPattern, Qt::CaseInsensitive); - if (keyMatcher.exactMatch(trimmed)) { + QRegularExpressionMatch keyMatch = s_keyRegex.match(trimmed); + if (keyMatch.hasMatch()) { // Take the first letter, lowercase it and subtract 'a' and we get a // number between 0-6. Look up the major key associated with that letter // from s_letterToMajorKey. Upper-case means major, lower-case means // minor. Then apply the sharps or flats to the key. - QChar letter = keyMatcher.cap(1).at(0); + QChar letter = keyMatch.captured(1).at(0); int letterIndex = letter.toLower().toLatin1() - 'a'; bool major = letter.isUpper(); // Now apply sharps and flats to the letter key. - QString adjustments = keyMatcher.cap(2); + QString adjustments = keyMatch.captured(2); int steps = 0; for (const auto* it = adjustments.constBegin(); it != adjustments.constEnd(); @@ -317,7 +326,7 @@ ChromaticKey KeyUtils::guessKeyFromText(const QString& text) { steps += (*it == '#' || *it == s_sharpSymbol[0]) ? 1 : -1; } - QString scale = keyMatcher.cap(3); + QString scale = keyMatch.captured(3); // we override major if a scale definition exists if (! scale.isEmpty()) { if (scale.compare("m", Qt::CaseInsensitive) == 0) { diff --git a/src/util/dnd.cpp b/src/util/dnd.cpp index 0e3a9f008668..1d1165f27f2a 100644 --- a/src/util/dnd.cpp +++ b/src/util/dnd.cpp @@ -1,7 +1,5 @@ #include "util/dnd.h" -#include - #include "control/controlobject.h" #include "library/parserm3u.h" #include "library/parserpls.h" diff --git a/src/util/regex.h b/src/util/regex.h index 527d0b3ffe35..e3c59368d455 100644 --- a/src/util/regex.h +++ b/src/util/regex.h @@ -1,6 +1,11 @@ #pragma once +// QRegularExpression::escape was introduced in Qt 5.15. +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) +#include +#else #include +#endif #include #include @@ -9,7 +14,11 @@ class RegexUtils { static QString fileExtensionsRegex(QStringList extensions) { // Escape every extension appropriately for (int i = 0; i < extensions.size(); ++i) { +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + extensions[i] = QRegularExpression::escape(extensions[i]); +#else extensions[i] = QRegExp::escape(extensions[i]); +#endif } // Turn the list into a "\\.(jpg|gif|etc)$" style regex string return QString("\\.(%1)$").arg(extensions.join("|")); diff --git a/src/vinylcontrol/vinylcontrolmanager.cpp b/src/vinylcontrol/vinylcontrolmanager.cpp index 2577a3be9bc6..97d85579647e 100644 --- a/src/vinylcontrol/vinylcontrolmanager.cpp +++ b/src/vinylcontrol/vinylcontrolmanager.cpp @@ -1,5 +1,7 @@ #include "vinylcontrol/vinylcontrolmanager.h" +#include + #include "control/controlobject.h" #include "control/controlproxy.h" #include "mixer/playermanager.h" @@ -12,6 +14,10 @@ #include "vinylcontrol/vinylcontrolprocessor.h" #include "vinylcontrol/vinylcontrolxwax.h" +namespace { +const QRegularExpression kChannelRegex(QStringLiteral("\\[Channel([1-9]\\d*)\\]")); +} + VinylControlManager::VinylControlManager(QObject* pParent, UserSettingsPointer pConfig, SoundManager* pSoundManager) @@ -123,10 +129,10 @@ bool VinylControlManager::vinylInputConnected(int deck) { } int VinylControlManager::vinylInputFromGroup(const QString& group) { - QRegExp channelMatcher("\\[Channel([1-9]\\d*)\\]"); - if (channelMatcher.exactMatch(group)) { + QRegularExpressionMatch channelMatch = kChannelRegex.match(group); + if (channelMatch.hasMatch()) { bool ok = false; - int input = channelMatcher.cap(1).toInt(&ok); + int input = channelMatch.captured(1).toInt(&ok); return ok ? input - 1 : -1; } return -1; diff --git a/src/widget/hexspinbox.cpp b/src/widget/hexspinbox.cpp index c58ef0fe8866..35fd6ca43008 100644 --- a/src/widget/hexspinbox.cpp +++ b/src/widget/hexspinbox.cpp @@ -2,6 +2,10 @@ #include "moc_hexspinbox.cpp" +namespace { +const QRegularExpression kValidationRegex(QStringLiteral("^0(x|X)[0-9A-Fa-f]+")); +} + HexSpinBox::HexSpinBox(QWidget* pParent) : QSpinBox(pParent) { setRange(0, 255); @@ -19,7 +23,6 @@ int HexSpinBox::valueFromText(const QString& text) const { } QValidator::State HexSpinBox::validate(QString& input, int& pos) const { - const QRegExp regExp("^0(x|X)[0-9A-Fa-f]+"); - QRegExpValidator validator(regExp, nullptr); + QRegularExpressionValidator validator(kValidationRegex, nullptr); return validator.validate(input, pos); } diff --git a/src/widget/wbeatspinbox.cpp b/src/widget/wbeatspinbox.cpp index 7876b2fd1dea..945790e541ba 100644 --- a/src/widget/wbeatspinbox.cpp +++ b/src/widget/wbeatspinbox.cpp @@ -1,13 +1,16 @@ #include "widget/wbeatspinbox.h" #include +#include #include "control/controlobject.h" #include "control/controlproxy.h" #include "moc_wbeatspinbox.cpp" #include "util/math.h" -QRegExp WBeatSpinBox::s_regexpBlacklist("[^0-9.,/ ]"); +namespace { +const QRegularExpression kBlockListRegex(QStringLiteral("[^0-9.,/ ]")); +} WBeatSpinBox::WBeatSpinBox(QWidget* parent, const ConfigKey& configKey, @@ -201,7 +204,8 @@ double WBeatSpinBox::valueFromText(const QString& text) const { QValidator::State WBeatSpinBox::validate(QString& input, int& pos) const { Q_UNUSED(pos); - if (input.contains(s_regexpBlacklist)) { + QRegularExpressionMatch blockListMatch = kBlockListRegex.match(input); + if (blockListMatch.hasMatch()) { return QValidator::Invalid; } if (input.isEmpty()) { diff --git a/src/widget/wbeatspinbox.h b/src/widget/wbeatspinbox.h index c88a990d6fde..b27eaaf60fbf 100644 --- a/src/widget/wbeatspinbox.h +++ b/src/widget/wbeatspinbox.h @@ -30,7 +30,6 @@ class WBeatSpinBox : public QDoubleSpinBox, public WBaseWidget { QString fractionString(int numerator, int denominator) const; ControlProxy m_valueControl; - static QRegExp s_regexpBlacklist; // for font scaling bool event(QEvent* pEvent) override;