/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Author: Milian Wolff, KDAB (milian.wolff@kdab.com) ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ #include "valgrindsettings.h" #include "valgrindplugin.h" #include "valgrindconfigwidget.h" #include #include #include #include #include const char numCallersC[] = "Analyzer.Valgrind.NumCallers"; const char leakCheckOnFinishC[] = "Analyzer.Valgrind.LeakCheckOnFinish"; const char showReachableC[] = "Analyzer.Valgrind.ShowReachable"; const char trackOriginsC[] = "Analyzer.Valgrind.TrackOrigins"; const char selfModifyingCodeDetectionC[] = "Analyzer.Valgrind.SelfModifyingCodeDetection"; const char suppressionFilesC[] = "Analyzer.Valgrind.SupressionFiles"; const char removedSuppressionFilesC[] = "Analyzer.Valgrind.RemovedSuppressionFiles"; const char addedSuppressionFilesC[] = "Analyzer.Valgrind.AddedSuppressionFiles"; const char filterExternalIssuesC[] = "Analyzer.Valgrind.FilterExternalIssues"; const char visibleErrorKindsC[] = "Analyzer.Valgrind.VisibleErrorKinds"; const char lastSuppressionDirectoryC[] = "Analyzer.Valgrind.LastSuppressionDirectory"; const char lastSuppressionHistoryC[] = "Analyzer.Valgrind.LastSuppressionHistory"; const char callgrindEnableCacheSimC[] = "Analyzer.Valgrind.Callgrind.EnableCacheSim"; const char callgrindEnableBranchSimC[] = "Analyzer.Valgrind.Callgrind.EnableBranchSim"; const char callgrindCollectSystimeC[] = "Analyzer.Valgrind.Callgrind.CollectSystime"; const char callgrindCollectBusEventsC[] = "Analyzer.Valgrind.Callgrind.CollectBusEvents"; const char callgrindEnableEventToolTipsC[] = "Analyzer.Valgrind.Callgrind.EnableEventToolTips"; const char callgrindMinimumCostRatioC[] = "Analyzer.Valgrind.Callgrind.MinimumCostRatio"; const char callgrindVisualisationMinimumCostRatioC[] = "Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio"; const char callgrindCycleDetectionC[] = "Analyzer.Valgrind.Callgrind.CycleDetection"; const char callgrindShortenTemplates[] = "Analyzer.Valgrind.Callgrind.ShortenTemplates"; const char callgrindCostFormatC[] = "Analyzer.Valgrind.Callgrind.CostFormat"; const char valgrindExeC[] = "Analyzer.Valgrind.ValgrindExecutable"; namespace Valgrind { namespace Internal { ////////////////////////////////////////////////////////////////// // // ValgrindBaseSettings // ////////////////////////////////////////////////////////////////// /** * Utility function to set @p val if @p key is present in @p map. */ template void setIfPresent(const QVariantMap &map, const QString &key, T *val) { if (map.contains(key)) *val = map.value(key).template value(); } void ValgrindBaseSettings::fromMap(const QVariantMap &map) { // General setIfPresent(map, QLatin1String(valgrindExeC), &m_valgrindExecutable); setIfPresent(map, QLatin1String(selfModifyingCodeDetectionC), (int*) &m_selfModifyingCodeDetection); // Memcheck setIfPresent(map, QLatin1String(numCallersC), &m_numCallers); setIfPresent(map, QLatin1String(leakCheckOnFinishC), (int*) &m_leakCheckOnFinish); setIfPresent(map, QLatin1String(showReachableC), &m_showReachable); setIfPresent(map, QLatin1String(trackOriginsC), &m_trackOrigins); setIfPresent(map, QLatin1String(filterExternalIssuesC), &m_filterExternalIssues); if (map.contains(QLatin1String(visibleErrorKindsC))) { m_visibleErrorKinds.clear(); foreach (const QVariant &val, map.value(QLatin1String(visibleErrorKindsC)).toList()) m_visibleErrorKinds << val.toInt(); } // Callgrind setIfPresent(map, QLatin1String(callgrindEnableCacheSimC), &m_enableCacheSim); setIfPresent(map, QLatin1String(callgrindEnableBranchSimC), &m_enableBranchSim); setIfPresent(map, QLatin1String(callgrindCollectSystimeC), &m_collectSystime); setIfPresent(map, QLatin1String(callgrindCollectBusEventsC), &m_collectBusEvents); setIfPresent(map, QLatin1String(callgrindEnableEventToolTipsC), &m_enableEventToolTips); setIfPresent(map, QLatin1String(callgrindMinimumCostRatioC), &m_minimumInclusiveCostRatio); setIfPresent(map, QLatin1String(callgrindVisualisationMinimumCostRatioC), &m_visualisationMinimumInclusiveCostRatio); emit changed(); } void ValgrindBaseSettings::toMap(QVariantMap &map) const { // General map.insert(QLatin1String(valgrindExeC), m_valgrindExecutable); map.insert(QLatin1String(selfModifyingCodeDetectionC), m_selfModifyingCodeDetection); // Memcheck map.insert(QLatin1String(numCallersC), m_numCallers); map.insert(QLatin1String(leakCheckOnFinishC), m_leakCheckOnFinish); map.insert(QLatin1String(showReachableC), m_showReachable); map.insert(QLatin1String(trackOriginsC), m_trackOrigins); map.insert(QLatin1String(filterExternalIssuesC), m_filterExternalIssues); QVariantList errorKinds; foreach (int i, m_visibleErrorKinds) errorKinds << i; map.insert(QLatin1String(visibleErrorKindsC), errorKinds); // Callgrind map.insert(QLatin1String(callgrindEnableCacheSimC), m_enableCacheSim); map.insert(QLatin1String(callgrindEnableBranchSimC), m_enableBranchSim); map.insert(QLatin1String(callgrindCollectSystimeC), m_collectSystime); map.insert(QLatin1String(callgrindCollectBusEventsC), m_collectBusEvents); map.insert(QLatin1String(callgrindEnableEventToolTipsC), m_enableEventToolTips); map.insert(QLatin1String(callgrindMinimumCostRatioC), m_minimumInclusiveCostRatio); map.insert(QLatin1String(callgrindVisualisationMinimumCostRatioC), m_visualisationMinimumInclusiveCostRatio); } void ValgrindBaseSettings::setValgrindExecutable(const QString &valgrindExecutable) { if (m_valgrindExecutable != valgrindExecutable) { m_valgrindExecutable = valgrindExecutable; emit valgrindExecutableChanged(valgrindExecutable); } } void ValgrindBaseSettings::setSelfModifyingCodeDetection(int smcDetection) { if (m_selfModifyingCodeDetection != smcDetection) { m_selfModifyingCodeDetection = (SelfModifyingCodeDetection) smcDetection; emit selfModifyingCodeDetectionChanged(smcDetection); } } QString ValgrindBaseSettings::valgrindExecutable() const { return m_valgrindExecutable; } ValgrindBaseSettings::SelfModifyingCodeDetection ValgrindBaseSettings::selfModifyingCodeDetection() const { return m_selfModifyingCodeDetection; } void ValgrindBaseSettings::setNumCallers(int numCallers) { if (m_numCallers != numCallers) { m_numCallers = numCallers; emit numCallersChanged(numCallers); } } void ValgrindBaseSettings::setLeakCheckOnFinish(int leakCheckOnFinish) { if (m_leakCheckOnFinish != leakCheckOnFinish) { m_leakCheckOnFinish = (LeakCheckOnFinish) leakCheckOnFinish; emit leakCheckOnFinishChanged(leakCheckOnFinish); } } void ValgrindBaseSettings::setShowReachable(bool showReachable) { if (m_showReachable != showReachable) { m_showReachable = showReachable; emit showReachableChanged(showReachable); } } void ValgrindBaseSettings::setTrackOrigins(bool trackOrigins) { if (m_trackOrigins != trackOrigins) { m_trackOrigins = trackOrigins; emit trackOriginsChanged(trackOrigins); } } void ValgrindBaseSettings::setFilterExternalIssues(bool filterExternalIssues) { if (m_filterExternalIssues != filterExternalIssues) { m_filterExternalIssues = filterExternalIssues; emit filterExternalIssuesChanged(filterExternalIssues); } } void ValgrindBaseSettings::setVisibleErrorKinds(const QList &visibleErrorKinds) { if (m_visibleErrorKinds != visibleErrorKinds) { m_visibleErrorKinds = visibleErrorKinds; emit visibleErrorKindsChanged(visibleErrorKinds); } } void ValgrindBaseSettings::setEnableCacheSim(bool enable) { if (m_enableCacheSim == enable) return; m_enableCacheSim = enable; emit enableCacheSimChanged(enable); } void ValgrindBaseSettings::setEnableBranchSim(bool enable) { if (m_enableBranchSim == enable) return; m_enableBranchSim = enable; emit enableBranchSimChanged(enable); } void ValgrindBaseSettings::setCollectSystime(bool collect) { if (m_collectSystime == collect) return; m_collectSystime = collect; emit collectSystimeChanged(collect); } void ValgrindBaseSettings::setCollectBusEvents(bool collect) { if (m_collectBusEvents == collect) return; m_collectBusEvents = collect; emit collectBusEventsChanged(collect); } void ValgrindBaseSettings::setEnableEventToolTips(bool enable) { if (m_enableEventToolTips == enable) return; m_enableEventToolTips = enable; emit enableEventToolTipsChanged(enable); } void ValgrindBaseSettings::setMinimumInclusiveCostRatio( double minimumInclusiveCostRatio) { if (m_minimumInclusiveCostRatio == minimumInclusiveCostRatio) return; m_minimumInclusiveCostRatio = qBound(0.0, minimumInclusiveCostRatio, 100.0); emit minimumInclusiveCostRatioChanged(minimumInclusiveCostRatio); } void ValgrindBaseSettings::setVisualisationMinimumInclusiveCostRatio( double minimumInclusiveCostRatio) { if (m_visualisationMinimumInclusiveCostRatio == minimumInclusiveCostRatio) return; m_visualisationMinimumInclusiveCostRatio = qBound(0.0, minimumInclusiveCostRatio, 100.0); emit visualisationMinimumInclusiveCostRatioChanged(minimumInclusiveCostRatio); } ////////////////////////////////////////////////////////////////// // // ValgrindGlobalSettings // ////////////////////////////////////////////////////////////////// ValgrindGlobalSettings::ValgrindGlobalSettings() { readSettings(); } QWidget *ValgrindGlobalSettings::createConfigWidget(QWidget *parent) { return new ValgrindConfigWidget(this, parent, true); } void ValgrindGlobalSettings::fromMap(const QVariantMap &map) { ValgrindBaseSettings::fromMap(map); // Memcheck m_suppressionFiles = map.value(QLatin1String(suppressionFilesC)).toStringList(); m_lastSuppressionDirectory = map.value(QLatin1String(lastSuppressionDirectoryC)).toString(); m_lastSuppressionHistory = map.value(QLatin1String(lastSuppressionHistoryC)).toStringList(); // Callgrind // special code as the default one does not cope with the enum properly if (map.contains(QLatin1String(callgrindCostFormatC))) m_costFormat = static_cast(map.value(QLatin1String(callgrindCostFormatC)).toInt()); setIfPresent(map, QLatin1String(callgrindCycleDetectionC), &m_detectCycles); setIfPresent(map, QLatin1String(callgrindShortenTemplates), &m_shortenTemplates); } void ValgrindGlobalSettings::toMap(QVariantMap &map) const { ValgrindBaseSettings::toMap(map); // Memcheck map.insert(QLatin1String(suppressionFilesC), m_suppressionFiles); map.insert(QLatin1String(lastSuppressionDirectoryC), m_lastSuppressionDirectory); map.insert(QLatin1String(lastSuppressionHistoryC), m_lastSuppressionHistory); // Callgrind map.insert(QLatin1String(callgrindCostFormatC), m_costFormat); map.insert(QLatin1String(callgrindCycleDetectionC), m_detectCycles); map.insert(QLatin1String(callgrindShortenTemplates), m_shortenTemplates); } // // Memcheck // QStringList ValgrindGlobalSettings::suppressionFiles() const { return m_suppressionFiles; } void ValgrindGlobalSettings::addSuppressionFiles(const QStringList &suppressions) { foreach (const QString &s, suppressions) if (!m_suppressionFiles.contains(s)) m_suppressionFiles.append(s); } void ValgrindGlobalSettings::removeSuppressionFiles(const QStringList &suppressions) { foreach (const QString &s, suppressions) m_suppressionFiles.removeAll(s); } QString ValgrindGlobalSettings::lastSuppressionDialogDirectory() const { return m_lastSuppressionDirectory; } void ValgrindGlobalSettings::setLastSuppressionDialogDirectory(const QString &directory) { m_lastSuppressionDirectory = directory; } QStringList ValgrindGlobalSettings::lastSuppressionDialogHistory() const { return m_lastSuppressionHistory; } void ValgrindGlobalSettings::setLastSuppressionDialogHistory(const QStringList &history) { m_lastSuppressionHistory = history; } static const char groupC[] = "Analyzer"; void ValgrindGlobalSettings::readSettings() { QVariantMap defaults; // General defaults.insert(QLatin1String(valgrindExeC), QLatin1String("valgrind")); defaults.insert(QLatin1String(selfModifyingCodeDetectionC), DetectSmcStackOnly); // Memcheck defaults.insert(QLatin1String(numCallersC), 25); defaults.insert(QLatin1String(leakCheckOnFinishC), LeakCheckOnFinishSummaryOnly); defaults.insert(QLatin1String(showReachableC), false); defaults.insert(QLatin1String(trackOriginsC), true); defaults.insert(QLatin1String(filterExternalIssuesC), true); QVariantList defaultErrorKinds; for (int i = 0; i < Valgrind::XmlProtocol::MemcheckErrorKindCount; ++i) defaultErrorKinds << i; defaults.insert(QLatin1String(visibleErrorKindsC), defaultErrorKinds); defaults.insert(QLatin1String(suppressionFilesC), QStringList()); defaults.insert(QLatin1String(lastSuppressionDirectoryC), QString()); defaults.insert(QLatin1String(lastSuppressionHistoryC), QStringList()); // Callgrind defaults.insert(QLatin1String(callgrindEnableCacheSimC), false); defaults.insert(QLatin1String(callgrindEnableBranchSimC), false); defaults.insert(QLatin1String(callgrindCollectSystimeC), false); defaults.insert(QLatin1String(callgrindCollectBusEventsC), false); defaults.insert(QLatin1String(callgrindEnableEventToolTipsC), true); defaults.insert(QLatin1String(callgrindMinimumCostRatioC), 0.01); defaults.insert(QLatin1String(callgrindVisualisationMinimumCostRatioC), 10.0); defaults.insert(QLatin1String(callgrindCostFormatC), CostDelegate::FormatRelative); defaults.insert(QLatin1String(callgrindCycleDetectionC), true); defaults.insert(QLatin1String(callgrindShortenTemplates), true); // Read stored values QSettings *settings = Core::ICore::settings(); settings->beginGroup(QLatin1String(groupC)); QVariantMap map = defaults; for (QVariantMap::ConstIterator it = defaults.constBegin(); it != defaults.constEnd(); ++it) map.insert(it.key(), settings->value(it.key(), it.value())); settings->endGroup(); fromMap(map); } void ValgrindGlobalSettings::writeSettings() const { QSettings *settings = Core::ICore::settings(); settings->beginGroup(QLatin1String(groupC)); QVariantMap map; toMap(map); for (QVariantMap::ConstIterator it = map.constBegin(); it != map.constEnd(); ++it) settings->setValue(it.key(), it.value()); settings->endGroup(); } // // Callgrind // CostDelegate::CostFormat ValgrindGlobalSettings::costFormat() const { return m_costFormat; } void ValgrindGlobalSettings::setCostFormat(CostDelegate::CostFormat format) { m_costFormat = format; writeSettings(); } bool ValgrindGlobalSettings::detectCycles() const { return m_detectCycles; } void ValgrindGlobalSettings::setDetectCycles(bool on) { m_detectCycles = on; writeSettings(); } bool ValgrindGlobalSettings::shortenTemplates() const { return m_shortenTemplates; } void ValgrindGlobalSettings::setShortenTemplates(bool on) { m_shortenTemplates = on; writeSettings(); } ////////////////////////////////////////////////////////////////// // // ValgrindProjectSettings // ////////////////////////////////////////////////////////////////// QWidget *ValgrindProjectSettings::createConfigWidget(QWidget *parent) { return new ValgrindConfigWidget(this, parent, false); } void ValgrindProjectSettings::fromMap(const QVariantMap &map) { ValgrindBaseSettings::fromMap(map); // Memcheck setIfPresent(map, QLatin1String(addedSuppressionFilesC), &m_addedSuppressionFiles); setIfPresent(map, QLatin1String(removedSuppressionFilesC), &m_disabledGlobalSuppressionFiles); } void ValgrindProjectSettings::toMap(QVariantMap &map) const { ValgrindBaseSettings::toMap(map); // Memcheck map.insert(QLatin1String(addedSuppressionFilesC), m_addedSuppressionFiles); map.insert(QLatin1String(removedSuppressionFilesC), m_disabledGlobalSuppressionFiles); } // // Memcheck // void ValgrindProjectSettings::addSuppressionFiles(const QStringList &suppressions) { QStringList globalSuppressions = ValgrindPlugin::globalSettings()->suppressionFiles(); foreach (const QString &s, suppressions) { if (m_addedSuppressionFiles.contains(s)) continue; m_disabledGlobalSuppressionFiles.removeAll(s); if (!globalSuppressions.contains(s)) m_addedSuppressionFiles.append(s); } } void ValgrindProjectSettings::removeSuppressionFiles(const QStringList &suppressions) { QStringList globalSuppressions = ValgrindPlugin::globalSettings()->suppressionFiles(); foreach (const QString &s, suppressions) { m_addedSuppressionFiles.removeAll(s); if (globalSuppressions.contains(s)) m_disabledGlobalSuppressionFiles.append(s); } } QStringList ValgrindProjectSettings::suppressionFiles() const { QStringList ret = ValgrindPlugin::globalSettings()->suppressionFiles(); foreach (const QString &s, m_disabledGlobalSuppressionFiles) ret.removeAll(s); ret.append(m_addedSuppressionFiles); return ret; } } // namespace Internal } // namespace Valgrind