// Copyright (c) 2020 The Orbit Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "SessionsDataView.h" #include <OrbitBase/Logging.h> #include <OrbitBase/SafeStrerror.h> #include <cstdio> #include "App.h" #include "Callstack.h" #include "Capture.h" #include "Core.h" #include "ModulesDataView.h" #include "OrbitSession.h" #include "OrbitType.h" #include "Pdb.h" #include "absl/strings/str_format.h" //----------------------------------------------------------------------------- PresetsDataView::PresetsDataView() : DataView(DataViewType::PRESETS) {} //----------------------------------------------------------------------------- const std::vector<DataView::Column>& PresetsDataView::GetColumns() { static const std::vector<Column> columns = [] { std::vector<Column> columns; columns.resize(COLUMN_NUM); columns[COLUMN_SESSION_NAME] = {"Preset", .49f, SortingOrder::Ascending}; columns[COLUMN_PROCESS_NAME] = {"Process", .49f, SortingOrder::Ascending}; return columns; }(); return columns; } //----------------------------------------------------------------------------- std::string PresetsDataView::GetValue(int row, int col) { const std::shared_ptr<Preset>& preset = GetPreset(row); switch (col) { case COLUMN_SESSION_NAME: return Path::GetFileName(preset->m_FileName); case COLUMN_PROCESS_NAME: return Path::GetFileName(preset->m_ProcessFullPath); default: return ""; } } //----------------------------------------------------------------------------- std::string PresetsDataView::GetToolTip(int a_Row, int /*a_Column*/) { const Preset& preset = *GetPreset(a_Row); return preset.m_FileName; } //----------------------------------------------------------------------------- #define ORBIT_PRESET_SORT(Member) \ [&](int a, int b) { \ return OrbitUtils::Compare(presets_[a]->Member, presets_[b]->Member, \ ascending); \ } //----------------------------------------------------------------------------- void PresetsDataView::DoSort() { bool ascending = m_SortingOrders[m_SortingColumn] == SortingOrder::Ascending; std::function<bool(int a, int b)> sorter = nullptr; switch (m_SortingColumn) { case COLUMN_SESSION_NAME: sorter = ORBIT_PRESET_SORT(m_FileName); break; case COLUMN_PROCESS_NAME: sorter = ORBIT_PRESET_SORT(m_ProcessFullPath); break; default: break; } if (sorter) { std::stable_sort(m_Indices.begin(), m_Indices.end(), sorter); } } //----------------------------------------------------------------------------- const std::string PresetsDataView::MENU_ACTION_LOAD = "Load Preset"; const std::string PresetsDataView::MENU_ACTION_DELETE = "Delete Preset"; //----------------------------------------------------------------------------- std::vector<std::string> PresetsDataView::GetContextMenu( int a_ClickedIndex, const std::vector<int>& a_SelectedIndices) { std::vector<std::string> menu; // Note that the UI already enforces a single selection. if (a_SelectedIndices.size() == 1) { Append(menu, {MENU_ACTION_LOAD, MENU_ACTION_DELETE}); } Append(menu, DataView::GetContextMenu(a_ClickedIndex, a_SelectedIndices)); return menu; } //----------------------------------------------------------------------------- void PresetsDataView::OnContextMenu(const std::string& a_Action, int a_MenuIndex, const std::vector<int>& a_ItemIndices) { if (a_Action == MENU_ACTION_LOAD) { if (a_ItemIndices.size() != 1) { return; } const std::shared_ptr<Preset>& preset = GetPreset(a_ItemIndices[0]); GOrbitApp->LoadPreset(preset); } else if (a_Action == MENU_ACTION_DELETE) { if (a_ItemIndices.size() != 1) { return; } int row = a_ItemIndices[0]; const std::shared_ptr<Preset>& preset = GetPreset(row); const std::string& filename = preset->m_FileName; int ret = remove(filename.c_str()); if (ret == 0) { presets_.erase(presets_.begin() + m_Indices[row]); OnDataChanged(); } else { ERROR("Deleting preset \"%s\": %s", filename, SafeStrerror(errno)); GOrbitApp->SendErrorToUi( "Error deleting preset", absl::StrFormat("Could not delete preset \"%s\".", filename)); } } else { DataView::OnContextMenu(a_Action, a_MenuIndex, a_ItemIndices); } } //----------------------------------------------------------------------------- void PresetsDataView::DoFilter() { std::vector<uint32_t> indices; std::vector<std::string> tokens = absl::StrSplit(ToLower(m_Filter), ' '); for (size_t i = 0; i < presets_.size(); ++i) { const Preset& preset = *presets_[i]; std::string name = Path::GetFileName(ToLower(preset.m_FileName)); std::string path = ToLower(preset.m_ProcessFullPath); bool match = true; for (std::string& filterToken : tokens) { if (!(name.find(filterToken) != std::string::npos || path.find(filterToken) != std::string::npos)) { match = false; break; } } if (match) { indices.push_back(i); } } m_Indices = indices; OnSort(m_SortingColumn, {}); } //----------------------------------------------------------------------------- void PresetsDataView::OnDataChanged() { m_Indices.resize(presets_.size()); for (size_t i = 0; i < presets_.size(); ++i) { m_Indices[i] = i; } DataView::OnDataChanged(); } //----------------------------------------------------------------------------- void PresetsDataView::SetPresets( const std::vector<std::shared_ptr<Preset> >& presets) { presets_ = presets; OnDataChanged(); } //----------------------------------------------------------------------------- const std::shared_ptr<Preset>& PresetsDataView::GetPreset( unsigned int a_Row) const { return presets_[m_Indices[a_Row]]; }