UI: show recently selected items at the top of searches #110828
|
@ -216,6 +216,11 @@ class USERPREF_PT_interface_display(InterfacePanel, CenterAlignMixIn, Panel):
|
|||
sub.active = view.show_tooltips
|
||||
sub.prop(view, "show_tooltips_python")
|
||||
|
||||
col.separator()
|
||||
|
||||
col = layout.column(heading="Search", align=True)
|
||||
col.prop(prefs, "use_recent_searches", text="Sort by Most Recent")
|
||||
|
||||
|
||||
class USERPREF_PT_interface_text(InterfacePanel, CenterAlignMixIn, Panel):
|
||||
bl_label = "Text Rendering"
|
||||
|
|
|
@ -188,6 +188,7 @@ enum {
|
|||
#define BLENDER_QUIT_FILE "quit.blend"
|
||||
#define BLENDER_BOOKMARK_FILE "bookmarks.txt"
|
||||
#define BLENDER_HISTORY_FILE "recent-files.txt"
|
||||
#define BLENDER_RECENT_SEARCHES_FILE "recent-searches.txt"
|
||||
#define BLENDER_PLATFORM_SUPPORT_FILE "platform_support.txt"
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "BLI_linear_allocator.hh"
|
||||
#include "BLI_map.hh"
|
||||
#include "BLI_span.hh"
|
||||
#include "BLI_string_ref.hh"
|
||||
#include "BLI_vector.hh"
|
||||
|
@ -12,10 +13,23 @@
|
|||
namespace blender::string_search {
|
||||
|
||||
struct SearchItem {
|
||||
void *user_data;
|
||||
Span<blender::StringRef> normalized_words;
|
||||
int length;
|
||||
void *user_data;
|
||||
int weight;
|
||||
/**
|
||||
JacquesLucke marked this conversation as resolved
Outdated
|
||||
* This is a logical time stamp, i.e. the greater it is, the more recent the item was used. The
|
||||
* number is not based on an actual clock.
|
||||
*/
|
||||
int recent_time;
|
||||
};
|
||||
|
||||
JacquesLucke marked this conversation as resolved
Outdated
Hans Goudey
commented
`the more recent` -> `the more recently`
|
||||
struct RecentCache {
|
||||
/**
|
||||
* Stores a logical time stamp for each previously choosen search item. The higher the time
|
||||
* stamp, the more recently the item has been selected.
|
||||
*/
|
||||
Map<std::string, int> logical_time_by_str;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -25,6 +39,7 @@ class StringSearchBase {
|
|||
protected:
|
||||
LinearAllocator<> allocator_;
|
||||
Vector<SearchItem> items_;
|
||||
const RecentCache *recent_cache_ = nullptr;
|
||||
|
||||
protected:
|
||||
void add_impl(StringRef str, void *user_data, int weight);
|
||||
|
@ -43,6 +58,11 @@ class StringSearchBase {
|
|||
*/
|
||||
template<typename T> class StringSearch : private StringSearchBase {
|
||||
public:
|
||||
StringSearch(const RecentCache *recent_cache = nullptr)
|
||||
{
|
||||
this->recent_cache_ = recent_cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new possible result to the search.
|
||||
*
|
||||
|
|
|
@ -398,8 +398,14 @@ void StringSearchBase::add_impl(const StringRef str, void *user_data, const int
|
|||
{
|
||||
Vector<StringRef, 64> words;
|
||||
string_search::extract_normalized_words(str, allocator_, words);
|
||||
items_.append(
|
||||
{allocator_.construct_array_copy(words.as_span()), int(str.size()), user_data, weight});
|
||||
const int recent_time = recent_cache_ ?
|
||||
recent_cache_->logical_time_by_str.lookup_default(str, -1) :
|
||||
-1;
|
||||
items_.append({user_data,
|
||||
allocator_.construct_array_copy(words.as_span()),
|
||||
int(str.size()),
|
||||
weight,
|
||||
recent_time});
|
||||
}
|
||||
|
||||
Vector<void *> StringSearchBase::query_impl(const StringRef query) const
|
||||
|
@ -429,17 +435,23 @@ Vector<void *> StringSearchBase::query_impl(const StringRef query) const
|
|||
Vector<int> sorted_result_indices;
|
||||
for (const int score : found_scores) {
|
||||
MutableSpan<int> indices = result_indices_by_score.lookup(score);
|
||||
if (score == found_scores[0] && !query.is_empty()) {
|
||||
/* Sort items with best score by length. Shorter items are more likely the ones you are
|
||||
* looking for. This also ensures that exact matches will be at the top, even if the query is
|
||||
* a sub-string of another item. */
|
||||
std::sort(indices.begin(), indices.end(), [&](int a, int b) {
|
||||
return items_[a].length < items_[b].length;
|
||||
});
|
||||
/* Prefer items with larger weights. Use `stable_sort` so that if the weights are the same,
|
||||
* the order won't be changed. */
|
||||
if (score == found_scores[0]) {
|
||||
if (!query.is_empty()) {
|
||||
/* Sort items with best score by length. Shorter items are more likely the ones you are
|
||||
* looking for. This also ensures that exact matches will be at the top, even if the query
|
||||
* is a sub-string of another item. */
|
||||
std::sort(indices.begin(), indices.end(), [&](int a, int b) {
|
||||
return items_[a].length < items_[b].length;
|
||||
});
|
||||
/* Prefer items with larger weights. Use `stable_sort` so that if the weights are the same,
|
||||
* the order won't be changed. */
|
||||
std::stable_sort(indices.begin(), indices.end(), [&](int a, int b) {
|
||||
return items_[a].weight > items_[b].weight;
|
||||
});
|
||||
}
|
||||
/* Prefer items that have been selected recently. */
|
||||
std::stable_sort(indices.begin(), indices.end(), [&](int a, int b) {
|
||||
return items_[a].weight > items_[b].weight;
|
||||
return items_[a].recent_time > items_[b].recent_time;
|
||||
});
|
||||
}
|
||||
sorted_result_indices.extend(indices);
|
||||
|
|
|
@ -461,7 +461,7 @@ void blo_do_versions_userdef(UserDef *userdef)
|
|||
|
||||
if (!USER_VERSION_ATLEAST(278, 6)) {
|
||||
/* Clear preference flags for re-use. */
|
||||
userdef->flag &= ~(USER_FLAG_NUMINPUT_ADVANCED | USER_FLAG_UNUSED_2 | USER_FLAG_UNUSED_3 |
|
||||
userdef->flag &= ~(USER_FLAG_NUMINPUT_ADVANCED | (1 << 2) | USER_FLAG_UNUSED_3 |
|
||||
USER_FLAG_UNUSED_6 | USER_FLAG_UNUSED_7 | USER_FLAG_UNUSED_9 |
|
||||
USER_DEVELOPER_UI);
|
||||
userdef->uiflag &= ~(USER_HEADER_BOTTOM);
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BLI_string_search.hh"
|
||||
|
||||
namespace blender::ui::string_search {
|
||||
|
||||
/**
|
||||
* Remember the string that the user chose. This allows us to put it higher up in the search items
|
||||
* later on.
|
||||
*/
|
||||
void add_recent_search(StringRef chosen_str);
|
||||
|
||||
/**
|
||||
* Depending on the user preferences, either outputs the recent cache or null.
|
||||
*/
|
||||
const blender::string_search::RecentCache *get_recent_cache_or_null();
|
||||
|
||||
void write_recent_searches_file();
|
||||
void read_recent_searches_file();
|
||||
|
||||
/**
|
||||
* Wrapper for the lower level #StringSearch in blenlib that takes recent searches into account
|
||||
* automatically.
|
||||
*/
|
||||
template<typename T> class StringSearch : public blender::string_search::StringSearch<T> {
|
||||
public:
|
||||
StringSearch() : blender::string_search::StringSearch<T>(get_recent_cache_or_null()) {}
|
||||
};
|
||||
|
||||
} // namespace blender::ui::string_search
|
|
@ -64,6 +64,7 @@ set(SRC
|
|||
interface_region_search.cc
|
||||
interface_region_tooltip.cc
|
||||
interface_regions.cc
|
||||
interface_string_search.cc
|
||||
interface_style.cc
|
||||
interface_template_asset_view.cc
|
||||
interface_template_attribute_search.cc
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#include "BLI_listbase.h"
|
||||
#include "BLI_rect.h"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_string_search.hh"
|
||||
#include "BLI_string_utf8.h"
|
||||
#include "BLI_vector.hh"
|
||||
|
||||
|
@ -52,6 +51,7 @@
|
|||
|
||||
#include "UI_interface.hh"
|
||||
#include "UI_interface_icons.hh"
|
||||
#include "UI_string_search.hh"
|
||||
#include "UI_view2d.hh"
|
||||
|
||||
#include "IMB_imbuf.h"
|
||||
|
@ -3444,6 +3444,7 @@ static void ui_but_free_type_specific(uiBut *but)
|
|||
switch (but->type) {
|
||||
case UI_BTYPE_SEARCH_MENU: {
|
||||
uiButSearch *search_but = (uiButSearch *)but;
|
||||
MEM_SAFE_FREE(search_but->item_active_str);
|
||||
|
||||
if (search_but->arg_free_fn) {
|
||||
search_but->arg_free_fn(search_but->arg);
|
||||
|
@ -6400,7 +6401,7 @@ static void operator_enum_search_update_fn(
|
|||
const EnumPropertyItem *all_items;
|
||||
RNA_property_enum_items_gettexted((bContext *)C, ptr, prop, &all_items, nullptr, &do_free);
|
||||
|
||||
blender::string_search::StringSearch<const EnumPropertyItem> search;
|
||||
blender::ui::string_search::StringSearch<const EnumPropertyItem> search;
|
||||
|
||||
for (const EnumPropertyItem *item = all_items; item->identifier; item++) {
|
||||
search.add(item->name, item);
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
#include "ED_undo.hh"
|
||||
|
||||
#include "UI_interface.hh"
|
||||
#include "UI_string_search.hh"
|
||||
#include "UI_view2d.hh"
|
||||
|
||||
#include "BLF_api.h"
|
||||
|
@ -1252,6 +1253,8 @@ static void ui_apply_but_TEX(bContext *C, uiBut *but, uiHandleButtonData *data)
|
|||
if ((but->func_arg2 == nullptr) && (but->type == UI_BTYPE_SEARCH_MENU)) {
|
||||
uiButSearch *search_but = (uiButSearch *)but;
|
||||
but->func_arg2 = search_but->item_active;
|
||||
|
||||
blender::ui::string_search::add_recent_search(search_but->item_active_str);
|
||||
}
|
||||
|
||||
ui_apply_but_func(C, but);
|
||||
|
|
|
@ -329,6 +329,7 @@ struct uiButSearch : public uiBut {
|
|||
uiButSearchListenFn listen_fn = nullptr;
|
||||
|
||||
void *item_active = nullptr;
|
||||
char *item_active_str;
|
||||
|
||||
void *arg = nullptr;
|
||||
uiFreeArgFunc arg_free_fn = nullptr;
|
||||
|
|
|
@ -301,6 +301,8 @@ bool ui_searchbox_apply(uiBut *but, ARegion *region)
|
|||
}
|
||||
|
||||
search_but->item_active = data->items.pointers[data->active];
|
||||
MEM_SAFE_FREE(search_but->item_active_str);
|
||||
search_but->item_active_str = BLI_strdup(data->items.names[data->active]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "BKE_appdir.h"
|
||||
|
||||
#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()
|
||||
{
|
||||
static RecentCacheStorage storage;
|
||||
return storage;
|
||||
}
|
||||
JacquesLucke marked this conversation as resolved
Outdated
Hans Goudey
commented
Spelling: Spelling: `choosen` -> `chosen`. Same in the header.
|
||||
|
||||
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 char *user_config_dir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, nullptr);
|
||||
if (!user_config_dir) {
|
||||
return std::nullopt;
|
||||
}
|
||||
char filepath[FILE_MAX];
|
||||
BLI_path_join(filepath, sizeof(filepath), user_config_dir, BLENDER_RECENT_SEARCHES_FILE);
|
||||
return std::string(filepath);
|
||||
}
|
||||
|
||||
void write_recent_searches_file()
|
||||
{
|
||||
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()
|
||||
{
|
||||
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
|
|
@ -7,7 +7,6 @@
|
|||
*/
|
||||
|
||||
#include "BLI_string_ref.hh"
|
||||
#include "BLI_string_search.hh"
|
||||
|
||||
#include "DNA_customdata_types.h"
|
||||
|
||||
|
@ -22,6 +21,7 @@
|
|||
|
||||
#include "UI_interface.hh"
|
||||
#include "UI_resources.hh"
|
||||
#include "UI_string_search.hh"
|
||||
|
||||
using blender::nodes::geo_eval_log::GeometryAttributeInfo;
|
||||
|
||||
|
@ -91,7 +91,7 @@ void attribute_search_add_items(StringRefNull str,
|
|||
* so the items are in the same order they will appear in while searching. */
|
||||
const char *string = is_first ? "" : str.c_str();
|
||||
|
||||
string_search::StringSearch<const GeometryAttributeInfo> search;
|
||||
ui::string_search::StringSearch<const GeometryAttributeInfo> search;
|
||||
for (const GeometryAttributeInfo *item : infos) {
|
||||
if (!bke::allow_procedural_attribute_access(item->name)) {
|
||||
continue;
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
#include "BLI_set.hh"
|
||||
#include "BLI_stack.hh"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_string_search.hh"
|
||||
#include "BLI_string_utils.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
|
@ -50,6 +49,7 @@
|
|||
#include "WM_types.hh"
|
||||
|
||||
#include "UI_interface.hh"
|
||||
#include "UI_string_search.hh"
|
||||
#include "interface_intern.hh"
|
||||
|
||||
/* For key-map item access. */
|
||||
|
@ -1002,7 +1002,7 @@ static void menu_search_update_fn(const bContext * /*C*/,
|
|||
{
|
||||
MenuSearch_Data *data = (MenuSearch_Data *)arg;
|
||||
|
||||
blender::string_search::StringSearch<MenuSearch_Item> search;
|
||||
blender::ui::string_search::StringSearch<MenuSearch_Item> search;
|
||||
|
||||
LISTBASE_FOREACH (MenuSearch_Item *, item, &data->items) {
|
||||
search.add(item->drawwstr_full, item);
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
#include "BLI_path_util.h"
|
||||
#include "BLI_rect.h"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_string_search.hh"
|
||||
#include "BLI_string_utils.h"
|
||||
#include "BLI_timecode.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
@ -90,6 +89,7 @@
|
|||
|
||||
#include "UI_interface.hh"
|
||||
#include "UI_interface_icons.hh"
|
||||
#include "UI_string_search.hh"
|
||||
#include "UI_view2d.hh"
|
||||
#include "interface_intern.hh"
|
||||
|
||||
|
@ -423,7 +423,7 @@ static void id_search_cb(const bContext *C,
|
|||
ListBase *lb = template_ui->idlb;
|
||||
const int flag = RNA_property_flag(template_ui->prop);
|
||||
|
||||
blender::string_search::StringSearch<ID> search;
|
||||
blender::ui::string_search::StringSearch<ID> search;
|
||||
|
||||
/* ID listbase */
|
||||
LISTBASE_FOREACH (ID *, id, lb) {
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_string_search.hh"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BLT_translation.h"
|
||||
|
@ -37,6 +36,7 @@
|
|||
#include "UI_interface.hh"
|
||||
#include "UI_interface_icons.hh"
|
||||
#include "UI_resources.hh"
|
||||
#include "UI_string_search.hh"
|
||||
#include "UI_view2d.hh"
|
||||
|
||||
#include "WM_api.hh"
|
||||
|
@ -519,7 +519,7 @@ void ui_rna_collection_search_update_fn(
|
|||
char *name;
|
||||
bool has_id_icon = false;
|
||||
|
||||
blender::string_search::StringSearch<CollItemSearch> search;
|
||||
blender::ui::string_search::StringSearch<CollItemSearch> search;
|
||||
|
||||
if (data->search_prop != nullptr) {
|
||||
/* build a temporary list of relevant items first */
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
#include "AS_asset_representation.hh"
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_string_search.hh"
|
||||
|
||||
#include "DNA_space_types.h"
|
||||
|
||||
|
@ -17,6 +16,8 @@
|
|||
#include "BKE_node_tree_update.h"
|
||||
#include "BKE_screen.h"
|
||||
|
||||
#include "UI_string_search.hh"
|
||||
|
||||
#include "NOD_socket.hh"
|
||||
#include "NOD_socket_search_link.hh"
|
||||
|
||||
|
@ -359,7 +360,7 @@ static void link_drag_search_update_fn(
|
|||
storage.update_items_tag = false;
|
||||
}
|
||||
|
||||
string_search::StringSearch<SocketLinkOperation> search;
|
||||
ui::string_search::StringSearch<SocketLinkOperation> search;
|
||||
|
||||
for (SocketLinkOperation &op : storage.search_link_ops) {
|
||||
search.add(op.name, &op, op.weight);
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#include "BLI_set.hh"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_string_ref.hh"
|
||||
#include "BLI_string_search.hh"
|
||||
|
||||
#include "DNA_modifier_types.h"
|
||||
#include "DNA_node_types.h"
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
#include "BLI_listbase.h"
|
||||
#include "BLI_rect.h"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_string_search.hh"
|
||||
#include "BLI_string_utf8.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
|
@ -41,6 +40,7 @@
|
|||
|
||||
#include "UI_interface.hh"
|
||||
#include "UI_resources.hh"
|
||||
#include "UI_string_search.hh"
|
||||
#include "UI_view2d.hh"
|
||||
|
||||
#include "DEG_depsgraph.hh"
|
||||
|
@ -1346,7 +1346,7 @@ static void node_find_update_fn(const bContext *C,
|
|||
{
|
||||
SpaceNode *snode = CTX_wm_space_node(C);
|
||||
|
||||
string_search::StringSearch<bNode> search;
|
||||
ui::string_search::StringSearch<bNode> search;
|
||||
|
||||
for (bNode *node : snode->edittree->all_nodes()) {
|
||||
char name[256];
|
||||
|
|
|
@ -104,6 +104,7 @@ set(SRC
|
|||
../include/UI_interface_c.hh
|
||||
../include/UI_interface_icons.hh
|
||||
../include/UI_resources.hh
|
||||
../include/UI_string_search.hh
|
||||
../include/UI_tree_view.hh
|
||||
../include/UI_view2d.hh
|
||||
)
|
||||
|
|
|
@ -1084,9 +1084,9 @@ typedef enum eUserPref_SpaceData_Flag {
|
|||
typedef enum eUserPref_Flag {
|
||||
USER_AUTOSAVE = (1 << 0),
|
||||
USER_FLAG_NUMINPUT_ADVANCED = (1 << 1),
|
||||
USER_FLAG_UNUSED_2 = (1 << 2), /* cleared */
|
||||
USER_FLAG_UNUSED_3 = (1 << 3), /* cleared */
|
||||
USER_FLAG_UNUSED_4 = (1 << 4), /* cleared */
|
||||
USER_FLAG_RECENT_SEARCHES_DISABLE = (1 << 2), /* cleared */
|
||||
USER_FLAG_UNUSED_3 = (1 << 3), /* cleared */
|
||||
USER_FLAG_UNUSED_4 = (1 << 4), /* cleared */
|
||||
USER_TRACKBALL = (1 << 5),
|
||||
USER_FLAG_UNUSED_6 = (1 << 6), /* cleared */
|
||||
USER_FLAG_UNUSED_7 = (1 << 7), /* cleared */
|
||||
|
|
|
@ -7143,6 +7143,10 @@ void RNA_def_userdef(BlenderRNA *brna)
|
|||
RNA_def_property_ui_text(prop, "Auto-Execution Paths", "");
|
||||
rna_def_userdef_autoexec_path_collection(brna, prop);
|
||||
|
||||
prop = RNA_def_property(srna, "use_recent_searches", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_negative_sdna(prop, nullptr, "flag", USER_FLAG_RECENT_SEARCHES_DISABLE);
|
||||
RNA_def_property_ui_text(prop, "Recent Searches", "Sort the recently searched items at the top");
|
||||
|
||||
/* nested structs */
|
||||
prop = RNA_def_property(srna, "view", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_flag(prop, PROP_NEVER_NULL);
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include "BLI_path_util.h"
|
||||
#include "BLI_set.hh"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_string_search.hh"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "DNA_collection_types.h"
|
||||
|
|
|
@ -111,8 +111,10 @@
|
|||
|
||||
#include "BLF_api.h"
|
||||
#include "BLT_lang.h"
|
||||
|
||||
#include "UI_interface.hh"
|
||||
#include "UI_resources.hh"
|
||||
#include "UI_string_search.hh"
|
||||
|
||||
#include "GPU_context.h"
|
||||
#include "GPU_init_exit.h"
|
||||
|
@ -357,6 +359,7 @@ void WM_init(bContext *C, int argc, const char **argv)
|
|||
ED_render_clear_mtex_copybuf();
|
||||
|
||||
wm_history_file_read();
|
||||
blender::ui::string_search::read_recent_searches_file();
|
||||
|
||||
STRNCPY(G.lib, BKE_main_blendfile_path_from_global());
|
||||
|
||||
|
@ -539,6 +542,10 @@ void WM_exit_ex(bContext *C, const bool do_python_exit, const bool do_user_exit_
|
|||
ED_screen_exit(C, win, WM_window_get_active_screen(win));
|
||||
}
|
||||
|
||||
if (!G.background) {
|
||||
blender::ui::string_search::write_recent_searches_file();
|
||||
}
|
||||
|
||||
if (do_user_exit_actions) {
|
||||
if ((U.pref_flag & USER_PREF_FLAG_SAVE) && ((G.f & G_FLAG_USERPREF_NO_SAVE_ON_EXIT) == 0)) {
|
||||
if (U.runtime.is_dirty) {
|
||||
|
|
Loading…
Reference in New Issue
Worth noting what units this is in & if it can ever be negative.