├── app ├── appconfig.ini ├── worker.cpp ├── mainwindow_presenter.h ├── globals.cpp ├── globals.h ├── helper.h ├── worker.h ├── csvparser.h ├── jsonparser.h ├── appconfig.h ├── main.cpp ├── benchmarkdelegate.h ├── helper.cpp ├── benchmarkproxymodel.h ├── benchmark.h ├── abstractparser.cpp ├── abstractparser.h ├── benchmark.cpp ├── context.h ├── CMakeLists.txt ├── benchmarkview.h ├── chartviewwidget.h ├── app.pro ├── context.cpp ├── measurement.h ├── benchmarkproxymodel.cpp ├── appconfig.cpp ├── benchmarkmodel.h ├── mainwindow.h ├── benchmarkdelegate.cpp ├── chartviewwidget.cpp ├── measurement.cpp ├── jsonparser.cpp ├── csvparser.cpp ├── benchmarkview.cpp ├── mainwindow_presenter.cpp ├── benchmarkmodel.cpp └── mainwindow.cpp ├── screenshot.png ├── app_screenshot.gif ├── run.sh ├── .gitignore ├── example_files ├── creation.json ├── smart_ptr.json ├── op.json └── bool2str.json ├── gen.pl ├── LICENSE ├── README.md ├── BenchmarkViewer.pro ├── CMakeLists.txt ├── .travis.yml └── appveyor.yml /app/appconfig.ini: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asit-dhal/BenchmarkViewer/HEAD/screenshot.png -------------------------------------------------------------------------------- /app_screenshot.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asit-dhal/BenchmarkViewer/HEAD/app_screenshot.gif -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | root=${PWD} 2 | 3 | mkdir -p "${root}/static_analysis" 4 | ./how-to-use-pvs-studio-free -c 1 . 5 | pvs-studio-analyzer trace -o "${root}/static_analysis/strace_out" -- make 6 | pvs-studio-analyzer analyze -f "${root}/static_analysis/strace_out" -o "${root}/static_analysis/project.log" 7 | plog-converter -a GA:1,2 -t tasklist -o "${root}/static_analysis/project.tasks" "${root}/static_analysis/project.log" 8 | -------------------------------------------------------------------------------- /app/worker.cpp: -------------------------------------------------------------------------------- 1 | #include "worker.h" 2 | #include "globals.h" 3 | 4 | void Worker::parse(ParserType parserType, const QString &filename) 5 | { 6 | qCDebug(parser) << "Request Arrived to parse: " << filename 7 | << " type: " << parserType; 8 | auto parser = ParserFactory::getParser(parserType); 9 | parser->parse(filename); 10 | auto benchmark = parser->getBenchmark(); 11 | emit parsingFinished(filename, benchmark); 12 | } 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # C++ objects and libs 2 | *.slo 3 | *.lo 4 | *.o 5 | *.a 6 | *.la 7 | *.lai 8 | *.so 9 | *.dll 10 | *.dylib 11 | 12 | # Qt-es 13 | object_script.*.Release 14 | object_script.*.Debug 15 | *_plugin_import.cpp 16 | /.qmake.cache 17 | /.qmake.stash 18 | *.pro.user 19 | *.pro.user.* 20 | *.qbs.user 21 | *.qbs.user.* 22 | *.moc 23 | moc_*.cpp 24 | moc_*.h 25 | qrc_*.cpp 26 | ui_*.h 27 | *.qmlc 28 | *.jsc 29 | Makefile* 30 | *build-* 31 | 32 | # Qt unit tests 33 | target_wrapper.* 34 | 35 | # QtCreator 36 | *.autosave 37 | 38 | # QtCreator Qml 39 | *.qmlproject.user 40 | *.qmlproject.user.* 41 | 42 | # QtCreator CMake 43 | CMakeLists.txt.user* 44 | 45 | # Paths 46 | build/* 47 | -------------------------------------------------------------------------------- /example_files/creation.json: -------------------------------------------------------------------------------- 1 | { 2 | "context": { 3 | "date": "2018-05-06 07:41:19", 4 | "num_cpus": 2, 5 | "mhz_per_cpu": 2400, 6 | "cpu_scaling_enabled": true, 7 | "library_build_type": "debug" 8 | }, 9 | "benchmarks": [ 10 | { 11 | "name": "String_Creation", 12 | "iterations": 7220901, 13 | "real_time": 9.7116062663081891e+01, 14 | "cpu_time": 9.7101819565176143e+01, 15 | "time_unit": "ns" 16 | }, 17 | { 18 | "name": "StringStream_Creation", 19 | "iterations": 880831, 20 | "real_time": 7.9514907626999479e+02, 21 | "cpu_time": 7.9514210785042758e+02, 22 | "time_unit": "ns" 23 | }, 24 | { 25 | "name": "OstringStream_Creation", 26 | "iterations": 1186483, 27 | "real_time": 6.2545052057210785e+02, 28 | "cpu_time": 6.2545120494773221e+02, 29 | "time_unit": "ns" 30 | } 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /gen.pl: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use LWP::Simple; 4 | use Cwd qw(); 5 | use File::Basename; 6 | use FindBin qw($Bin); 7 | 8 | $ENV{"QT_MESSAGE_PATTERN"} = '%{time h:mm:ss.zzz}%{threadid}%{if-category} %{category}%{endif} %{type}%{if-debug} %{file}:%{line} %{function} %{endif} %{message}'; 9 | 10 | my $current_path = Cwd::cwd(); 11 | 12 | my $build_path = "$current_path/build"; 13 | mkdir($build_path, 0700) unless(-d $build_path ); 14 | chdir($build_path) or die "can't chdir $build_path\n"; 15 | 16 | my $qt_path = qq("c:/Qt/5.11.2/msvc2017_64"); 17 | my $build_type = "Debug"; 18 | my $vs_generator = qq("Visual Studio 15 2017 Win64"); 19 | my $devenv_path = qq("C:\\Program Files\ (x86)\\Microsoft Visual Studio\\2017\\Community\\Common7\\IDE\\devenv.exe"); 20 | my $vsproj_path = "$build_path/BenchmarkViewer.sln"; 21 | 22 | system("cmake -G $vs_generator -DCMAKE_PREFIX_PATH=$qt_path -DCMAKE_BUILD_TYPE=$build_type .."); 23 | exec("$devenv_path $vsproj_path") -------------------------------------------------------------------------------- /app/mainwindow_presenter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include "worker.h" 7 | #include 8 | #include "abstractparser.h" 9 | 10 | class MainWindow; 11 | 12 | class MainWindowPresenter: public QObject 13 | { 14 | Q_OBJECT 15 | public: 16 | MainWindowPresenter(MainWindow* mainWindow, QObject* parent); 17 | 18 | public slots: 19 | void onOpenFileTriggered(); 20 | void onCloseAllFilesTriggered(); 21 | void onExportChartTriggered(); 22 | void onExitTriggered(); 23 | void onAboutAppTriggered(); 24 | void onNewBenchmark(QString filename, Benchmark benchmark); 25 | void onRemoveBenchmark(QString filename); 26 | 27 | signals: 28 | void newFileSelected(ParserType, const QString &); 29 | void fileRemoved(QString); 30 | 31 | private: 32 | void connectSignalsToSlots(); 33 | void updateRecentFilesActions(); 34 | void updateCloseFileActions(); 35 | void openFile(QString filename); 36 | void closeFile(QString filename); 37 | 38 | Worker m_worker; 39 | QThread m_workerThread; 40 | MainWindow* m_view; 41 | QStringList m_openedFiles; 42 | }; 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Asit Kumar Dhal 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### BenchmarkViewer 2 | 3 | Qt application to view Google Microbenchmarking data https://github.com/google/benchmark. 4 | 5 | ### Build Status 6 | | Build | Status | 7 | |------- | -------- | 8 | | AppVeyor | [![Build status](https://ci.appveyor.com/api/projects/status/2ryk3cvxmygfp22g?svg=true)](https://ci.appveyor.com/api/projects/status/2ryk3cvxmygfp22g?svg=true) | 9 | | Travis | [![Build Status](https://travis-ci.org/asit-dhal/BenchmarkViewer.svg?branch=master)](https://travis-ci.org/asit-dhal/BenchmarkViewer.svg?branch=master) | 10 | 11 | 12 | ### Supported Platforms 13 | 14 | The standalone binary packages support the following platforms: 15 | 16 | * Windows 7 or later 17 | * (K)Ubuntu Linux 16.04 (64-bit) or later 18 | 19 | ### Usages 20 | * Generate json report from your benchmark 21 | ```bash 22 | ./benchmark_binary --benchmark_format=json > benchmark.json 23 | ``` 24 | * Open the json file in BenchmarkViewer. It will list all generated benchmarks. 25 | * Select on any benchmarks by clicking the checkbox. 26 | 27 | ### Sample Screenshot 28 | ![alt text](https://github.com/asit-dhal/BenchmarkViewer/raw/master/screenshot.png "Screenshot of chart view") 29 | ![alt text](https://github.com/asit-dhal/BenchmarkViewer/raw/master/app_screenshot.gif "Recording of BenchmarkViewer") -------------------------------------------------------------------------------- /app/globals.cpp: -------------------------------------------------------------------------------- 1 | /*========================================================================= 2 | 3 | Program: BenchmarkViewer 4 | 5 | Copyright (c) 2018 Asit Dhal 6 | All rights reserved. 7 | 8 | BenchmarkViewer is a free software; you can redistribute it and/or modify it. 9 | 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 12 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 13 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 14 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR 15 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 19 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | ========================================================================*/ 24 | 25 | #include "globals.h" 26 | 27 | Q_LOGGING_CATEGORY(gui, "gui") 28 | Q_LOGGING_CATEGORY(parser, "parser") 29 | -------------------------------------------------------------------------------- /app/globals.h: -------------------------------------------------------------------------------- 1 | /*========================================================================= 2 | 3 | Program: BenchmarkViewer 4 | 5 | Copyright (c) 2018 Asit Dhal 6 | All rights reserved. 7 | 8 | BenchmarkViewer is a free software; you can redistribute it and/or modify it. 9 | 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 12 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 13 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 14 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR 15 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 19 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | ========================================================================*/ 24 | 25 | #pragma once 26 | 27 | #include 28 | 29 | Q_DECLARE_LOGGING_CATEGORY(gui); 30 | Q_DECLARE_LOGGING_CATEGORY(parser); 31 | -------------------------------------------------------------------------------- /BenchmarkViewer.pro: -------------------------------------------------------------------------------- 1 | # ========================================================================= 2 | # 3 | # Program: BenchmarkViewer 4 | # 5 | # Copyright (c) 2018 Asit Dhal 6 | # All rights reserved. 7 | 8 | # BenchmarkViewer is a free software; you can redistribute it and/or modify it. 9 | 10 | 11 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 12 | # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 13 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 14 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR 15 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16 | # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 19 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | #========================================================================*/ 24 | 25 | TEMPLATE = subdirs 26 | 27 | CONFIG += c++14 28 | 29 | SUBDIRS = \ 30 | app 31 | 32 | 33 | DISTFILES += \ 34 | CMakeLists.txt 35 | 36 | OTHER_FILES += \ 37 | appveyor.yml \ 38 | .travis.yml 39 | -------------------------------------------------------------------------------- /app/helper.h: -------------------------------------------------------------------------------- 1 | /*========================================================================= 2 | 3 | Program: BenchmarkViewer 4 | 5 | Copyright (c) 2018 Asit Dhal 6 | All rights reserved. 7 | 8 | BenchmarkViewer is a free software; you can redistribute it and/or modify it. 9 | 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 12 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 13 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 14 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR 15 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 19 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | ========================================================================*/ 24 | 25 | #pragma once 26 | 27 | #include "abstractparser.h" 28 | #include 29 | 30 | class Helper { 31 | public: 32 | static int getUniqueMeasurementId(); 33 | static ParserType getParserTypeFromFilename(QString filename); 34 | 35 | private: 36 | static int m_measurementId; 37 | }; 38 | -------------------------------------------------------------------------------- /app/worker.h: -------------------------------------------------------------------------------- 1 | /*========================================================================= 2 | 3 | Program: BenchmarkViewer 4 | 5 | Copyright (c) 2018 Asit Dhal 6 | All rights reserved. 7 | 8 | QCommander is a free software; you can redistribute it and/or modify it. 9 | 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 12 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 13 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 14 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR 15 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 19 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | ========================================================================*/ 24 | 25 | #pragma once 26 | 27 | #include 28 | #include 29 | #include "abstractparser.h" 30 | 31 | class Worker: public QObject 32 | { 33 | Q_OBJECT 34 | 35 | public: 36 | 37 | public slots: 38 | void parse(ParserType parserType, const QString &filename); 39 | 40 | signals: 41 | void parsingFinished(QString filename, Benchmark bm); 42 | }; 43 | -------------------------------------------------------------------------------- /app/csvparser.h: -------------------------------------------------------------------------------- 1 | /*========================================================================= 2 | 3 | Program: QCommander 4 | 5 | Copyright (c) 2018 Asit Dhal 6 | All rights reserved. 7 | 8 | QCommander is a free software; you can redistribute it and/or modify it. 9 | 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 12 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 13 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 14 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR 15 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 19 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | ========================================================================*/ 24 | 25 | #pragma once 26 | 27 | #include "abstractparser.h" 28 | 29 | class CsvParser : public IAbstractParser { 30 | public: 31 | CsvParser() = default; 32 | void parse(QString filename) override; 33 | Benchmark getBenchmark() const override; 34 | 35 | private: 36 | QStringList parseHeaders(QString header); 37 | QList parseBenchmarks(QStringList& data, QStringList& header); 38 | Benchmark m_benchmark; 39 | }; 40 | -------------------------------------------------------------------------------- /app/jsonparser.h: -------------------------------------------------------------------------------- 1 | /*========================================================================= 2 | 3 | Program: BenchmarkViewer 4 | 5 | Copyright (c) 2018 Asit Dhal 6 | All rights reserved. 7 | 8 | BenchmarkViewer is a free software; you can redistribute it and/or modify it. 9 | 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 12 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 13 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 14 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR 15 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 19 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | ========================================================================*/ 24 | 25 | #pragma once 26 | 27 | #include 28 | #include "abstractparser.h" 29 | 30 | class JsonParser : public IAbstractParser 31 | { 32 | public: 33 | void parse(QString filename) override; 34 | Benchmark getBenchmark() const override; 35 | 36 | private: 37 | Context parseContext(const QJsonObject& json); 38 | QVector parseBenchmarks(const QJsonObject& json); 39 | Benchmark m_benchmark; 40 | }; 41 | -------------------------------------------------------------------------------- /app/appconfig.h: -------------------------------------------------------------------------------- 1 | /*========================================================================= 2 | 3 | Program: BenchmarkViewer 4 | 5 | Copyright (c) 2018 Asit Dhal 6 | All rights reserved. 7 | 8 | BenchmarkViewer is a free software; you can redistribute it and/or modify it. 9 | 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 12 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 13 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 14 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR 15 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 19 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | ========================================================================*/ 24 | 25 | #ifndef APPCONFIG_H 26 | #define APPCONFIG_H 27 | 28 | #include 29 | #include 30 | 31 | void loadAppSettings(); 32 | QStringList readRecentFiles(); 33 | void updateRecentFiles(QString fileName); 34 | 35 | QString readLastOpenedFilePath(); 36 | void updateLastOpenedFilePath(QString path); 37 | 38 | QString readLastExportedFilePath(); 39 | void updateLastExportedFilePath(const QString &path); 40 | 41 | #endif // APPCONFIG_H 42 | -------------------------------------------------------------------------------- /app/main.cpp: -------------------------------------------------------------------------------- 1 | /*========================================================================= 2 | 3 | Program: BenchmarkViewer 4 | 5 | Copyright (c) 2018 Asit Dhal 6 | All rights reserved. 7 | 8 | BenchmarkViewer is a free software; you can redistribute it and/or modify it. 9 | 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 12 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 13 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 14 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR 15 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 19 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | ========================================================================*/ 24 | 25 | #include 26 | #include 27 | #include "appconfig.h" 28 | #include "mainwindow.h" 29 | 30 | int main(int argc, char* argv[]) 31 | { 32 | QApplication a(argc, argv); 33 | a.setAttribute(Qt::AA_DontShowIconsInMenus); 34 | 35 | loadAppSettings(); 36 | 37 | MainWindow w; 38 | 39 | QLoggingCategory::setFilterRules( 40 | "*.debug=true\n" 41 | "qt.*.debug=false\n"); 42 | 43 | w.show(); 44 | 45 | return a.exec(); 46 | } 47 | -------------------------------------------------------------------------------- /app/benchmarkdelegate.h: -------------------------------------------------------------------------------- 1 | /*========================================================================= 2 | 3 | Program: BenchmarkViewer 4 | 5 | Copyright (c) 2018 Asit Dhal 6 | All rights reserved. 7 | 8 | BenchmarkViewer is a free software; you can redistribute it and/or modify it. 9 | 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 12 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 13 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 14 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR 15 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 19 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | ========================================================================*/ 24 | 25 | #pragma once 26 | 27 | #include 28 | 29 | class BenchmarkDelegate : public QStyledItemDelegate { 30 | Q_OBJECT 31 | 32 | public: 33 | BenchmarkDelegate(QObject* parent = nullptr); 34 | void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override; 35 | bool editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index) override; 36 | }; 37 | 38 | -------------------------------------------------------------------------------- /app/helper.cpp: -------------------------------------------------------------------------------- 1 | /*========================================================================= 2 | 3 | Program: BenchmarkViewer 4 | 5 | Copyright (c) 2018 Asit Dhal 6 | All rights reserved. 7 | 8 | BenchmarkViewer is a free software; you can redistribute it and/or modify it. 9 | 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 12 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 13 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 14 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR 15 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 19 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | ========================================================================*/ 24 | 25 | #include "helper.h" 26 | #include 27 | 28 | int Helper::m_measurementId = 0; 29 | int Helper::getUniqueMeasurementId() 30 | { 31 | m_measurementId++; 32 | return m_measurementId; 33 | } 34 | 35 | ParserType Helper::getParserTypeFromFilename(QString filename) 36 | { 37 | QFileInfo fi(filename); 38 | if (fi.suffix().compare("json", Qt::CaseInsensitive) == 0) 39 | { 40 | return ParserType::eGoogleBenchmarkJson; 41 | } 42 | else /*if (fi.suffix().compare("csv", Qt::CaseInsensitive) == 0)*/ 43 | { 44 | return ParserType::eGoogleBenchmarkCsv; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app/benchmarkproxymodel.h: -------------------------------------------------------------------------------- 1 | /*========================================================================= 2 | 3 | Program: BenchmarkViewer 4 | 5 | Copyright (c) 2018 Asit Dhal 6 | All rights reserved. 7 | 8 | BenchmarkViewer is a free software; you can redistribute it and/or modify it. 9 | 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 12 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 13 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 14 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR 15 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 19 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | ========================================================================*/ 24 | 25 | #pragma once 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | Q_DECLARE_LOGGING_CATEGORY(proxyModel); 32 | 33 | class BenchmarkProxyModel : public QSortFilterProxyModel 34 | { 35 | public: 36 | BenchmarkProxyModel(QObject* parent = nullptr); 37 | static BenchmarkProxyModel *getInstance(); 38 | 39 | protected: 40 | bool lessThan(const QModelIndex& left, const QModelIndex& right) const override; 41 | bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override; 42 | 43 | private: 44 | static BenchmarkProxyModel *m_pInstance; 45 | }; 46 | -------------------------------------------------------------------------------- /app/benchmark.h: -------------------------------------------------------------------------------- 1 | /*========================================================================= 2 | 3 | Program: BenchmarkViewer 4 | 5 | Copyright (c) 2018 Asit Dhal 6 | All rights reserved. 7 | 8 | BenchmarkViewer is a free software; you can redistribute it and/or modify it. 9 | 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 12 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 13 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 14 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR 15 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 19 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | ========================================================================*/ 24 | 25 | #ifndef BENCHMARKS_H 26 | #define BENCHMARKS_H 27 | 28 | #include 29 | #include "context.h" 30 | #include "measurement.h" 31 | 32 | class Benchmark 33 | { 34 | public: 35 | Benchmark(); 36 | 37 | Context getContext() const; 38 | void setContext(const Context& value); 39 | 40 | QVector getMeasurements() const; 41 | void addMeasurement(const Measurement& _mmt); 42 | void setMeasurements(const QVector& value); 43 | 44 | private: 45 | Context m_context; 46 | QVector m_measurements; 47 | }; 48 | 49 | Q_DECLARE_METATYPE(Benchmark); 50 | 51 | QDebug operator<<(QDebug d, const Benchmark& bmk); 52 | 53 | #endif // BENCHMARKS_H 54 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # ========================================================================= 2 | # 3 | # Program: BenchmarkViewer 4 | # 5 | # Copyright (c) 2018 Asit Dhal 6 | # All rights reserved. 7 | 8 | # BenchmarkViewer is a free software; you can redistribute it and/or modify it. 9 | 10 | 11 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 12 | # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 13 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 14 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR 15 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16 | # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 19 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | #========================================================================*/ 24 | 25 | project(BenchmarkViewer) 26 | 27 | cmake_minimum_required(VERSION 3.2.2) 28 | 29 | set(PROJECT_NAME "BenchmarkViewer") 30 | 31 | if (NOT CMAKE_BUILD_TYPE) 32 | set(CMAKE_BUILD_TYPE "Release") 33 | endif() 34 | 35 | set(CMAKE_CXX_STANDARD 14) 36 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 37 | 38 | if (MSVC) 39 | if(CMAKE_BUILD_TYPE STREQUAL "Release") 40 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup") 41 | set(GUI_TYPE WIN32) 42 | endif() 43 | else() 44 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") 45 | endif() 46 | 47 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) 48 | 49 | add_subdirectory(app) 50 | -------------------------------------------------------------------------------- /app/abstractparser.cpp: -------------------------------------------------------------------------------- 1 | /*========================================================================= 2 | 3 | Program: QCommander 4 | 5 | Copyright (c) 2018 Asit Dhal 6 | All rights reserved. 7 | 8 | QCommander is a free software; you can redistribute it and/or modify it. 9 | 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 12 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 13 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 14 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR 15 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 19 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | ========================================================================*/ 24 | #include "abstractparser.h" 25 | 26 | #include "csvparser.h" 27 | #include "jsonparser.h" 28 | 29 | std::unique_ptr ParserFactory::getParser(ParserType parserType) 30 | { 31 | switch (parserType) 32 | { 33 | case ParserType::eGoogleBenchmarkCsv: 34 | return std::make_unique(); 35 | case ParserType::eGoogleBenchmarkJson: 36 | return std::make_unique(); 37 | } 38 | } 39 | 40 | QDebug operator<<(QDebug d, const ParserType& type) 41 | { 42 | switch (type) 43 | { 44 | case ParserType::eGoogleBenchmarkCsv: 45 | d << "GoogleBenchmarkCsv"; 46 | break; 47 | case ParserType::eGoogleBenchmarkJson: 48 | d << "GoogleBenchmarkJson"; 49 | break; 50 | } 51 | return d; 52 | } 53 | -------------------------------------------------------------------------------- /app/abstractparser.h: -------------------------------------------------------------------------------- 1 | /*========================================================================= 2 | 3 | Program: BenchmarkViewer 4 | 5 | Copyright (c) 2018 Asit Dhal 6 | All rights reserved. 7 | 8 | QCommander is a free software; you can redistribute it and/or modify it. 9 | 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 12 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 13 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 14 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR 15 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 19 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | ========================================================================*/ 24 | 25 | #ifndef ABSTRACTPARSER_H 26 | #define ABSTRACTPARSER_H 27 | 28 | #include 29 | #include 30 | #include 31 | #include "benchmark.h" 32 | 33 | class IAbstractParser 34 | { 35 | public: 36 | virtual ~IAbstractParser() = default; 37 | virtual void parse(QString filename) = 0; 38 | virtual Benchmark getBenchmark() const = 0; 39 | }; 40 | 41 | 42 | enum class ParserType 43 | { 44 | eGoogleBenchmarkCsv, 45 | eGoogleBenchmarkJson 46 | }; 47 | 48 | class ParserFactory 49 | { 50 | public: 51 | static std::unique_ptr getParser(ParserType parserType); 52 | }; 53 | 54 | Q_DECLARE_METATYPE(ParserType); 55 | 56 | QDebug operator<<(QDebug d, const ParserType& type); 57 | 58 | 59 | 60 | #endif // ABSTRACTPARSER_H 61 | -------------------------------------------------------------------------------- /app/benchmark.cpp: -------------------------------------------------------------------------------- 1 | /*========================================================================= 2 | 3 | Program: BenchmarkViewer 4 | 5 | Copyright (c) 2018 Asit Dhal 6 | All rights reserved. 7 | 8 | BenchmarkViewer is a free software; you can redistribute it and/or modify it. 9 | 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 12 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 13 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 14 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR 15 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 19 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | ========================================================================*/ 24 | 25 | #include "benchmark.h" 26 | 27 | Benchmark::Benchmark() {} 28 | 29 | Context Benchmark::getContext() const 30 | { 31 | return m_context; 32 | } 33 | 34 | void Benchmark::setContext(const Context& value) 35 | { 36 | m_context = value; 37 | } 38 | 39 | QVector Benchmark::getMeasurements() const 40 | { 41 | return m_measurements; 42 | } 43 | 44 | void Benchmark::addMeasurement(const Measurement& _mmt) 45 | { 46 | m_measurements.append(_mmt); 47 | } 48 | 49 | void Benchmark::setMeasurements(const QVector& value) 50 | { 51 | m_measurements = value; 52 | } 53 | 54 | QDebug operator<<(QDebug d, const Benchmark& bmk) 55 | { 56 | d << "context: {" << bmk.getContext() << "}" 57 | << " benchmarks: [" << bmk.getMeasurements() << "]"; 58 | return d; 59 | } 60 | -------------------------------------------------------------------------------- /app/context.h: -------------------------------------------------------------------------------- 1 | /*========================================================================= 2 | 3 | Program: BenchmarkViewer 4 | 5 | Copyright (c) 2018 Asit Dhal 6 | All rights reserved. 7 | 8 | BenchmarkViewer is a free software; you can redistribute it and/or modify it. 9 | 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 12 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 13 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 14 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR 15 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 19 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | ========================================================================*/ 24 | 25 | #ifndef CONTEXT_H 26 | #define CONTEXT_H 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | class Context 33 | { 34 | public: 35 | Context() = default; 36 | QDateTime getTimestamp() const; 37 | void setTimestamp(const QDateTime& value); 38 | int getCpuFrequency() const; 39 | void setCpuFrequency(int value); 40 | bool getCpuScalingEnabled() const; 41 | void setCpuScalingEnabled(bool value); 42 | QString getLibraryBuildType() const; 43 | void setLibraryBuildType(QString value); 44 | int getCpuCount() const; 45 | void setCpuCount(int value); 46 | 47 | private: 48 | QDateTime timestamp; 49 | int cpuCount; 50 | int cpuFrequency; 51 | bool cpuScalingEnabled; 52 | QString libraryBuildType; 53 | }; 54 | 55 | QDebug operator<<(QDebug d, const Context& ctx); 56 | 57 | #endif // CONTEXT_H 58 | -------------------------------------------------------------------------------- /example_files/smart_ptr.json: -------------------------------------------------------------------------------- 1 | { 2 | "context": { 3 | "date": "2018-05-06 07:41:55", 4 | "num_cpus": 2, 5 | "mhz_per_cpu": 2400, 6 | "cpu_scaling_enabled": true, 7 | "library_build_type": "debug" 8 | }, 9 | "benchmarks": [ 10 | { 11 | "name": "RawPointer_Creation", 12 | "iterations": 17818200, 13 | "real_time": 3.9362968425543208e+01, 14 | "cpu_time": 3.9352987843889949e+01, 15 | "time_unit": "ns" 16 | }, 17 | { 18 | "name": "UniquePtr_Creation", 19 | "iterations": 18206519, 20 | "real_time": 3.8532861828232946e+01, 21 | "cpu_time": 3.8510875033277912e+01, 22 | "time_unit": "ns" 23 | }, 24 | { 25 | "name": "SharedPtr_Creation", 26 | "iterations": 7664960, 27 | "real_time": 9.1243453977576664e+01, 28 | "cpu_time": 9.1243030883396671e+01, 29 | "time_unit": "ns" 30 | }, 31 | { 32 | "name": "RawPointer_Access", 33 | "iterations": 643908, 34 | "real_time": 1.0871965330167179e+03, 35 | "cpu_time": 1.0879234673271478e+03, 36 | "time_unit": "ns" 37 | }, 38 | { 39 | "name": "UniquePtr_Access", 40 | "iterations": 652992, 41 | "real_time": 1.0660579177232553e+03, 42 | "cpu_time": 1.0734384418193874e+03, 43 | "time_unit": "ns" 44 | }, 45 | { 46 | "name": "SharedPtr_Access", 47 | "iterations": 644068, 48 | "real_time": 1.0732783199931487e+03, 49 | "cpu_time": 1.0840270080178309e+03, 50 | "time_unit": "ns" 51 | }, 52 | { 53 | "name": "RawPointer_Param", 54 | "iterations": 650094, 55 | "real_time": 1.0648214736604009e+03, 56 | "cpu_time": 1.0669418222592938e+03, 57 | "time_unit": "ns" 58 | }, 59 | { 60 | "name": "UniquePtr_Param", 61 | "iterations": 659623, 62 | "real_time": 1.0541111830755553e+03, 63 | "cpu_time": 1.0621727941555259e+03, 64 | "time_unit": "ns" 65 | }, 66 | { 67 | "name": "SharedPtr_Param", 68 | "iterations": 626394, 69 | "real_time": 1.1086830334037613e+03, 70 | "cpu_time": 1.1135660399040746e+03, 71 | "time_unit": "ns" 72 | } 73 | ] 74 | } 75 | -------------------------------------------------------------------------------- /app/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # ========================================================================= 2 | # 3 | # Program: BenchmarkViewer 4 | # 5 | # Copyright (c) 2018 Asit Dhal 6 | # All rights reserved. 7 | 8 | # BenchmarkViewer is a free software; you can redistribute it and/or modify it. 9 | 10 | 11 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 12 | # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 13 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 14 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR 15 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16 | # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 19 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | #========================================================================*/ 24 | 25 | set(CMAKE_AUTOMOC ON) 26 | 27 | find_package(Qt5Widgets 5.10 REQUIRED) 28 | find_package(Qt5Charts 5.10 REQUIRED) 29 | find_package(Qt5Core 5.10 REQUIRED) 30 | find_package(Qt5Gui 5.10 REQUIRED) 31 | 32 | set(SRCS 33 | appconfig.cpp 34 | benchmark.cpp 35 | benchmarkdelegate.cpp 36 | benchmarkmodel.cpp 37 | benchmarkproxymodel.cpp 38 | benchmarkview.cpp 39 | chartviewwidget.cpp 40 | context.cpp 41 | helper.cpp 42 | main.cpp 43 | mainwindow.cpp 44 | mainwindow_presenter.cpp 45 | measurement.cpp 46 | abstractparser.cpp 47 | jsonparser.cpp 48 | csvparser.cpp 49 | globals.cpp 50 | worker.cpp 51 | ) 52 | 53 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 54 | 55 | add_executable(${PROJECT_NAME} ${SRCS}) 56 | 57 | target_link_libraries(${PROJECT_NAME} 58 | Qt5::Widgets 59 | Qt5::Core 60 | Qt5::Gui 61 | Qt5::Charts 62 | ) 63 | 64 | -------------------------------------------------------------------------------- /app/benchmarkview.h: -------------------------------------------------------------------------------- 1 | /*========================================================================= 2 | 3 | Program: BenchmarkViewer 4 | 5 | Copyright (c) 2018 Asit Dhal 6 | All rights reserved. 7 | 8 | BenchmarkViewer is a free software; you can redistribute it and/or modify it. 9 | 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 12 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 13 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 14 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR 15 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 19 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | ========================================================================*/ 24 | 25 | #pragma once 26 | 27 | #include 28 | #include "benchmarkmodel.h" 29 | 30 | class QHeaderView; 31 | 32 | class BenchmarkView : public QTableView 33 | { 34 | Q_OBJECT 35 | 36 | public: 37 | BenchmarkView(QWidget* parent = 0); 38 | ~BenchmarkView() = default; 39 | void seBenchmarkColumnAttributes(BenchmarkModel *bmModel); 40 | 41 | signals: 42 | void select(); 43 | void selectAllRows(); 44 | void clearSelection(); 45 | void clearAllRows(); 46 | 47 | public slots: 48 | void onShowColumn(BenchmarkModel::Columns col); 49 | void onHideColumn(BenchmarkModel::Columns col); 50 | 51 | private slots: 52 | void onContextMenuOnHeader(QPoint p); 53 | void onContextMenuOnBody(QPoint p); 54 | void onSlotMoveLast(); 55 | void onSlotMoveFirst(); 56 | 57 | private: 58 | QHeaderView* m_header; 59 | QList m_columnShowHideActions; 60 | QAction* m_moveLastAction; 61 | QAction* m_moveFirstAction; 62 | 63 | QAction* m_select; 64 | QAction* m_selectAll; 65 | QAction* m_clearSelection; 66 | QAction* m_clearAllRows; 67 | QList m_currentHiddenColumns; 68 | }; 69 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # Copyright(c) 2018 Asit Dhal. 2 | # Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | language: cpp 5 | sudo: required 6 | dist: trusty 7 | 8 | #compiler: 9 | # - gcc 10 | # - clang 11 | 12 | configuration: 13 | - Release 14 | - Debug 15 | 16 | environment: 17 | matrix: 18 | - CMAKE_BUILD_SYS: true 19 | - QMAKE_BUILD_SYS: true 20 | 21 | 22 | matrix: 23 | include: 24 | - os: osx 25 | osx_image: xcode9 26 | compiler: clang 27 | - os: linux 28 | compiler: gcc 29 | env: 30 | - CXX_COMPILER=g++-7 31 | - C_COMPILER=gcc-7 32 | addons: 33 | apt: 34 | sources: ["ubuntu-toolchain-r-test"] 35 | packages: ["g++-7", "ninja-build"] 36 | - os: linux 37 | compiler: clang 38 | env: 39 | - CXX_COMPILER=clang++-5.0 40 | - C_COMPILER=clang-5.0 41 | addons: 42 | apt: 43 | sources: ["ubuntu-toolchain-r-test", "llvm-toolchain-trusty-5.0"] 44 | packages: ["clang-5.0", "g++-7", "ninja-build"] 45 | 46 | before_install: 47 | - export CXX=${CXX_COMPILER} 48 | - export CC=${C_COMPILER} 49 | 50 | before_install: 51 | - if [[ "$TRAVIS_OS_NAME" = "linux" ]]; then 52 | sudo add-apt-repository ppa:beineri/opt-qt-5.10.1-trusty -y; 53 | fi 54 | - if [ "$TRAVIS_OS_NAME" = "linux" ]; then 55 | sudo apt-get update -qq; 56 | else 57 | brew update; 58 | brew cleanup; 59 | fi 60 | 61 | install: 62 | - if [ "$TRAVIS_OS_NAME" = "linux" ]; then 63 | sudo apt-get install -qq qt510base qt510charts-no-lgpl; source /opt/qt510/bin/qt510-env.sh; 64 | else 65 | brew install qt5; 66 | brew link --force qt5; 67 | export HOMEBREW_QT5_VERSION=$(brew list --versions qt5 | rev | cut -d' ' -f1 | rev); 68 | sudo ln -s /usr/local/Cellar/qt5/$HOMEBREW_QT5_VERSION/mkspecs /usr/local/mkspecs; 69 | echo 'export PATH="/usr/local/opt/qt/bin:$PATH"' >> ~/.bash_profile; 70 | fi 71 | 72 | script: 73 | - mkdir ./build && cd ./build 74 | - if [ "$CMAKE_BUILD_SYS" = "true" ]; then 75 | cmake --version; 76 | cmake -DCMAKE_BUILD_TYPE=$configuration ..; 77 | make -j2; 78 | else 79 | qmake -v; 80 | qmake ../BenchmarkViewer.pro CONFIG+=$configuration; 81 | make -j2 ; 82 | fi 83 | 84 | notifications: 85 | email: false 86 | -------------------------------------------------------------------------------- /app/chartviewwidget.h: -------------------------------------------------------------------------------- 1 | /*========================================================================= 2 | 3 | Program: BenchmarkViewer 4 | 5 | Copyright (c) 2018 Asit Dhal 6 | All rights reserved. 7 | 8 | BenchmarkViewer is a free software; you can redistribute it and/or modify it. 9 | 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 12 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 13 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 14 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR 15 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 19 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | ========================================================================*/ 24 | 25 | #pragma once 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include "measurement.h" 37 | 38 | Q_DECLARE_LOGGING_CATEGORY(chartView); 39 | 40 | QT_CHARTS_USE_NAMESPACE 41 | 42 | class ChartViewWidget : public QWidget { 43 | Q_OBJECT 44 | public: 45 | static ChartViewWidget* getInstance(); 46 | ChartViewWidget(QWidget* parent = nullptr); 47 | bool exportChart(QString filename); 48 | 49 | signals: 50 | void measurementColorChanged(int, QString); 51 | 52 | public slots: 53 | void onAddMeasurement(const Measurement &mmt); 54 | void onRemoveMeasurement(const Measurement &mmt); 55 | 56 | 57 | private: 58 | void init(); 59 | double calculateMaxY(); 60 | 61 | double m_maxY = 0; 62 | QBarCategoryAxis* m_axis; 63 | QChart* m_chart; 64 | QChartView* m_chartView; 65 | QBarSeries* m_series; 66 | QMap m_barSet; 67 | 68 | static ChartViewWidget *m_pInstance; 69 | }; 70 | -------------------------------------------------------------------------------- /app/app.pro: -------------------------------------------------------------------------------- 1 | # ========================================================================= 2 | # 3 | # Program: BenchmarkViewer 4 | # 5 | # Copyright (c) 2018 Asit Dhal 6 | # All rights reserved. 7 | 8 | # BenchmarkViewer is a free software; you can redistribute it and/or modify it. 9 | 10 | 11 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 12 | # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 13 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 14 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR 15 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16 | # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 19 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | #========================================================================*/ 24 | 25 | QT += core gui charts 26 | 27 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 28 | 29 | TARGET = BenchmarkViewer 30 | TEMPLATE = app 31 | 32 | DEFINES += QT_DEPRECATED_WARNINGS 33 | 34 | SOURCES += \ 35 | main.cpp \ 36 | mainwindow.cpp \ 37 | context.cpp \ 38 | benchmarkmodel.cpp \ 39 | measurement.cpp \ 40 | helper.cpp \ 41 | benchmark.cpp \ 42 | benchmarkview.cpp \ 43 | benchmarkdelegate.cpp \ 44 | chartviewwidget.cpp \ 45 | benchmarkproxymodel.cpp \ 46 | appconfig.cpp \ 47 | globals.cpp \ 48 | jsonparser.cpp \ 49 | csvparser.cpp \ 50 | abstractparser.cpp \ 51 | worker.cpp \ 52 | mainwindow_presenter.cpp 53 | 54 | HEADERS += \ 55 | mainwindow.h \ 56 | context.h \ 57 | benchmarkmodel.h \ 58 | measurement.h \ 59 | helper.h \ 60 | benchmark.h \ 61 | benchmarkview.h \ 62 | benchmarkdelegate.h \ 63 | chartviewwidget.h \ 64 | benchmarkproxymodel.h \ 65 | appconfig.h \ 66 | globals.h \ 67 | abstractparser.h \ 68 | jsonparser.h \ 69 | csvparser.h \ 70 | worker.h \ 71 | mainwindow_presenter.h 72 | 73 | DISTFILES += \ 74 | appconfig.ini \ 75 | CMakeLists.txt 76 | -------------------------------------------------------------------------------- /app/context.cpp: -------------------------------------------------------------------------------- 1 | /*========================================================================= 2 | 3 | Program: BenchmarkViewer 4 | 5 | Copyright (c) 2018 Asit Dhal 6 | All rights reserved. 7 | 8 | BenchmarkViewer is a free software; you can redistribute it and/or modify it. 9 | 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 12 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 13 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 14 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR 15 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 19 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | ========================================================================*/ 24 | 25 | #include "context.h" 26 | 27 | QDateTime Context::getTimestamp() const 28 | { 29 | return timestamp; 30 | } 31 | 32 | void Context::setTimestamp(const QDateTime& value) 33 | { 34 | timestamp = value; 35 | } 36 | 37 | int Context::getCpuFrequency() const 38 | { 39 | return cpuFrequency; 40 | } 41 | 42 | void Context::setCpuFrequency(int value) 43 | { 44 | cpuFrequency = value; 45 | } 46 | 47 | bool Context::getCpuScalingEnabled() const 48 | { 49 | return cpuScalingEnabled; 50 | } 51 | 52 | void Context::setCpuScalingEnabled(bool value) 53 | { 54 | cpuScalingEnabled = value; 55 | } 56 | 57 | QString Context::getLibraryBuildType() const 58 | { 59 | return libraryBuildType; 60 | } 61 | 62 | void Context::setLibraryBuildType(QString value) 63 | { 64 | libraryBuildType = value; 65 | } 66 | 67 | int Context::getCpuCount() const 68 | { 69 | return cpuCount; 70 | } 71 | 72 | void Context::setCpuCount(int value) 73 | { 74 | cpuCount = value; 75 | } 76 | 77 | QDebug operator<<(QDebug d, const Context& ctx) 78 | { 79 | d << "timestamp: " << ctx.getTimestamp() 80 | << " cpu_count: " << ctx.getCpuCount() 81 | << " cpu_frequency: " << ctx.getCpuFrequency() 82 | << " cpu_scaling_enabled: " << ctx.getCpuScalingEnabled() 83 | << " library_build_type: " << ctx.getLibraryBuildType(); 84 | return d; 85 | } 86 | -------------------------------------------------------------------------------- /app/measurement.h: -------------------------------------------------------------------------------- 1 | /*========================================================================= 2 | 3 | Program: BenchmarkViewer 4 | 5 | Copyright (c) 2018 Asit Dhal 6 | All rights reserved. 7 | 8 | BenchmarkViewer is a free software; you can redistribute it and/or modify it. 9 | 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 12 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 13 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 14 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR 15 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 19 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | ========================================================================*/ 24 | #pragma once 25 | 26 | #include 27 | #include 28 | 29 | class Measurement { 30 | public: 31 | Measurement() noexcept; 32 | QString getName() const; 33 | void setName(const QString& value); 34 | 35 | quint64 getIterations() const; 36 | void setIterations(quint64 value); 37 | 38 | quint64 getRealTime() const; 39 | void setRealTime(quint64 value); 40 | 41 | quint64 getCpuTime() const; 42 | void setCpuTime(quint64 value); 43 | 44 | QString getTimeUnit() const; 45 | void setTimeUnit(const QString& value); 46 | 47 | int getId() const; 48 | 49 | quint64 getBytesPerSecond() const; 50 | void setBytesPerSecond(const quint64& bytesPerSecond); 51 | 52 | quint64 getItemsPerSecond() const; 53 | void setItemsPerSecond(const quint64& itemsPerSecond); 54 | 55 | QString getLabel() const; 56 | void setLabel(const QString& label); 57 | 58 | bool getErrorOccured() const; 59 | void setErrorOccured(bool errorOccured); 60 | 61 | QString getErrorMessage() const; 62 | void setErrorMessage(const QString& errorMessage); 63 | 64 | private: 65 | QString m_name; 66 | quint64 m_iterations; 67 | quint64 m_realTime; 68 | quint64 m_cpuTime; 69 | QString m_timeUnit; 70 | quint64 m_bytesPerSecond; 71 | quint64 m_itemsPerSecond; 72 | QString m_label; 73 | bool m_errorOccured; 74 | QString m_errorMessage; 75 | int m_id; 76 | }; 77 | 78 | Q_DECLARE_METATYPE(Measurement); 79 | 80 | QDebug operator<<(QDebug d, const Measurement& mmt); 81 | -------------------------------------------------------------------------------- /app/benchmarkproxymodel.cpp: -------------------------------------------------------------------------------- 1 | /*========================================================================= 2 | 3 | Program: BenchmarkViewer 4 | 5 | Copyright (c) 2018 Asit Dhal 6 | All rights reserved. 7 | 8 | BenchmarkViewer is a free software; you can redistribute it and/or modify it. 9 | 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 12 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 13 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 14 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR 15 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 19 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | ========================================================================*/ 24 | 25 | #include "benchmarkproxymodel.h" 26 | #include "benchmarkmodel.h" 27 | 28 | Q_LOGGING_CATEGORY(proxyModel, "proxyModel") 29 | 30 | BenchmarkProxyModel *BenchmarkProxyModel::m_pInstance = nullptr; 31 | 32 | BenchmarkProxyModel *BenchmarkProxyModel::getInstance() 33 | { 34 | return m_pInstance; 35 | } 36 | 37 | BenchmarkProxyModel::BenchmarkProxyModel(QObject* parent) 38 | : QSortFilterProxyModel(parent) 39 | { 40 | m_pInstance = this; 41 | } 42 | 43 | bool BenchmarkProxyModel::lessThan(const QModelIndex& left, const QModelIndex& right) const 44 | { 45 | QVariant leftData = sourceModel()->data(left); 46 | QVariant rightData = sourceModel()->data(right); 47 | 48 | using Columns = BenchmarkModel::Columns; 49 | switch (static_cast(left.column())) { 50 | case Columns::eStatus: 51 | return leftData.toBool(); 52 | case Columns::eIterations: 53 | case Columns::eRealTime: 54 | case Columns::eCpuTime: 55 | return leftData.toDouble() < rightData.toDouble(); 56 | case Columns::eName: 57 | case Columns::eFilename: 58 | default: 59 | return QString::localeAwareCompare(leftData.toString(), rightData.toString()) < 0; 60 | } 61 | } 62 | 63 | bool BenchmarkProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const 64 | { 65 | QModelIndex nameIndex = sourceModel()->index(sourceRow, 66 | static_cast(BenchmarkModel::Columns::eName), sourceParent); 67 | 68 | if (sourceModel()->data(nameIndex).toString().toLower().trimmed() 69 | .contains(filterRegExp())) { 70 | return true; 71 | } else { 72 | return false; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /app/appconfig.cpp: -------------------------------------------------------------------------------- 1 | /*========================================================================= 2 | 3 | Program: BenchmarkViewer 4 | 5 | Copyright (c) 2018 Asit Dhal 6 | All rights reserved. 7 | 8 | BenchmarkViewer is a free software; you can redistribute it and/or modify it. 9 | 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 12 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 13 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 14 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR 15 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 19 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | ========================================================================*/ 24 | 25 | #include "appconfig.h" 26 | 27 | void loadAppSettings() 28 | { 29 | QSettings::setDefaultFormat(QSettings::IniFormat); 30 | } 31 | 32 | QStringList readRecentFiles() 33 | { 34 | QSettings appSettings; 35 | appSettings.beginGroup("recent-files"); 36 | QString temp = appSettings.value("files").toString(); 37 | QStringList recentFiles; 38 | recentFiles << temp.split(" "); 39 | appSettings.endGroup(); 40 | return recentFiles; 41 | } 42 | 43 | void updateRecentFiles(QString fileName) 44 | { 45 | QSettings appSettings; 46 | appSettings.beginGroup("recent-files"); 47 | QString temp = appSettings.value("files").toString(); 48 | QStringList recentFiles; 49 | recentFiles << temp.split(" "); 50 | if (recentFiles.contains(fileName)) 51 | { 52 | recentFiles.removeOne(fileName); 53 | } 54 | recentFiles.push_front(fileName); 55 | if (recentFiles.size() > 5) 56 | recentFiles.pop_back(); 57 | appSettings.setValue("files", recentFiles.join(" ")); 58 | appSettings.endGroup(); 59 | } 60 | 61 | QString readLastOpenedFilePath() 62 | { 63 | QSettings appSettings; 64 | appSettings.beginGroup("last-opened-file-path"); 65 | QString temp = appSettings.value("path").toString(); 66 | appSettings.endGroup(); 67 | return temp.trimmed(); 68 | } 69 | 70 | void updateLastOpenedFilePath(QString path) 71 | { 72 | QSettings appSettings; 73 | appSettings.beginGroup("last-opened-file-path"); 74 | appSettings.setValue("path", path); 75 | appSettings.endGroup(); 76 | } 77 | 78 | QString readLastExportedFilePath() 79 | { 80 | QSettings appSettings; 81 | appSettings.beginGroup("last-exported-file-path"); 82 | QString temp = appSettings.value("path").toString(); 83 | appSettings.endGroup(); 84 | return temp.trimmed(); 85 | } 86 | void updateLastExportedFilePath(const QString &path) 87 | { 88 | QSettings appSettings; 89 | appSettings.beginGroup("last-exported-file-path"); 90 | appSettings.setValue("path", path); 91 | appSettings.endGroup(); 92 | } 93 | -------------------------------------------------------------------------------- /app/benchmarkmodel.h: -------------------------------------------------------------------------------- 1 | /*========================================================================= 2 | 3 | Program: BenchmarkViewer 4 | 5 | Copyright (c) 2018 Asit Dhal 6 | All rights reserved. 7 | 8 | BenchmarkViewer is a free software; you can redistribute it and/or modify it. 9 | 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 12 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 13 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 14 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR 15 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 19 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | ========================================================================*/ 24 | #pragma once 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include "benchmark.h" 31 | #include "measurement.h" 32 | 33 | Q_DECLARE_LOGGING_CATEGORY(benchmarkModel); 34 | 35 | struct BenchmarkViewUnit 36 | { 37 | Measurement measurement; 38 | QString filename; 39 | QString hexColor{ "#000000" }; 40 | bool isSelected{false}; 41 | }; 42 | 43 | class BenchmarkModel : public QAbstractTableModel 44 | { 45 | Q_OBJECT 46 | public: 47 | 48 | static BenchmarkModel* getInstance(); 49 | enum class Columns : int 50 | { 51 | eInvalid = 100, 52 | eStatus = 0, 53 | eName, 54 | eIterations, 55 | eRealTime, 56 | eCpuTime, 57 | eTimeUnit, 58 | eFilename 59 | }; 60 | 61 | static const int COLUMN_COUNT; 62 | 63 | explicit BenchmarkModel(QObject* parent = nullptr); 64 | void addBenchmark(QString filename, Benchmark benchmarks); 65 | void removeBenchmark(QString filename); 66 | void setMeasurementColor(int id, QString color); 67 | QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; 68 | 69 | int rowCount(const QModelIndex& parent = QModelIndex()) const override; 70 | int columnCount(const QModelIndex& parent = QModelIndex()) const override; 71 | 72 | QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; 73 | Qt::ItemFlags flags(const QModelIndex& index) const override; 74 | bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override; 75 | bool getColumnVisibility(Columns col); 76 | void setColumnVisibility(Columns col, bool visibility); 77 | 78 | signals: 79 | void measurementActive(Measurement); 80 | void measurementInactive(Measurement); 81 | void columnVisibilityChanged(Columns, bool); 82 | 83 | private: 84 | void initializeMetaData(); 85 | QList m_benchmarks; 86 | QMap m_columnsVisibility; 87 | 88 | static BenchmarkModel *m_pInstance; 89 | }; 90 | 91 | QString toString(BenchmarkModel::Columns col); 92 | -------------------------------------------------------------------------------- /app/mainwindow.h: -------------------------------------------------------------------------------- 1 | /*========================================================================= 2 | 3 | Program: BenchmarkViewer 4 | 5 | Copyright (c) 2018 Asit Dhal 6 | All rights reserved. 7 | 8 | BenchmarkViewer is a free software; you can redistribute it and/or modify it. 9 | 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 12 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 13 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 14 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR 15 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 19 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | ========================================================================*/ 24 | 25 | #pragma once 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include "benchmark.h" 38 | #include "worker.h" 39 | #include "mainwindow_presenter.h" 40 | 41 | QT_CHARTS_USE_NAMESPACE 42 | 43 | class QMenu; 44 | class QAction; 45 | class QListWidget; 46 | class BenchmarkModel; 47 | class QTableView; 48 | class BenchmarkView; 49 | class QLineEdit; 50 | class QPushButton; 51 | class BenchmarkDelegate; 52 | class BenchmarkProxyModel; 53 | class QItemSelectionModel; 54 | class QItemSelection; 55 | 56 | class MainWindow : public QMainWindow { 57 | Q_OBJECT 58 | 59 | public: 60 | MainWindow(QWidget* parent = 0); 61 | ~MainWindow(); 62 | void setRecentFileActions(QList recentFileActions); 63 | void setCloseFileActions(QList closeFileActions); 64 | void setViewColumnActions(QList viewColumnActions); 65 | 66 | signals: 67 | void newFileSelected(ParserType, QString); 68 | void selectedFileDeleted(QString); 69 | 70 | private: 71 | void createActions(); 72 | void createMenus(); 73 | void createWidgets(); 74 | void connectSignalsToSlots(); 75 | void init(); 76 | 77 | private slots: 78 | void onBenchmarkFilter(QString filter); 79 | void onSelectionChanged(const QItemSelection& selected, 80 | const QItemSelection& deselected); 81 | void onPlotSelection(); 82 | void onPlotAllRows(); 83 | void onClearSelection(); 84 | void onClearAllRows(); 85 | 86 | public: 87 | QAction* getOpenFileAction(); 88 | QAction* getCloseAllFilesAction(); 89 | QAction* getExportChartAction(); 90 | QAction* getExitAction(); 91 | QAction* getAboutBenchmarkAppAction(); 92 | 93 | private: 94 | QMenu* m_fileMenu; 95 | QMenu* m_recentFileMenu; 96 | QMenu* m_closeFileMenu; 97 | QMenu* m_helpMenu; 98 | 99 | QAction* m_openFileAction; 100 | QList m_openRecentFilesAction; 101 | QList m_closeFileActions; 102 | QAction* m_closeAllFilesAction; 103 | QAction* m_exportChart; 104 | QAction* m_exitAction; 105 | 106 | QAction* m_toogleSelectedFileWidget; 107 | QAction* m_aboutApp; 108 | 109 | QStack m_files; 110 | QListWidget* m_selectedFilesWidget; 111 | QItemSelectionModel* m_selectionModel; 112 | BenchmarkView* m_benchmarkView; 113 | BenchmarkDelegate* m_benchmarkDelegate; 114 | 115 | IAbstractParser* m_parser; 116 | QChart* m_chart; 117 | QLineEdit* m_benchmarkNameFilter; 118 | 119 | MainWindowPresenter *m_mainWindowPresenter; 120 | }; 121 | -------------------------------------------------------------------------------- /app/benchmarkdelegate.cpp: -------------------------------------------------------------------------------- 1 | /*========================================================================= 2 | 3 | Program: BenchmarkViewer 4 | 5 | Copyright (c) 2018 Asit Dhal 6 | All rights reserved. 7 | 8 | BenchmarkViewer is a free software; you can redistribute it and/or modify it. 9 | 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 12 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 13 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 14 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR 15 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 19 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | ========================================================================*/ 24 | 25 | #include "benchmarkdelegate.h" 26 | #include 27 | #include 28 | #include 29 | 30 | static QRect CheckBoxRect(const QStyleOptionViewItem& view_item_style_options) 31 | { 32 | QStyleOptionButton check_box_style_option; 33 | QRect check_box_rect = QApplication::style()->subElementRect(QStyle::SE_CheckBoxIndicator, &check_box_style_option); 34 | QPoint check_box_point(view_item_style_options.rect.x() + view_item_style_options.rect.width() / 2 - check_box_rect.width() / 2, 35 | view_item_style_options.rect.y() + view_item_style_options.rect.height() / 2 - check_box_rect.height() / 2); 36 | return QRect(check_box_point, check_box_rect.size()); 37 | } 38 | 39 | BenchmarkDelegate::BenchmarkDelegate(QObject* parent) : QStyledItemDelegate(parent) {} 40 | 41 | bool BenchmarkDelegate::editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index) 42 | { 43 | if (index.column() == 0) { 44 | if ((event->type() == QEvent::MouseButtonRelease) 45 | || (event->type() == QEvent::MouseButtonDblClick)) { 46 | QMouseEvent* mouse_event = static_cast(event); 47 | if (mouse_event->button() != Qt::LeftButton 48 | || !CheckBoxRect(option).contains(mouse_event->pos())) { 49 | return false; 50 | } 51 | if (event->type() == QEvent::MouseButtonDblClick) { 52 | return true; 53 | } 54 | } else if (event->type() == QEvent::KeyPress) { 55 | if (static_cast(event)->key() != Qt::Key_Space 56 | && static_cast(event)->key() != Qt::Key_Select) { 57 | return false; 58 | } 59 | } else { 60 | return false; 61 | } 62 | 63 | bool checked = index.model()->data(index, Qt::DisplayRole).toBool(); 64 | return model->setData(index, !checked, Qt::EditRole); 65 | } else { 66 | return QStyledItemDelegate::editorEvent(event, model, option, index); 67 | } 68 | } 69 | 70 | void BenchmarkDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const 71 | { 72 | if (index.column() == 0) { 73 | bool checked = index.model()->data(index, Qt::DisplayRole).toBool(); 74 | 75 | QStyleOptionButton check_box_style_option; 76 | check_box_style_option.state |= QStyle::State_Enabled; 77 | if (checked) { 78 | check_box_style_option.state |= QStyle::State_On; 79 | } else { 80 | check_box_style_option.state |= QStyle::State_Off; 81 | } 82 | check_box_style_option.rect = CheckBoxRect(option); 83 | 84 | QApplication::style()->drawControl(QStyle::CE_CheckBox, &check_box_style_option, painter); 85 | } else { 86 | QStyledItemDelegate::paint(painter, option, index); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /app/chartviewwidget.cpp: -------------------------------------------------------------------------------- 1 | /*========================================================================= 2 | 3 | Program: BenchmarkViewer 4 | 5 | Copyright (c) 2018 Asit Dhal 6 | All rights reserved. 7 | 8 | BenchmarkViewer is a free software; you can redistribute it and/or modify it. 9 | 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 12 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 13 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 14 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR 15 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 19 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | ========================================================================*/ 24 | 25 | #include "chartviewwidget.h" 26 | 27 | #include 28 | #include 29 | 30 | Q_LOGGING_CATEGORY(chartView, "chartView"); 31 | 32 | ChartViewWidget *ChartViewWidget::m_pInstance = nullptr; 33 | 34 | ChartViewWidget* ChartViewWidget::getInstance() 35 | { 36 | Q_ASSERT(m_pInstance); 37 | return m_pInstance; 38 | } 39 | 40 | ChartViewWidget::ChartViewWidget(QWidget* parent) 41 | : QWidget(parent), m_chartView(new QChartView) 42 | { 43 | if (m_pInstance) { 44 | m_pInstance->deleteLater(); 45 | } 46 | m_pInstance = this; 47 | init(); 48 | QHBoxLayout* mainLayout = new QHBoxLayout; 49 | mainLayout->addWidget(m_chartView); 50 | setLayout(mainLayout); 51 | } 52 | 53 | bool ChartViewWidget::exportChart(QString filename) 54 | { 55 | QPixmap pixmap = grab(); 56 | if (!filename.isEmpty()) 57 | { 58 | return pixmap.save(filename, "PNG"); 59 | } 60 | return false; 61 | } 62 | 63 | void ChartViewWidget::init() 64 | { 65 | m_chart = new QChart; 66 | m_series = new QBarSeries; 67 | m_chart->addSeries(m_series); 68 | m_chart->legend()->setVisible(true); 69 | m_chart->legend()->setAlignment(Qt::AlignRight); 70 | QStringList categories; 71 | categories << "CPU Time" << "Real Time"; 72 | m_axis = new QBarCategoryAxis(); 73 | m_axis->append(categories); 74 | m_chart->createDefaultAxes(); 75 | m_chart->axisY()->setMin(0); 76 | m_chart->setAxisX(m_axis, m_series); 77 | m_chart->setAnimationOptions(QChart::AllAnimations); 78 | m_chartView->setChart(m_chart); 79 | m_chartView->setRenderHint(QPainter::Antialiasing); 80 | } 81 | 82 | void ChartViewWidget::onAddMeasurement(const Measurement &mmt) 83 | { 84 | qCDebug(chartView) << "New Measurement: " << mmt; 85 | QString name = mmt.getName(); 86 | double cpuTime = mmt.getCpuTime(); 87 | double realTime = mmt.getRealTime(); 88 | QBarSet* set = new QBarSet(name); 89 | *set << cpuTime << realTime; 90 | m_barSet[mmt.getId()] = set; 91 | m_series->append(set); 92 | m_chart->axisY()->setMax(calculateMaxY() + 10); 93 | QString hexColor = "#" + QString::number(set->brush().color().rgb(), 16) 94 | .right(6).toUpper(); 95 | emit measurementColorChanged(mmt.getId(), hexColor); 96 | } 97 | 98 | double ChartViewWidget::calculateMaxY() 99 | { 100 | double maxY = 50; 101 | foreach (QBarSet* barSet, m_barSet.values()) 102 | { 103 | if (barSet->at(0) > maxY) 104 | { 105 | maxY = barSet->at(0); 106 | } 107 | if (barSet->at(1) > maxY) 108 | { 109 | maxY = barSet->at(1); 110 | } 111 | } 112 | return maxY; 113 | } 114 | 115 | void ChartViewWidget::onRemoveMeasurement(const Measurement &mmt) 116 | { 117 | qCDebug(chartView) << "Removed Measurement: " << mmt; 118 | QBarSet* set = m_barSet[mmt.getId()]; 119 | m_series->remove(set); 120 | m_barSet.remove(mmt.getId()); 121 | m_chart->axisY()->setMax(calculateMaxY()); 122 | } 123 | -------------------------------------------------------------------------------- /app/measurement.cpp: -------------------------------------------------------------------------------- 1 | /*========================================================================= 2 | 3 | Program: BenchmarkViewer 4 | 5 | Copyright (c) 2018 Asit Dhal 6 | All rights reserved. 7 | 8 | BenchmarkViewer is a free software; you can redistribute it and/or modify it. 9 | 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 12 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 13 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 14 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR 15 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 19 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | ========================================================================*/ 24 | 25 | #include "measurement.h" 26 | #include "helper.h" 27 | 28 | Measurement::Measurement() noexcept 29 | { 30 | m_id = Helper::getUniqueMeasurementId(); 31 | m_name = ""; 32 | m_iterations = 0; 33 | m_realTime = 0; 34 | m_cpuTime = 0; 35 | m_timeUnit = ""; 36 | m_bytesPerSecond = 0; 37 | m_itemsPerSecond = 0; 38 | m_label = ""; 39 | m_errorOccured = false; 40 | m_errorMessage = ""; 41 | } 42 | 43 | QString Measurement::getName() const 44 | { 45 | return m_name; 46 | } 47 | 48 | void Measurement::setName(const QString& value) 49 | { 50 | m_name = value; 51 | } 52 | 53 | quint64 Measurement::getIterations() const 54 | { 55 | return m_iterations; 56 | } 57 | 58 | void Measurement::setIterations(quint64 value) 59 | { 60 | m_iterations = value; 61 | } 62 | 63 | quint64 Measurement::getRealTime() const 64 | { 65 | return m_realTime; 66 | } 67 | 68 | void Measurement::setRealTime(quint64 value) 69 | { 70 | m_realTime = value; 71 | } 72 | 73 | quint64 Measurement::getCpuTime() const 74 | { 75 | return m_cpuTime; 76 | } 77 | 78 | void Measurement::setCpuTime(quint64 value) 79 | { 80 | m_cpuTime = value; 81 | } 82 | 83 | QString Measurement::getTimeUnit() const 84 | { 85 | return m_timeUnit; 86 | } 87 | 88 | void Measurement::setTimeUnit(const QString& value) 89 | { 90 | m_timeUnit = value; 91 | } 92 | 93 | int Measurement::getId() const 94 | { 95 | return m_id; 96 | } 97 | 98 | quint64 Measurement::getBytesPerSecond() const 99 | { 100 | return m_bytesPerSecond; 101 | } 102 | 103 | void Measurement::setBytesPerSecond(const quint64& bytesPerSecond) 104 | { 105 | m_bytesPerSecond = bytesPerSecond; 106 | } 107 | 108 | quint64 Measurement::getItemsPerSecond() const 109 | { 110 | return m_itemsPerSecond; 111 | } 112 | 113 | void Measurement::setItemsPerSecond(const quint64& itemsPerSecond) 114 | { 115 | m_itemsPerSecond = itemsPerSecond; 116 | } 117 | 118 | QString Measurement::getLabel() const 119 | { 120 | return m_label; 121 | } 122 | 123 | void Measurement::setLabel(const QString& label) 124 | { 125 | m_label = label; 126 | } 127 | 128 | bool Measurement::getErrorOccured() const 129 | { 130 | return m_errorOccured; 131 | } 132 | 133 | void Measurement::setErrorOccured(bool errorOccured) 134 | { 135 | m_errorOccured = errorOccured; 136 | } 137 | 138 | QString Measurement::getErrorMessage() const 139 | { 140 | return m_errorMessage; 141 | } 142 | 143 | void Measurement::setErrorMessage(const QString& errorMessage) 144 | { 145 | m_errorMessage = errorMessage; 146 | } 147 | 148 | QDebug operator<<(QDebug d, const Measurement& mmt) 149 | { 150 | d << "id: " << mmt.getId() << "name: " << mmt.getName() 151 | << " iterations: " << mmt.getIterations() 152 | << " real_time: " << mmt.getRealTime() 153 | << " cpu_time: " << mmt.getCpuTime() 154 | << " time_unit: " << mmt.getTimeUnit(); 155 | d << " bytes_per_second: " << mmt.getBytesPerSecond() 156 | << " items_per_second: " << mmt.getItemsPerSecond() 157 | << " label: " << mmt.getLabel() 158 | << " error_occured: " << mmt.getErrorOccured() 159 | << " error_message: " << mmt.getErrorMessage(); 160 | return d; 161 | } 162 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2018 Asit Dhal 2 | # Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | version: 0.0.1-{build} 5 | 6 | configuration: 7 | - Release 8 | - Debug 9 | 10 | image: 11 | - Visual Studio 2017 12 | - Visual Studio 2015 13 | 14 | platform: 15 | - x64 16 | - win32 17 | 18 | branches: 19 | only: 20 | - master 21 | 22 | matrix: 23 | fast_finish: false 24 | exclude: 25 | - platform: win32 26 | image: Visual Studio 2017 27 | 28 | environment: 29 | matrix: 30 | - CMAKE_BUILD_SYS: True 31 | - QMAKE_BUILD_SYS: True 32 | 33 | install: 34 | - ps: | 35 | if ($Env:Platform -Match "x64") { 36 | if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2015") { 37 | $qt_path="C:\Qt\5.10.1\msvc2015_64\bin" 38 | $mingw_path="C:\MinGW\bin" 39 | $env:Path+=";" + $qt_path +";" + $mingw_path 40 | cmd.exe /c "call `"C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd`" /x64 && call `"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat`" x86_amd64 && set > %temp%\vcvars.txt" 41 | } else { 42 | $qt_path="C:\Qt\5.10.1\msvc2017_64\bin" 43 | $mingw_path="C:\MinGW\bin" 44 | $env:Path+=";" + $qt_path +";" + $mingw_path 45 | cmd.exe /c "call `"C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat`" && set > %temp%\vcvars.txt" 46 | } 47 | } else { 48 | if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2015") { 49 | $qt_path="C:\Qt\5.10.1\msvc2015\bin" 50 | $mingw_path="C:\MinGW\bin" 51 | $env:Path+=";" + $qt_path +";" + $mingw_path 52 | cmd.exe /c "call `"C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd`" /x64 && call `"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat`" x86 && set > %temp%\vcvars.txt" 53 | } 54 | # win32 build is not available for vs2017 55 | } 56 | 57 | Get-Content "$env:temp\vcvars.txt" | Foreach-Object { 58 | if ($_ -match "^(.*?)=(.*)$") { 59 | Set-Content "env:\$($matches[1])" $matches[2] 60 | } 61 | } 62 | 63 | build: 64 | parallel: true 65 | 66 | build_script: 67 | - ps: $env:BUILD_PATH=$env:APPVEYOR_BUILD_FOLDER + "\build_" + $env:platform 68 | - mkdir %BUILD_PATH% 69 | - cd %BUILD_PATH% 70 | - if "%platform%"=="x64" ( 71 | if "%APPVEYOR_BUILD_WORKER_IMAGE%" == "Visual Studio 2017" ( 72 | if "%CMAKE_BUILD_SYS%" == "True" ( 73 | cmake %APPVEYOR_BUILD_FOLDER% -G "Visual Studio 15 2017 Win64" -DCMAKE_BUILD_TYPE=%configuration% 74 | ) else ( 75 | qmake %APPVEYOR_BUILD_FOLDER%\BenchmarkViewer.pro CONFIG+=%configuration% DESTDIR=%cd% 76 | ) 77 | ) else ( 78 | if "%CMAKE_BUILD_SYS%" == "True" ( 79 | cmake %APPVEYOR_BUILD_FOLDER% -G "Visual Studio 14 2015 Win64" -DCMAKE_BUILD_TYPE=%configuration% 80 | ) else ( 81 | qmake %APPVEYOR_BUILD_FOLDER%\BenchmarkViewer.pro CONFIG+=%configuration% DESTDIR=%cd% 82 | ) 83 | ) 84 | ) else ( 85 | if "%APPVEYOR_BUILD_WORKER_IMAGE%" == "Visual Studio 2015" ( 86 | if "%CMAKE_BUILD_SYS%" == "True" ( 87 | cmake %APPVEYOR_BUILD_FOLDER% -G "Visual Studio 14 2015" -DCMAKE_BUILD_TYPE=%configuration% 88 | ) else ( 89 | qmake %APPVEYOR_BUILD_FOLDER%\BenchmarkViewer.pro CONFIG+=%configuration% DESTDIR=%cd% 90 | ) 91 | ) 92 | ) 93 | 94 | - if "%CMAKE_BUILD_SYS%" == "True" ( 95 | cmake --build . --config %configuration% 96 | ) else ( 97 | nmake 98 | ) 99 | 100 | after_build: 101 | - if "%CMAKE_BUILD_SYS%" == "True" ( 102 | windeployqt %BUILD_PATH%\bin\%configuration%\BenchmarkViewer.exe && 103 | 7z a %APPVEYOR_BUILD_FOLDER%\BenchmarkViewer.7z %BUILD_PATH%\bin\%configuration%\* 104 | ) else ( 105 | mkdir %BUILD_PATH%\bin && 106 | copy %BUILD_PATH%\BenchmarkViewer.exe %BUILD_PATH%\bin && 107 | windeployqt %BUILD_PATH%\bin\BenchmarkViewer.exe && 108 | 7z a %APPVEYOR_BUILD_FOLDER%\BenchmarkViewer.7z %BUILD_PATH%\bin\* 109 | ) 110 | 111 | artifacts: 112 | - path: BenchmarkViewer.7z 113 | name: BenchmarkViewer 114 | -------------------------------------------------------------------------------- /app/jsonparser.cpp: -------------------------------------------------------------------------------- 1 | /*========================================================================= 2 | 3 | Program: BenchmarkViewer 4 | 5 | Copyright (c) 2018 Asit Dhal 6 | All rights reserved. 7 | 8 | BenchmarkViewer is a free software; you can redistribute it and/or modify it. 9 | 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 12 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 13 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 14 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR 15 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 19 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | ========================================================================*/ 24 | 25 | #include "jsonparser.h" 26 | #include "globals.h" 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | void JsonParser::parse(QString filename) 34 | { 35 | qCDebug(parser) << "Parsing started: " << filename; 36 | QFile file; 37 | file.setFileName(filename); 38 | file.open(QIODevice::ReadOnly | QIODevice::Text); 39 | QString fileContent = file.readAll(); 40 | file.close(); 41 | 42 | QJsonDocument jsonDocument = QJsonDocument::fromJson(fileContent.toUtf8()); 43 | QJsonObject jsonObj = jsonDocument.object(); 44 | m_benchmark.setContext(parseContext(jsonObj)); 45 | m_benchmark.setMeasurements(parseBenchmarks(jsonObj)); 46 | qCDebug(parser) << "Parsing finished: " << filename; 47 | } 48 | 49 | Context JsonParser::parseContext(const QJsonObject& json) 50 | { 51 | Context ctx; 52 | if (json.contains("context")) 53 | { 54 | QJsonObject ctxJObject = json["context"].toObject(); 55 | if (ctxJObject.contains("date") && ctxJObject["date"].isString()) 56 | { 57 | auto timestampStr = ctxJObject["date"].toString(); 58 | QDateTime timestamp = QDateTime::fromString( 59 | timestampStr, "yyyy-MM-dd HH:mm:ss"); // 2017-12-09 22:01:41 60 | ctx.setTimestamp(timestamp); 61 | } 62 | if (ctxJObject.contains("num_cpus") 63 | && ctxJObject["num_cpus"].isDouble()) 64 | { 65 | ctx.setCpuCount(ctxJObject["num_cpus"].toInt()); 66 | } 67 | if (ctxJObject.contains("mhz_per_cpu") 68 | && ctxJObject["mhz_per_cpu"].isDouble()) 69 | { 70 | ctx.setCpuFrequency(ctxJObject["mhz_per_cpu"].toInt()); 71 | } 72 | if (ctxJObject.contains("cpu_scaling_enabled") 73 | && ctxJObject["cpu_scaling_enabled"].isBool()) 74 | { 75 | ctx.setCpuScalingEnabled(ctxJObject["cpu_scaling_enabled"].toBool()); 76 | } 77 | if (ctxJObject.contains("library_build_type") 78 | && ctxJObject["library_build_type"].isString()) 79 | { 80 | ctx.setLibraryBuildType(ctxJObject["library_build_type"].toString()); 81 | } 82 | } 83 | else 84 | { 85 | qCCritical(parser) << "No context exists"; 86 | } 87 | qCDebug(parser) << "Context: " << ctx; 88 | return ctx; 89 | } 90 | 91 | QVector JsonParser::parseBenchmarks(const QJsonObject& json) 92 | { 93 | QVector mmts; 94 | if (json.contains("benchmarks") && json["benchmarks"].isArray()) 95 | { 96 | QJsonArray jsonArrayObject = json["benchmarks"].toArray(); 97 | foreach (const QJsonValue& value, jsonArrayObject) 98 | { 99 | QJsonObject jsonObj = value.toObject(); 100 | Measurement mmt; 101 | 102 | if (jsonObj.contains("name") && jsonObj["name"].isString()) 103 | { 104 | mmt.setName(jsonObj["name"].toString()); 105 | } 106 | 107 | if (jsonObj.contains("iterations") 108 | && jsonObj["iterations"].isDouble()) 109 | { 110 | mmt.setIterations(jsonObj["iterations"].toVariant().toLongLong()); 111 | } 112 | 113 | if (jsonObj.contains("real_time") 114 | && jsonObj["real_time"].isDouble()) 115 | { 116 | mmt.setRealTime(jsonObj["real_time"].toVariant().toLongLong()); 117 | } 118 | 119 | if (jsonObj.contains("cpu_time") && jsonObj["cpu_time"].isDouble()) 120 | { 121 | mmt.setCpuTime(jsonObj["cpu_time"].toVariant().toLongLong()); 122 | } 123 | 124 | if (jsonObj.contains("time_unit") && jsonObj["time_unit"].isString()) 125 | { 126 | mmt.setTimeUnit(jsonObj["time_unit"].toString()); 127 | } 128 | 129 | mmts.push_back(mmt); 130 | } 131 | } 132 | else 133 | { 134 | qCCritical(parser) << "No benchmark exists"; 135 | } 136 | 137 | qCDebug(parser) << "No. of measurements: " << mmts.size(); 138 | 139 | return mmts; 140 | } 141 | 142 | Benchmark JsonParser::getBenchmark() const 143 | { 144 | return m_benchmark; 145 | } 146 | -------------------------------------------------------------------------------- /app/csvparser.cpp: -------------------------------------------------------------------------------- 1 | /*========================================================================= 2 | 3 | Program: QCommander 4 | 5 | Copyright (c) 2018 Asit Dhal 6 | All rights reserved. 7 | 8 | QCommander is a free software; you can redistribute it and/or modify it. 9 | 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 12 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 13 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 14 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR 15 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 19 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | ========================================================================*/ 24 | 25 | #include "csvparser.h" 26 | #include 27 | #include 28 | #include 29 | #include "globals.h" 30 | 31 | void CsvParser::parse(QString filename) 32 | { 33 | qCDebug(parser) << "Parsing started: " << filename; 34 | QFile file; 35 | file.setFileName(filename); 36 | file.open(QIODevice::ReadOnly | QIODevice::Text); 37 | QString fileContent = file.readAll(); 38 | file.close(); 39 | 40 | QStringList lines = fileContent.split(QRegExp("[\r\n]"), 41 | QString::SkipEmptyParts); 42 | 43 | QStringList headerFields = parseHeaders(lines.at(0)); 44 | lines.pop_front(); 45 | auto mmts = parseBenchmarks(lines, headerFields); 46 | m_benchmark.setMeasurements(mmts.toVector()); 47 | qCDebug(parser) << "Parsing finished: " << filename; 48 | } 49 | 50 | QStringList CsvParser::parseHeaders(QString header) 51 | { 52 | QStringList fields = header.split(",", QString::KeepEmptyParts); 53 | QList headerFields; 54 | for (QString s : fields) 55 | { 56 | headerFields.append(s.trimmed()); 57 | } 58 | return headerFields; 59 | } 60 | 61 | QList CsvParser::parseBenchmarks(QStringList& data, 62 | QStringList& header) 63 | { 64 | QList mmts; 65 | for (auto const& rec : data) 66 | { 67 | QStringList fields = rec.split(",", QString::KeepEmptyParts); 68 | 69 | Measurement mmt; 70 | for (auto i = 0; i < header.size(); i++) 71 | { 72 | qCDebug(parser) << "Data: " << fields; 73 | if (header.at(i).compare("name", Qt::CaseInsensitive) == 0) 74 | { 75 | QString name = fields.at(i); 76 | name.replace("'", ""); 77 | name.replace("\"", ""); 78 | mmt.setName(name); 79 | } 80 | else if (header.at(i).compare("iterations", 81 | Qt::CaseInsensitive) == 0) 82 | { 83 | mmt.setIterations(fields.at(i).toDouble()); 84 | } 85 | else if (header.at(i).compare("real_time", 86 | Qt::CaseInsensitive) == 0) 87 | { 88 | mmt.setRealTime(fields.at(i).toDouble()); 89 | } 90 | else if (header.at(i).compare("cpu_time", 91 | Qt::CaseInsensitive) == 0) 92 | { 93 | mmt.setCpuTime(fields.at(i).toDouble()); 94 | } 95 | else if (header.at(i).compare("time_unit", 96 | Qt::CaseInsensitive) == 0) 97 | { 98 | mmt.setTimeUnit(fields.at(i)); 99 | } 100 | else if (header.at(i).compare("bytes_per_second", 101 | Qt::CaseInsensitive) == 0) 102 | { 103 | mmt.setBytesPerSecond(fields.at(i).toDouble()); 104 | } 105 | else if (header.at(i).compare("items_per_second", 106 | Qt::CaseInsensitive) == 0) 107 | { 108 | mmt.setItemsPerSecond(fields.at(i).toDouble()); 109 | } 110 | else if (header.at(i).compare("label", 111 | Qt::CaseInsensitive) == 0) 112 | { 113 | mmt.setLabel(fields.at(i).trimmed()); 114 | } 115 | else if (header.at(i).compare("error_occured", 116 | Qt::CaseInsensitive) == 0) 117 | { 118 | mmt.setErrorOccured(fields.at(i).toInt()); 119 | } 120 | else if (header.at(i).compare("error_message", 121 | Qt::CaseInsensitive) == 0) 122 | { 123 | mmt.setErrorMessage(fields.at(i).trimmed()); 124 | } 125 | else 126 | { 127 | qCDebug(parser) << "Error occured Unknown field: " 128 | << fields.at(i); 129 | } 130 | } 131 | mmts.append(mmt); 132 | } 133 | return mmts; 134 | } 135 | 136 | Benchmark CsvParser::getBenchmark() const 137 | { 138 | return m_benchmark; 139 | } 140 | -------------------------------------------------------------------------------- /app/benchmarkview.cpp: -------------------------------------------------------------------------------- 1 | /*========================================================================= 2 | 3 | Program: BenchmarkViewer 4 | 5 | Copyright (c) 2018 Asit Dhal 6 | All rights reserved. 7 | 8 | BenchmarkViewer is a free software; you can redistribute it and/or modify it. 9 | 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 12 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 13 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 14 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR 15 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 19 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | ========================================================================*/ 24 | 25 | #include "benchmarkview.h" 26 | #include 27 | #include 28 | #include "globals.h" 29 | 30 | BenchmarkView::BenchmarkView(QWidget* parent) 31 | : QTableView(parent) 32 | { 33 | m_header = horizontalHeader(); 34 | m_header->setSectionsMovable(true); 35 | m_header->setContextMenuPolicy(Qt::CustomContextMenu); 36 | connect(m_header, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(onContextMenuOnHeader(const QPoint&))); 37 | 38 | this->setContextMenuPolicy(Qt::CustomContextMenu); 39 | connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(onContextMenuOnBody(const QPoint&))); 40 | 41 | m_moveLastAction = new QAction("MoveLast", this); 42 | connect(m_moveLastAction, SIGNAL(triggered(bool)), this, SLOT(onSlotMoveLast())); 43 | m_moveFirstAction = new QAction("MoveFirst", this); 44 | connect(m_moveFirstAction, SIGNAL(triggered(bool)), this, SLOT(onSlotMoveFirst())); 45 | 46 | m_select = new QAction(tr("Select"), this); 47 | connect(m_select, &QAction::triggered, [&]() { emit this->select(); }); 48 | m_selectAll = new QAction(tr("Select All"), this); 49 | connect(m_selectAll, &QAction::triggered, [&]() { emit this->selectAllRows(); }); 50 | m_clearSelection = new QAction(tr("Clear Selection"), this); 51 | connect(m_clearSelection, &QAction::triggered, [&]() { emit this->clearSelection(); }); 52 | m_clearAllRows = new QAction(tr("Clear All rows"), this); 53 | connect(m_clearAllRows, &QAction::triggered, [&]() { emit this->clearAllRows(); }); 54 | 55 | } 56 | 57 | void BenchmarkView::seBenchmarkColumnAttributes(BenchmarkModel *bmModel) 58 | { 59 | for (auto i = 0; i < BenchmarkModel::COLUMN_COUNT; i++) 60 | { 61 | auto col = static_cast(i); 62 | QAction* showHideColumn = new QAction(toString(col), this); 63 | showHideColumn->setCheckable(true); 64 | showHideColumn->setChecked(bmModel->getColumnVisibility(col)); 65 | connect(showHideColumn, &QAction::triggered, this, [=, _col=col]() { 66 | bmModel->setColumnVisibility( 67 | _col,!bmModel->getColumnVisibility(_col)); 68 | }); 69 | m_columnShowHideActions.append(showHideColumn); 70 | } 71 | 72 | connect(bmModel, &BenchmarkModel::columnVisibilityChanged, 73 | [&](BenchmarkModel::Columns col, bool visibility) { 74 | qCDebug(gui) << "col visibility changed: " << toString(col) 75 | << " visibility: " << visibility; 76 | (visibility == true) ? onShowColumn(col) : onHideColumn(col); 77 | }); 78 | } 79 | 80 | void BenchmarkView::onContextMenuOnHeader(QPoint p) 81 | { 82 | qCDebug(gui) << "context menu requested"; 83 | QMenu menu; 84 | QPoint p2 = mapToGlobal(p); 85 | int logicIndex = m_header->logicalIndexAt(p); 86 | qCDebug(gui) << "Logical Index: " << logicIndex; 87 | menu.addActions(m_columnShowHideActions); 88 | menu.addSeparator(); 89 | menu.addAction(m_moveLastAction); 90 | m_moveLastAction->setData(logicIndex); 91 | menu.addAction(m_moveFirstAction); 92 | m_moveFirstAction->setData(logicIndex); 93 | menu.exec(p2); 94 | } 95 | 96 | void BenchmarkView::onContextMenuOnBody(QPoint p) 97 | { 98 | qCDebug(gui) << "context menu requested"; 99 | QMenu menu; 100 | QPoint p2 = mapToGlobal(p); 101 | menu.addAction(m_select); 102 | menu.addAction(m_selectAll); 103 | menu.addAction(m_clearSelection); 104 | menu.addAction(m_clearAllRows); 105 | menu.exec(p2); 106 | } 107 | 108 | void BenchmarkView::onSlotMoveLast() 109 | { 110 | int last = m_header->count() - 1; 111 | int current = m_moveLastAction->data().toInt(); 112 | int from = m_header->visualIndex(current); 113 | m_header->moveSection(from, last); 114 | } 115 | 116 | void BenchmarkView::onSlotMoveFirst() 117 | { 118 | int current = m_moveFirstAction->data().toInt(); 119 | int from = m_header->visualIndex(current); 120 | m_header->moveSection(from, 0); 121 | } 122 | 123 | void BenchmarkView::onShowColumn(BenchmarkModel::Columns col) 124 | { 125 | showColumn(static_cast(col)); 126 | m_columnShowHideActions.at(static_cast(col))->setChecked(true); 127 | } 128 | 129 | void BenchmarkView::onHideColumn(BenchmarkModel::Columns col) 130 | { 131 | hideColumn(static_cast(col)); 132 | m_columnShowHideActions.at(static_cast(col))->setChecked(false); 133 | } 134 | -------------------------------------------------------------------------------- /app/mainwindow_presenter.cpp: -------------------------------------------------------------------------------- 1 | #include "mainwindow_presenter.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "mainwindow.h" 9 | #include "appconfig.h" 10 | #include "globals.h" 11 | #include "helper.h" 12 | #include "benchmarkmodel.h" 13 | #include "chartviewwidget.h" 14 | 15 | MainWindowPresenter::MainWindowPresenter(MainWindow* mainWindow, QObject* parent): QObject(parent), m_view(mainWindow) 16 | { 17 | m_worker.moveToThread(&m_workerThread); 18 | m_workerThread.start(); 19 | 20 | connect(QCoreApplication::instance(), &QApplication::aboutToQuit, 21 | [&]() { m_workerThread.quit(); 22 | m_workerThread.wait(); }); 23 | 24 | connectSignalsToSlots(); 25 | updateRecentFilesActions(); 26 | } 27 | 28 | void MainWindowPresenter::connectSignalsToSlots() 29 | { 30 | connect(this, &MainWindowPresenter::newFileSelected, 31 | &m_worker, &Worker::parse); 32 | connect(&m_worker, &Worker::parsingFinished, 33 | this, &MainWindowPresenter::onNewBenchmark); 34 | connect(this, &MainWindowPresenter::fileRemoved, 35 | this, &MainWindowPresenter::onRemoveBenchmark); 36 | 37 | connect(m_view->getOpenFileAction(), &QAction::triggered, 38 | this, &MainWindowPresenter::onOpenFileTriggered); 39 | connect(m_view->getCloseAllFilesAction(), &QAction::triggered, 40 | this, &MainWindowPresenter::onCloseAllFilesTriggered); 41 | connect(m_view->getExportChartAction(), &QAction::triggered, 42 | this, &MainWindowPresenter::onExportChartTriggered); 43 | connect(m_view->getExitAction(), &QAction::triggered, 44 | this, &MainWindowPresenter::onExitTriggered); 45 | connect(m_view->getAboutBenchmarkAppAction(), &QAction::triggered, 46 | this, &MainWindowPresenter::onAboutAppTriggered); 47 | } 48 | 49 | void MainWindowPresenter::onOpenFileTriggered() 50 | { 51 | QString lastPath = readLastOpenedFilePath(); 52 | QStringList files = QFileDialog::getOpenFileNames( 53 | m_view, tr("Open Directory"), lastPath); 54 | for (auto file : files) 55 | { 56 | openFile(file); 57 | } 58 | } 59 | 60 | void MainWindowPresenter::onCloseAllFilesTriggered() 61 | { 62 | for (auto file : m_openedFiles) 63 | { 64 | closeFile(file); 65 | } 66 | } 67 | 68 | void MainWindowPresenter::onExportChartTriggered() 69 | { 70 | QString lastPath = readLastExportedFilePath(); 71 | QString filename = QFileDialog::getSaveFileName( 72 | m_view, tr("Save Chart"), lastPath, tr("png file (*.png)")); 73 | updateLastExportedFilePath(QFileInfo(filename).path()); 74 | if (!ChartViewWidget::getInstance()->exportChart(filename)) 75 | { 76 | qCCritical(gui) << "Export failed"; 77 | } 78 | } 79 | 80 | void MainWindowPresenter::onExitTriggered() 81 | { 82 | qCDebug(gui) << "closing application"; 83 | QApplication::quit(); 84 | } 85 | 86 | void MainWindowPresenter::onAboutAppTriggered() 87 | { 88 | QString text = QString("Benchmark Viewer to plot google" 89 | " microbenchmark data ") 90 | + QChar(0x00A9) 91 | + QString(" 2018 Asit Dhal"); 92 | 93 | QMessageBox::about(m_view, tr("About BenchmarkViewer"), text); 94 | } 95 | 96 | void MainWindowPresenter::onNewBenchmark(QString filename, Benchmark benchmark) 97 | { 98 | BenchmarkModel::getInstance()->addBenchmark(filename, benchmark); 99 | //m_benchmarkView->resizeColumnsToContents(); 100 | } 101 | 102 | void MainWindowPresenter::onRemoveBenchmark(QString filename) 103 | { 104 | BenchmarkModel::getInstance()->removeBenchmark(filename); 105 | //m_benchmarkView->resizeColumnsToContents(); 106 | } 107 | 108 | 109 | void MainWindowPresenter::openFile(QString filename) 110 | { 111 | if (!filename.isEmpty()) 112 | { 113 | updateRecentFiles(filename); 114 | updateRecentFilesActions(); 115 | 116 | emit newFileSelected(Helper::getParserTypeFromFilename(filename), 117 | filename); 118 | 119 | updateLastOpenedFilePath(QFileInfo(filename).path()); 120 | m_openedFiles.append(filename); 121 | updateCloseFileActions(); 122 | } 123 | } 124 | 125 | void MainWindowPresenter::closeFile(QString filename) 126 | { 127 | if (!filename.isEmpty()) 128 | { 129 | emit fileRemoved(filename); 130 | m_openedFiles.removeOne(filename); 131 | updateCloseFileActions(); 132 | } 133 | } 134 | 135 | void MainWindowPresenter::updateRecentFilesActions() 136 | { 137 | QList recentFileActions; 138 | QStringList recentFiles = readRecentFiles(); 139 | qCDebug(gui) << "Recent Files: " << recentFiles.size() 140 | << "->" << recentFiles; 141 | int i = 1; 142 | foreach(QString recentFile, recentFiles) 143 | { 144 | if (recentFile.isEmpty()) 145 | continue; 146 | QString text = tr("&%1 %2").arg(i) 147 | .arg(QFileInfo(recentFile).fileName()); 148 | QAction* recentFileAction = new QAction(text, m_view); 149 | recentFileAction->setData(recentFile); 150 | recentFileAction->setVisible(true); 151 | connect(recentFileAction, &QAction::triggered, 152 | [this, _recentFile = recentFile]() { 153 | openFile(_recentFile); 154 | }); 155 | i++; 156 | recentFileActions.append(recentFileAction); 157 | } 158 | m_view->setRecentFileActions(recentFileActions); 159 | } 160 | 161 | void MainWindowPresenter::updateCloseFileActions() 162 | { 163 | QList closeFileActions; 164 | int i = 1; 165 | foreach(QString openedFile, m_openedFiles) 166 | { 167 | if (openedFile.isEmpty()) 168 | continue; 169 | QString text = tr("&%1 %2").arg(i) 170 | .arg(QFileInfo(openedFile).fileName()); 171 | QAction* closeFileAction = new QAction(text, m_view); 172 | closeFileAction->setData(openedFile); 173 | closeFileAction->setVisible(true); 174 | connect(closeFileAction, &QAction::triggered, 175 | [this, _closeFile = openedFile]() { 176 | closeFile(_closeFile); 177 | }); 178 | i++; 179 | closeFileActions.append(closeFileAction); 180 | } 181 | 182 | m_view->setCloseFileActions(closeFileActions); 183 | } 184 | -------------------------------------------------------------------------------- /example_files/op.json: -------------------------------------------------------------------------------- 1 | { 2 | "context": { 3 | "date": "2018-03-21 04:33:16", 4 | "num_cpus": 2, 5 | "mhz_per_cpu": 2400, 6 | "cpu_scaling_enabled": true, 7 | "library_build_type": "debug" 8 | }, 9 | "benchmarks": [ 10 | { 11 | "name": "Bool_ToString/8", 12 | "iterations": 407948, 13 | "real_time": 2.6648836954187568e+03, 14 | "cpu_time": 1.7665960048830095e+03, 15 | "time_unit": "ns" 16 | }, 17 | { 18 | "name": "Bool_ToString/16", 19 | "iterations": 255324, 20 | "real_time": 4.0068842309711490e+03, 21 | "cpu_time": 2.7397689171402876e+03, 22 | "time_unit": "ns" 23 | }, 24 | { 25 | "name": "Bool_ToString/32", 26 | "iterations": 150018, 27 | "real_time": 7.4965436529572980e+03, 28 | "cpu_time": 5.2049151768445063e+03, 29 | "time_unit": "ns" 30 | }, 31 | { 32 | "name": "Bool_ToString/64", 33 | "iterations": 69508, 34 | "real_time": 1.5279271620116964e+04, 35 | "cpu_time": 1.0080701775336640e+04, 36 | "time_unit": "ns" 37 | }, 38 | { 39 | "name": "Bool_ToString/128", 40 | "iterations": 36722, 41 | "real_time": 2.8018351294365872e+04, 42 | "cpu_time": 1.9063650944934452e+04, 43 | "time_unit": "ns" 44 | }, 45 | { 46 | "name": "Bool_ToString/256", 47 | "iterations": 15334, 48 | "real_time": 8.0350512236829745e+04, 49 | "cpu_time": 5.2950754532417362e+04, 50 | "time_unit": "ns" 51 | }, 52 | { 53 | "name": "Bool_ToString/512", 54 | "iterations": 6788, 55 | "real_time": 1.5361046586756452e+05, 56 | "cpu_time": 1.0270547142015214e+05, 57 | "time_unit": "ns" 58 | }, 59 | { 60 | "name": "Bool_BoostLexicalCast/8", 61 | "iterations": 625049, 62 | "real_time": 1.5472143223003316e+03, 63 | "cpu_time": 9.6951085914772671e+02, 64 | "time_unit": "ns" 65 | }, 66 | { 67 | "name": "Bool_BoostLexicalCast/16", 68 | "iterations": 673522, 69 | "real_time": 1.6120539871336953e+03, 70 | "cpu_time": 1.0375532439913254e+03, 71 | "time_unit": "ns" 72 | }, 73 | { 74 | "name": "Bool_BoostLexicalCast/32", 75 | "iterations": 585969, 76 | "real_time": 1.9128522283476477e+03, 77 | "cpu_time": 1.0531572557600055e+03, 78 | "time_unit": "ns" 79 | }, 80 | { 81 | "name": "Bool_BoostLexicalCast/64", 82 | "iterations": 539694, 83 | "real_time": 2.5496826822736143e+03, 84 | "cpu_time": 1.3317058221881898e+03, 85 | "time_unit": "ns" 86 | }, 87 | { 88 | "name": "Bool_BoostLexicalCast/128", 89 | "iterations": 364258, 90 | "real_time": 3.7565596718529750e+03, 91 | "cpu_time": 1.9181948042322654e+03, 92 | "time_unit": "ns" 93 | }, 94 | { 95 | "name": "Bool_BoostLexicalCast/256", 96 | "iterations": 250654, 97 | "real_time": 4.9625146411260857e+03, 98 | "cpu_time": 2.4552481468475144e+03, 99 | "time_unit": "ns" 100 | }, 101 | { 102 | "name": "Bool_BoostLexicalCast/512", 103 | "iterations": 197899, 104 | "real_time": 6.9984276654791565e+03, 105 | "cpu_time": 3.5687714642260285e+03, 106 | "time_unit": "ns" 107 | }, 108 | { 109 | "name": "Bool_StringStream/8", 110 | "iterations": 371058, 111 | "real_time": 4.1153019810195492e+03, 112 | "cpu_time": 1.8830578103745038e+03, 113 | "time_unit": "ns" 114 | }, 115 | { 116 | "name": "Bool_StringStream/16", 117 | "iterations": 295776, 118 | "real_time": 5.0711729303434613e+03, 119 | "cpu_time": 2.4529940664550054e+03, 120 | "time_unit": "ns" 121 | }, 122 | { 123 | "name": "Bool_StringStream/32", 124 | "iterations": 226210, 125 | "real_time": 5.8416573213299971e+03, 126 | "cpu_time": 2.9716443128091773e+03, 127 | "time_unit": "ns" 128 | }, 129 | { 130 | "name": "Bool_StringStream/64", 131 | "iterations": 147769, 132 | "real_time": 9.4973111879693643e+03, 133 | "cpu_time": 5.5218661424281509e+03, 134 | "time_unit": "ns" 135 | }, 136 | { 137 | "name": "Bool_StringStream/128", 138 | "iterations": 72366, 139 | "real_time": 1.5617527151432829e+04, 140 | "cpu_time": 9.2284905894955100e+03, 141 | "time_unit": "ns" 142 | }, 143 | { 144 | "name": "Bool_StringStream/256", 145 | "iterations": 43464, 146 | "real_time": 3.7601911608309005e+04, 147 | "cpu_time": 2.1232078087627335e+04, 148 | "time_unit": "ns" 149 | }, 150 | { 151 | "name": "Bool_StringStream/512", 152 | "iterations": 14290, 153 | "real_time": 8.6235861173238503e+04, 154 | "cpu_time": 4.7745425052488259e+04, 155 | "time_unit": "ns" 156 | }, 157 | { 158 | "name": "Bool_OstringStream/8", 159 | "iterations": 344660, 160 | "real_time": 4.1111097682947238e+03, 161 | "cpu_time": 2.2775522311868713e+03, 162 | "time_unit": "ns" 163 | }, 164 | { 165 | "name": "Bool_OstringStream/16", 166 | "iterations": 223825, 167 | "real_time": 5.4779480309530927e+03, 168 | "cpu_time": 3.2320316497242902e+03, 169 | "time_unit": "ns" 170 | }, 171 | { 172 | "name": "Bool_OstringStream/32", 173 | "iterations": 166756, 174 | "real_time": 7.4136580069515849e+03, 175 | "cpu_time": 4.5857075487469519e+03, 176 | "time_unit": "ns" 177 | }, 178 | { 179 | "name": "Bool_OstringStream/64", 180 | "iterations": 89604, 181 | "real_time": 1.2049467408882989e+04, 182 | "cpu_time": 7.7828248738846414e+03, 183 | "time_unit": "ns" 184 | }, 185 | { 186 | "name": "Bool_OstringStream/128", 187 | "iterations": 66756, 188 | "real_time": 1.7932669577020733e+04, 189 | "cpu_time": 1.1552306264580384e+04, 190 | "time_unit": "ns" 191 | }, 192 | { 193 | "name": "Bool_OstringStream/256", 194 | "iterations": 34906, 195 | "real_time": 2.9149908086183128e+04, 196 | "cpu_time": 2.0054853979255804e+04, 197 | "time_unit": "ns" 198 | }, 199 | { 200 | "name": "Bool_OstringStream/512", 201 | "iterations": 18165, 202 | "real_time": 5.9888450400773087e+04, 203 | "cpu_time": 3.8623834021420582e+04, 204 | "time_unit": "ns" 205 | } 206 | ] 207 | } 208 | -------------------------------------------------------------------------------- /example_files/bool2str.json: -------------------------------------------------------------------------------- 1 | { 2 | "context": { 3 | "date": "2018-05-06 07:40:25", 4 | "num_cpus": 2, 5 | "mhz_per_cpu": 2400, 6 | "cpu_scaling_enabled": true, 7 | "library_build_type": "debug" 8 | }, 9 | "benchmarks": [ 10 | { 11 | "name": "Bool_ToString/8", 12 | "iterations": 516481, 13 | "real_time": 1.3624930772711175e+03, 14 | "cpu_time": 1.3581409016014773e+03, 15 | "time_unit": "ns" 16 | }, 17 | { 18 | "name": "Bool_ToString/16", 19 | "iterations": 317468, 20 | "real_time": 2.1996967157286622e+03, 21 | "cpu_time": 2.2024573846815711e+03, 22 | "time_unit": "ns" 23 | }, 24 | { 25 | "name": "Bool_ToString/32", 26 | "iterations": 182458, 27 | "real_time": 3.8811009599824692e+03, 28 | "cpu_time": 3.8671056188271477e+03, 29 | "time_unit": "ns" 30 | }, 31 | { 32 | "name": "Bool_ToString/64", 33 | "iterations": 99334, 34 | "real_time": 7.0418608933061951e+03, 35 | "cpu_time": 7.0446668512324231e+03, 36 | "time_unit": "ns" 37 | }, 38 | { 39 | "name": "Bool_ToString/128", 40 | "iterations": 52376, 41 | "real_time": 1.3361274648927101e+04, 42 | "cpu_time": 1.3368785607913704e+04, 43 | "time_unit": "ns" 44 | }, 45 | { 46 | "name": "Bool_ToString/256", 47 | "iterations": 26892, 48 | "real_time": 2.6055534619959366e+04, 49 | "cpu_time": 2.6058732708614887e+04, 50 | "time_unit": "ns" 51 | }, 52 | { 53 | "name": "Bool_ToString/512", 54 | "iterations": 13741, 55 | "real_time": 5.0941187904864375e+04, 56 | "cpu_time": 5.0944161487519050e+04, 57 | "time_unit": "ns" 58 | }, 59 | { 60 | "name": "Bool_BoostLexicalCast/8", 61 | "iterations": 1262058, 62 | "real_time": 5.5777025698234445e+02, 63 | "cpu_time": 5.5795320975746120e+02, 64 | "time_unit": "ns" 65 | }, 66 | { 67 | "name": "Bool_BoostLexicalCast/16", 68 | "iterations": 1097079, 69 | "real_time": 6.3460629361461133e+02, 70 | "cpu_time": 6.3800441718374816e+02, 71 | "time_unit": "ns" 72 | }, 73 | { 74 | "name": "Bool_BoostLexicalCast/32", 75 | "iterations": 956673, 76 | "real_time": 7.2639861377549573e+02, 77 | "cpu_time": 7.3140043358655271e+02, 78 | "time_unit": "ns" 79 | }, 80 | { 81 | "name": "Bool_BoostLexicalCast/64", 82 | "iterations": 780356, 83 | "real_time": 8.9102166294298547e+02, 84 | "cpu_time": 8.9697396444511241e+02, 85 | "time_unit": "ns" 86 | }, 87 | { 88 | "name": "Bool_BoostLexicalCast/128", 89 | "iterations": 597339, 90 | "real_time": 1.1661535510001111e+03, 91 | "cpu_time": 1.1719053786854886e+03, 92 | "time_unit": "ns" 93 | }, 94 | { 95 | "name": "Bool_BoostLexicalCast/256", 96 | "iterations": 405278, 97 | "real_time": 1.7083106335111431e+03, 98 | "cpu_time": 1.7123548181701397e+03, 99 | "time_unit": "ns" 100 | }, 101 | { 102 | "name": "Bool_BoostLexicalCast/512", 103 | "iterations": 285675, 104 | "real_time": 2.4459080282744385e+03, 105 | "cpu_time": 2.4498647834086210e+03, 106 | "time_unit": "ns" 107 | }, 108 | { 109 | "name": "Bool_StringStream/8", 110 | "iterations": 623409, 111 | "real_time": 1.1221498067894258e+03, 112 | "cpu_time": 1.1240855297263358e+03, 113 | "time_unit": "ns" 114 | }, 115 | { 116 | "name": "Bool_StringStream/16", 117 | "iterations": 434183, 118 | "real_time": 1.6086627045584453e+03, 119 | "cpu_time": 1.6087078697186525e+03, 120 | "time_unit": "ns" 121 | }, 122 | { 123 | "name": "Bool_StringStream/32", 124 | "iterations": 274858, 125 | "real_time": 2.5880788441700224e+03, 126 | "cpu_time": 2.5881894723838250e+03, 127 | "time_unit": "ns" 128 | }, 129 | { 130 | "name": "Bool_StringStream/64", 131 | "iterations": 165174, 132 | "real_time": 4.2588353735320425e+03, 133 | "cpu_time": 4.2590343940362154e+03, 134 | "time_unit": "ns" 135 | }, 136 | { 137 | "name": "Bool_StringStream/128", 138 | "iterations": 94171, 139 | "real_time": 7.3898424145585850e+03, 140 | "cpu_time": 7.3924474732212411e+03, 141 | "time_unit": "ns" 142 | }, 143 | { 144 | "name": "Bool_StringStream/256", 145 | "iterations": 51058, 146 | "real_time": 1.2582435406467266e+04, 147 | "cpu_time": 1.2586441302044168e+04, 148 | "time_unit": "ns" 149 | }, 150 | { 151 | "name": "Bool_StringStream/512", 152 | "iterations": 28674, 153 | "real_time": 2.4390377100250396e+04, 154 | "cpu_time": 2.4392562565373690e+04, 155 | "time_unit": "ns" 156 | }, 157 | { 158 | "name": "Bool_OstringStream/8", 159 | "iterations": 619726, 160 | "real_time": 1.1200667101325480e+03, 161 | "cpu_time": 1.1228007829260989e+03, 162 | "time_unit": "ns" 163 | }, 164 | { 165 | "name": "Bool_OstringStream/16", 166 | "iterations": 443630, 167 | "real_time": 1.6585630434969153e+03, 168 | "cpu_time": 1.6608315172535677e+03, 169 | "time_unit": "ns" 170 | }, 171 | { 172 | "name": "Bool_OstringStream/32", 173 | "iterations": 280341, 174 | "real_time": 2.4941554282231959e+03, 175 | "cpu_time": 2.4967181717976141e+03, 176 | "time_unit": "ns" 177 | }, 178 | { 179 | "name": "Bool_OstringStream/64", 180 | "iterations": 172514, 181 | "real_time": 4.0562123887109728e+03, 182 | "cpu_time": 4.0588504411230260e+03, 183 | "time_unit": "ns" 184 | }, 185 | { 186 | "name": "Bool_OstringStream/128", 187 | "iterations": 98304, 188 | "real_time": 6.8074801434364626e+03, 189 | "cpu_time": 6.8128472086651573e+03, 190 | "time_unit": "ns" 191 | }, 192 | { 193 | "name": "Bool_OstringStream/256", 194 | "iterations": 56976, 195 | "real_time": 1.2270967530274318e+04, 196 | "cpu_time": 1.2279555760339274e+04, 197 | "time_unit": "ns" 198 | }, 199 | { 200 | "name": "Bool_OstringStream/512", 201 | "iterations": 29503, 202 | "real_time": 2.3853968545690535e+04, 203 | "cpu_time": 2.3870665389948645e+04, 204 | "time_unit": "ns" 205 | } 206 | ] 207 | } 208 | -------------------------------------------------------------------------------- /app/benchmarkmodel.cpp: -------------------------------------------------------------------------------- 1 | /*========================================================================= 2 | 3 | Program: BenchmarkViewer 4 | 5 | Copyright (c) 2018 Asit Dhal 6 | All rights reserved. 7 | 8 | BenchmarkViewer is a free software; you can redistribute it and/or modify it. 9 | 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 12 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 13 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 14 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR 15 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 19 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | ========================================================================*/ 24 | 25 | #include "benchmarkmodel.h" 26 | #include 27 | #include 28 | #include 29 | 30 | Q_LOGGING_CATEGORY(benchmarkModel, "benchmarkModel") 31 | 32 | BenchmarkModel *BenchmarkModel::m_pInstance = nullptr; 33 | 34 | BenchmarkModel *BenchmarkModel::getInstance() 35 | { 36 | Q_ASSERT(m_pInstance != nullptr); 37 | return m_pInstance; 38 | } 39 | 40 | BenchmarkModel::BenchmarkModel(QObject* parent) 41 | : QAbstractTableModel(parent) 42 | { 43 | m_pInstance = this; 44 | initializeMetaData(); 45 | } 46 | 47 | const int BenchmarkModel::COLUMN_COUNT = 7; 48 | 49 | void BenchmarkModel::addBenchmark(QString filename, Benchmark benchmark) 50 | { 51 | auto mmt = benchmark.getMeasurements(); 52 | beginResetModel(); 53 | for (auto itr = mmt.begin(); itr != mmt.end(); itr++) { 54 | BenchmarkViewUnit unit; 55 | unit.filename = filename; 56 | unit.measurement = *itr; 57 | m_benchmarks.append(unit); 58 | } 59 | 60 | endResetModel(); 61 | } 62 | 63 | void BenchmarkModel::removeBenchmark(QString filename) 64 | { 65 | QList::iterator itr = m_benchmarks.begin(); 66 | 67 | beginResetModel(); 68 | while (itr != m_benchmarks.end()) { 69 | if (filename.compare(itr->filename, Qt::CaseInsensitive) == 0) { 70 | if (itr->isSelected) { 71 | emit measurementInactive(itr->measurement); 72 | } 73 | itr = m_benchmarks.erase(itr); 74 | } else { 75 | ++itr; 76 | } 77 | } 78 | endResetModel(); 79 | } 80 | 81 | void BenchmarkModel::setMeasurementColor(int id, QString color) 82 | { 83 | for (auto rowIndex = 0; rowIndex < rowCount(); rowIndex++) { 84 | if (m_benchmarks[rowIndex].measurement.getId() == id) { 85 | setData(createIndex(rowIndex, columnCount()), 86 | QVariant::fromValue(color), Qt::BackgroundColorRole); 87 | break; 88 | } 89 | } 90 | } 91 | 92 | QVariant BenchmarkModel::headerData(int section, Qt::Orientation orientation, 93 | int role) const 94 | { 95 | if (role != Qt::DisplayRole) { 96 | return QVariant(); 97 | } 98 | 99 | if (orientation == Qt::Horizontal) { 100 | if (static_cast(section) != Columns::eInvalid) { 101 | return toString(static_cast(section)); 102 | } else { 103 | return QVariant(); 104 | } 105 | } else { 106 | return QVariant(); 107 | } 108 | } 109 | 110 | int BenchmarkModel::rowCount(const QModelIndex& parent) const 111 | { 112 | Q_UNUSED(parent) 113 | return m_benchmarks.size(); 114 | } 115 | 116 | int BenchmarkModel::columnCount(const QModelIndex& parent) const 117 | { 118 | Q_UNUSED(parent) 119 | return COLUMN_COUNT; 120 | } 121 | 122 | QVariant BenchmarkModel::data(const QModelIndex& index, int role) const 123 | { 124 | if (!index.isValid()) 125 | return QVariant(); 126 | 127 | if (index.row() >= m_benchmarks.size() || index.row() < 0) 128 | return QVariant(); 129 | 130 | if (role == Qt::DisplayRole) { 131 | BenchmarkViewUnit viewunit = m_benchmarks.at(index.row()); 132 | Columns col = static_cast(index.column()); 133 | switch (col) { 134 | case Columns::eStatus: 135 | return viewunit.isSelected; 136 | case Columns::eName: 137 | return viewunit.measurement.getName(); 138 | case Columns::eIterations: 139 | return viewunit.measurement.getIterations(); 140 | case Columns::eRealTime: 141 | return viewunit.measurement.getRealTime(); 142 | case Columns::eCpuTime: 143 | return viewunit.measurement.getCpuTime(); 144 | case Columns::eTimeUnit: 145 | return viewunit.measurement.getTimeUnit(); 146 | case Columns::eFilename: 147 | return QFileInfo(viewunit.filename).fileName(); 148 | default: 149 | return QVariant(); 150 | } 151 | } 152 | 153 | if (role == Qt::ToolTipRole) { 154 | BenchmarkViewUnit viewunit = m_benchmarks.at(index.row()); 155 | Columns col = static_cast(index.column()); 156 | switch (col) { 157 | case Columns::eFilename: 158 | return viewunit.filename; 159 | default: 160 | return QVariant(); 161 | } 162 | } 163 | 164 | if (role == Qt::BackgroundColorRole) { 165 | BenchmarkViewUnit viewunit = m_benchmarks.at(index.row()); 166 | if (viewunit.isSelected) { 167 | if (viewunit.hexColor == "#000000") { 168 | return QColor(Qt::lightGray); 169 | } else { 170 | return QColor(viewunit.hexColor); 171 | } 172 | } else { 173 | return QColor(Qt::white); 174 | } 175 | } 176 | 177 | return QVariant(); 178 | } 179 | 180 | Qt::ItemFlags BenchmarkModel::flags(const QModelIndex& index) const 181 | { 182 | if (!index.isValid()) 183 | return Qt::ItemIsEnabled; 184 | 185 | return QAbstractItemModel::flags(index); 186 | } 187 | 188 | bool BenchmarkModel::setData(const QModelIndex& index, const QVariant& value, int role) 189 | { 190 | if (index.isValid()) { 191 | auto row = index.row(); 192 | 193 | if (role == Qt::EditRole) { 194 | Columns col = static_cast(index.column()); 195 | if (col == Columns::eStatus 196 | && m_benchmarks[row].isSelected != value.toBool()) { 197 | m_benchmarks[row].isSelected = value.toBool(); 198 | emit dataChanged(createIndex(index.row(), 0), 199 | createIndex(index.row(), COLUMN_COUNT - 1)); 200 | 201 | if (m_benchmarks[row].isSelected) { 202 | emit measurementActive(m_benchmarks[row].measurement); 203 | } else { 204 | emit measurementInactive(m_benchmarks[row].measurement); 205 | } 206 | 207 | return true; 208 | } 209 | } else if (role == Qt::BackgroundColorRole) { 210 | m_benchmarks[row].hexColor = value.toString(); 211 | return true; 212 | } 213 | } 214 | 215 | return false; 216 | } 217 | 218 | void BenchmarkModel::initializeMetaData() 219 | { 220 | m_columnsVisibility[Columns::eStatus] = true; 221 | m_columnsVisibility[Columns::eName] = true; 222 | m_columnsVisibility[Columns::eIterations] = true; 223 | m_columnsVisibility[Columns::eRealTime] = true; 224 | m_columnsVisibility[Columns::eCpuTime] = true; 225 | m_columnsVisibility[Columns::eTimeUnit] = true; 226 | m_columnsVisibility[Columns::eFilename] = true; 227 | } 228 | 229 | bool BenchmarkModel::getColumnVisibility(Columns col) 230 | { 231 | return m_columnsVisibility[col]; 232 | } 233 | 234 | 235 | void BenchmarkModel::setColumnVisibility(Columns col, bool visibility) 236 | { 237 | m_columnsVisibility[col] = visibility; 238 | emit columnVisibilityChanged(col, visibility); 239 | } 240 | 241 | QString toString(BenchmarkModel::Columns col) 242 | { 243 | using Columns = BenchmarkModel::Columns; 244 | switch (col) 245 | { 246 | case Columns::eStatus: return QObject::tr("Status"); 247 | case Columns::eName: return QObject::tr("Name"); 248 | case Columns::eIterations: return QObject::tr("Iterations"); 249 | case Columns::eRealTime: return QObject::tr("Realtime"); 250 | case Columns::eCpuTime: return QObject::tr("Cpu Time"); 251 | case Columns::eTimeUnit: return QObject::tr("Timeunit"); 252 | case Columns::eFilename: return QObject::tr("Filename"); 253 | default: return QObject::tr("Unknown"); 254 | } 255 | } 256 | -------------------------------------------------------------------------------- /app/mainwindow.cpp: -------------------------------------------------------------------------------- 1 | /*========================================================================= 2 | 3 | Program: BenchmarkViewer 4 | 5 | Copyright (c) 2018 Asit Dhal 6 | All rights reserved. 7 | 8 | BenchmarkViewer is a free software; you can redistribute it and/or modify it. 9 | 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 12 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 13 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 14 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR 15 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 19 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | ========================================================================*/ 24 | 25 | #include "mainwindow.h" 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include "appconfig.h" 44 | #include "benchmarkdelegate.h" 45 | #include "benchmarkmodel.h" 46 | #include "benchmarkproxymodel.h" 47 | #include "benchmarkview.h" 48 | #include "csvparser.h" 49 | #include "globals.h" 50 | #include "helper.h" 51 | #include "chartviewwidget.h" 52 | 53 | MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) 54 | { 55 | init(); 56 | createActions(); 57 | createMenus(); 58 | createWidgets(); 59 | showMaximized(); 60 | 61 | m_mainWindowPresenter = new MainWindowPresenter(this, this); 62 | connectSignalsToSlots(); 63 | } 64 | 65 | MainWindow::~MainWindow() {} 66 | 67 | void MainWindow::init() 68 | { 69 | qRegisterMetaType("ParserType"); 70 | qRegisterMetaType("Benchmark"); 71 | 72 | new BenchmarkModel(this); 73 | new BenchmarkProxyModel(this); 74 | } 75 | 76 | QAction* MainWindow::getOpenFileAction() 77 | { 78 | return m_openFileAction; 79 | } 80 | 81 | QAction* MainWindow::getCloseAllFilesAction() 82 | { 83 | return m_closeAllFilesAction; 84 | } 85 | 86 | QAction* MainWindow::getExportChartAction() 87 | { 88 | return m_exportChart; 89 | } 90 | 91 | QAction* MainWindow::getExitAction() 92 | { 93 | return m_exitAction; 94 | } 95 | 96 | QAction* MainWindow::getAboutBenchmarkAppAction() 97 | { 98 | return m_aboutApp; 99 | } 100 | 101 | 102 | void MainWindow::createActions() 103 | { 104 | m_openFileAction = new QAction(tr("&Open File(s)"), this); 105 | m_openFileAction->setShortcuts(QKeySequence::Open); 106 | 107 | m_closeAllFilesAction = new QAction(tr("Close All files"), this); 108 | m_closeAllFilesAction->setStatusTip(tr("Close All Files ")); 109 | 110 | m_exportChart = new QAction(tr("Export Chart"), this); 111 | 112 | m_exitAction = new QAction(tr("E&xit"), this); 113 | m_exitAction->setStatusTip(tr("Exit")); 114 | m_exitAction->setShortcuts(QKeySequence::Quit); 115 | 116 | m_aboutApp = new QAction(tr("About BenchmarkViewer"), this); 117 | m_aboutApp->setStatusTip(tr("About BenchmarkViewer")); 118 | } 119 | 120 | void MainWindow::setRecentFileActions(QList recentFileActions) 121 | { 122 | qDeleteAll(m_openRecentFilesAction); 123 | m_openRecentFilesAction.clear(); 124 | 125 | m_openRecentFilesAction.append(recentFileActions); 126 | 127 | foreach (QAction* recentFileAction, m_openRecentFilesAction) 128 | { 129 | m_recentFileMenu->addAction(recentFileAction); 130 | } 131 | } 132 | 133 | void MainWindow::setCloseFileActions(QList closeFileActions) 134 | { 135 | qDeleteAll(m_closeFileActions); 136 | m_closeFileActions.clear(); 137 | 138 | m_closeFileActions.append(closeFileActions); 139 | 140 | foreach (QAction* closeFileAction, m_closeFileActions) 141 | { 142 | m_closeFileMenu->addAction(closeFileAction); 143 | } 144 | } 145 | 146 | void MainWindow::createMenus() 147 | { 148 | m_fileMenu = menuBar()->addMenu(tr("&File")); 149 | m_fileMenu->addAction(m_openFileAction); 150 | m_recentFileMenu = m_fileMenu->addMenu(tr("Recent Files")); 151 | m_closeFileMenu = m_fileMenu->addMenu(tr("Close File(s)")); 152 | 153 | m_fileMenu->addAction(m_closeAllFilesAction); 154 | m_fileMenu->addAction(m_exportChart); 155 | m_fileMenu->addAction(m_exitAction); 156 | 157 | m_helpMenu = menuBar()->addMenu(tr("&Help")); 158 | m_helpMenu->addAction(m_aboutApp); 159 | } 160 | 161 | void MainWindow::onSelectionChanged(const QItemSelection& selected, 162 | const QItemSelection& deselected) 163 | { 164 | Q_UNUSED(selected); 165 | Q_UNUSED(deselected); 166 | } 167 | 168 | void MainWindow::createWidgets() 169 | { 170 | QWidget* benckmarkSelector = new QWidget(this); 171 | m_benchmarkNameFilter = new QLineEdit(this); 172 | m_benchmarkNameFilter->setPlaceholderText(tr("Filter")); 173 | m_benchmarkView = new BenchmarkView(this); 174 | m_benchmarkDelegate = new BenchmarkDelegate(this); 175 | 176 | BenchmarkProxyModel::getInstance()->setSourceModel(BenchmarkModel::getInstance()); 177 | m_benchmarkView->seBenchmarkColumnAttributes(BenchmarkModel::getInstance()); // strongly coupled 178 | m_benchmarkView->setModel(BenchmarkProxyModel::getInstance()); 179 | m_benchmarkView->setItemDelegate(m_benchmarkDelegate); 180 | m_benchmarkView->setEditTriggers(QAbstractItemView::CurrentChanged); 181 | m_benchmarkView->setSortingEnabled(true); 182 | m_benchmarkView->setSelectionBehavior(QAbstractItemView::SelectRows); 183 | m_benchmarkView->sortByColumn(1, Qt::DescendingOrder); 184 | 185 | QHBoxLayout* benchmarkFilterLayout = new QHBoxLayout; 186 | benchmarkFilterLayout->addWidget(m_benchmarkNameFilter); 187 | QVBoxLayout* benchmarkLayout = new QVBoxLayout; 188 | benchmarkLayout->addLayout(benchmarkFilterLayout); 189 | benchmarkLayout->addWidget(m_benchmarkView); 190 | benckmarkSelector->setLayout(benchmarkLayout); 191 | 192 | new ChartViewWidget(this); 193 | 194 | QSplitter* splitter = new QSplitter(this); 195 | splitter->addWidget(benckmarkSelector); 196 | splitter->addWidget(ChartViewWidget::getInstance()); 197 | splitter->setStretchFactor(0, 1); 198 | splitter->setStretchFactor(1, 2); 199 | setCentralWidget(splitter); 200 | 201 | m_selectionModel = new QItemSelectionModel(BenchmarkProxyModel::getInstance()); 202 | m_benchmarkView->setSelectionModel(m_selectionModel); 203 | } 204 | 205 | void MainWindow::connectSignalsToSlots() 206 | { 207 | connect(m_benchmarkNameFilter, SIGNAL(textChanged(QString)), this, SLOT(onBenchmarkFilter(QString))); 208 | 209 | connect(BenchmarkModel::getInstance(), &BenchmarkModel::measurementActive, 210 | ChartViewWidget::getInstance(), &ChartViewWidget::onAddMeasurement); 211 | connect(BenchmarkModel::getInstance(), &BenchmarkModel::measurementInactive, 212 | ChartViewWidget::getInstance(), &ChartViewWidget::onRemoveMeasurement); 213 | 214 | connect(m_selectionModel, &QItemSelectionModel::selectionChanged, this, &MainWindow::onSelectionChanged); 215 | connect(m_benchmarkView, &BenchmarkView::select, this, &MainWindow::onPlotSelection); 216 | connect(m_benchmarkView, &BenchmarkView::selectAllRows, this, &MainWindow::onPlotAllRows); 217 | connect(m_benchmarkView, &BenchmarkView::clearSelection, this, &MainWindow::onClearSelection); 218 | connect(m_benchmarkView, &BenchmarkView::clearAllRows, this, &MainWindow::onClearAllRows); 219 | 220 | connect(ChartViewWidget::getInstance(), &ChartViewWidget::measurementColorChanged, 221 | [&](int id, QString color) { 222 | BenchmarkModel::getInstance()->setMeasurementColor(id, color); 223 | }); 224 | } 225 | 226 | 227 | void MainWindow::onBenchmarkFilter(QString filterText) 228 | { 229 | QRegExp regExp(filterText, Qt::CaseInsensitive, QRegExp::Wildcard); 230 | BenchmarkProxyModel::getInstance()->setFilterRegExp(regExp); 231 | } 232 | 233 | void MainWindow::onPlotSelection() 234 | { 235 | QItemSelectionModel* select = m_benchmarkView->selectionModel(); 236 | if (select->hasSelection()) 237 | { 238 | foreach (QModelIndex idx, select->selectedRows()) 239 | { 240 | auto srcIdx = BenchmarkProxyModel::getInstance()->mapToSource(idx); 241 | BenchmarkModel::getInstance()->setData(srcIdx, true); 242 | } 243 | } 244 | } 245 | 246 | void MainWindow::onPlotAllRows() 247 | { 248 | m_benchmarkView->selectAll(); 249 | QItemSelectionModel* select = m_benchmarkView->selectionModel(); 250 | if (select->hasSelection()) 251 | { 252 | foreach (QModelIndex idx, select->selectedRows()) 253 | { 254 | auto srcIdx = BenchmarkProxyModel::getInstance()->mapToSource(idx); 255 | BenchmarkModel::getInstance()->setData(srcIdx, true); 256 | } 257 | } 258 | } 259 | 260 | void MainWindow::onClearSelection() 261 | { 262 | QItemSelectionModel* select = m_benchmarkView->selectionModel(); 263 | if (select->hasSelection()) 264 | { 265 | foreach (QModelIndex idx, select->selectedRows()) 266 | { 267 | auto srcIdx = BenchmarkProxyModel::getInstance()->mapToSource(idx); 268 | BenchmarkModel::getInstance()->setData(srcIdx, false); 269 | } 270 | } 271 | } 272 | 273 | void MainWindow::onClearAllRows() 274 | { 275 | m_benchmarkView->selectAll(); 276 | QItemSelectionModel* select = m_benchmarkView->selectionModel(); 277 | if (select->hasSelection()) 278 | { 279 | foreach (QModelIndex idx, select->selectedRows()) 280 | { 281 | auto srcIdx = BenchmarkProxyModel::getInstance()->mapToSource(idx); 282 | BenchmarkModel::getInstance()->setData(srcIdx, false); 283 | } 284 | } 285 | } 286 | --------------------------------------------------------------------------------