Files
test/source/blender/editors/interface/interface_string_search.cc
Brecht Van Lommel e0ff7731e0 Core: make BKE_appdir functions thread safe, using optional<string>
The static variables can cause the wrong path to be used, for example
when asset indexing in a thread affects loading toolbar icons.

Fix #117416: toolbar icon randomly missing

Pull Request: https://projects.blender.org/blender/blender/pulls/117419
2024-01-23 18:38:15 +01:00

115 lines
2.8 KiB
C++

/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include <sstream>
#include "BKE_appdir.hh"
#include "DNA_userdef_types.h"
#include "UI_string_search.hh"
#include "BLI_fileops.hh"
#include "BLI_map.hh"
#include "BLI_path_util.h"
namespace blender::ui::string_search {
using blender::string_search::RecentCache;
struct RecentCacheStorage {
/**
* Is incremented every time a search item has been selected. This is used to keep track of the
* order of recent searches.
*/
int logical_clock = 0;
RecentCache cache;
};
static RecentCacheStorage &get_recent_cache_storage()
{
BLI_assert((U.flag & USER_FLAG_RECENT_SEARCHES_DISABLE) == 0);
static RecentCacheStorage storage;
return storage;
}
void add_recent_search(const StringRef chosen_str)
{
RecentCacheStorage &storage = get_recent_cache_storage();
storage.cache.logical_time_by_str.add_overwrite(chosen_str, storage.logical_clock);
storage.logical_clock++;
}
const RecentCache *get_recent_cache_or_null()
{
if (U.flag & USER_FLAG_RECENT_SEARCHES_DISABLE) {
return nullptr;
}
RecentCacheStorage &storage = get_recent_cache_storage();
return &storage.cache;
}
static std::optional<std::string> get_recent_searches_file_path()
{
const std::optional<std::string> user_config_dir = BKE_appdir_folder_id_create(
BLENDER_USER_CONFIG, nullptr);
if (!user_config_dir.has_value()) {
return std::nullopt;
}
char filepath[FILE_MAX];
BLI_path_join(
filepath, sizeof(filepath), user_config_dir->c_str(), BLENDER_RECENT_SEARCHES_FILE);
return std::string(filepath);
}
void write_recent_searches_file()
{
if (U.flag & USER_FLAG_RECENT_SEARCHES_DISABLE) {
return;
}
const std::optional<std::string> path = get_recent_searches_file_path();
if (!path) {
return;
}
const RecentCacheStorage &storage = get_recent_cache_storage();
Vector<std::pair<int, std::string>> values;
for (const auto item : storage.cache.logical_time_by_str.items()) {
values.append({item.value, item.key});
}
std::sort(values.begin(), values.end());
fstream file(*path, std::ios::out);
for (const auto &item : values) {
file.write(item.second.data(), item.second.size());
file.write("\n", 1);
}
}
void read_recent_searches_file()
{
if (U.flag & USER_FLAG_RECENT_SEARCHES_DISABLE) {
return;
}
const std::optional<std::string> path = get_recent_searches_file_path();
if (!path) {
return;
}
RecentCacheStorage &storage = get_recent_cache_storage();
storage.logical_clock = 0;
storage.cache.logical_time_by_str.clear();
fstream file(*path);
std::string line;
while (std::getline(file, line)) {
storage.cache.logical_time_by_str.add_overwrite(line, storage.logical_clock);
storage.logical_clock++;
}
}
} // namespace blender::ui::string_search