Context menu 'Edit Source' operator no longer needs to be enabled as a build option, improved this so the python file:line lookups are only done when the operator runs (previously this was done for every button, every draw when the build option was enabled).

Perhaps this should be hidden when not running with --debug, easy to change.
This commit is contained in:
Campbell Barton
2011-10-23 04:13:56 +00:00
parent 29417887d7
commit 8e2bc6cdbc
7 changed files with 271 additions and 128 deletions

View File

@@ -213,9 +213,6 @@ mark_as_advanced(WITH_CXX_GUARDEDALLOC)
option(WITH_ASSERT_ABORT "Call abort() when raising an assertion through BLI_assert()" OFF)
mark_as_advanced(WITH_ASSERT_ABORT)
option(WITH_PYTHON_UI_INFO "Allow navigating to UI source from the context menu" OFF)
mark_as_advanced(WITH_PYTHON_UI_INFO)
if(APPLE)
if(NOT CMAKE_OSX_ARCHITECTURES)
@@ -1330,10 +1327,6 @@ if(WITH_ASSERT_ABORT)
add_definitions(-DWITH_ASSERT_ABORT)
endif()
if(WITH_PYTHON_UI_INFO)
add_definitions(-DWITH_PYTHON_UI_INFO)
endif()
# message(STATUS "Using CFLAGS: ${CMAKE_C_FLAGS}")
# message(STATUS "Using CXXFLAGS: ${CMAKE_CXX_FLAGS}")

View File

@@ -787,6 +787,7 @@ void uiItemMenuEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propn
void UI_buttons_operatortypes(void);
/* Helpers for Operators */
uiBut *uiContextActiveButton(const struct bContext *C);
void uiContextActiveProperty(const struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA **prop, int *index);
void uiContextActivePropertyHandle(struct bContext *C);
void uiContextAnimUpdate(const struct bContext *C);
@@ -817,5 +818,9 @@ const char *UI_translate_do_tooltip(const char *msgid);
#define IFACE_(msgid) UI_translate_do_iface(msgid)
#define TIP_(msgid) UI_translate_do_tooltip(msgid)
/* UI_OT_editsource helpers */
int UI_editsource_enable_check(void);
void UI_editsource_active_but_test(uiBut *but);
#endif /* UI_INTERFACE_H */

View File

@@ -2562,23 +2562,10 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str,
if(block->curlayout)
ui_layout_add_but(block->curlayout, but);
#ifdef WITH_PYTHON_UI_INFO
{
extern void PyC_FileAndNum_Safe(const char **filename, int *lineno);
const char *fn;
int lineno= -1;
PyC_FileAndNum_Safe(&fn, &lineno);
if (lineno != -1) {
BLI_strncpy(but->py_dbg_fn, fn, sizeof(but->py_dbg_fn));
but->py_dbg_ln= lineno;
}
else {
but->py_dbg_fn[0]= '\0';
but->py_dbg_ln= -1;
}
/* if the 'UI_OT_editsource' is running, extract the source info from the button */
if (UI_editsource_enable_check()) {
UI_editsource_active_but_test(but);
}
#endif /* WITH_PYTHON_UI_INFO */
return but;
}

View File

@@ -4443,16 +4443,8 @@ static int ui_but_menu(bContext *C, uiBut *but)
}
}
#ifdef WITH_PYTHON_UI_INFO
if (but->py_dbg_ln != -1) {
PointerRNA ptr_props;
WM_operator_properties_create(&ptr_props, "WM_OT_text_edit");
RNA_string_set(&ptr_props, "filepath", but->py_dbg_fn);
RNA_int_set(&ptr_props, "line", but->py_dbg_ln);
uiItemFullO(layout, "WM_OT_text_edit", "Edit Source", ICON_NONE, ptr_props.data, WM_OP_EXEC_DEFAULT, 0);
}
#endif /* WITH_PYTHON_UI_INFO */
/* perhaps we should move this into (G.f & G_DEBUG) - campbell */
uiItemFullO(layout, "UI_OT_editsource", "Edit Source", ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0);
uiPupMenuEnd(C, pup);
@@ -5146,9 +5138,10 @@ void ui_button_active_free(const bContext *C, uiBut *but)
}
}
static uiBut *ui_context_rna_button_active(const bContext *C)
/* returns the active button with an optional checking function */
static uiBut *ui_context_button_active(const bContext *C, int (*but_check_cb)(uiBut *))
{
uiBut *rnabut= NULL;
uiBut *but_found= NULL;
ARegion *ar= CTX_wm_region(C);
@@ -5166,26 +5159,40 @@ static uiBut *ui_context_rna_button_active(const bContext *C)
}
}
if(activebut && activebut->rnapoin.data) {
if(activebut && (but_check_cb == NULL || but_check_cb(activebut))) {
uiHandleButtonData *data= activebut->active;
rnabut= activebut;
but_found= activebut;
/* recurse into opened menu, like colorpicker case */
if(data && data->menu && (ar != data->menu->region)) {
ar = data->menu->region;
}
else {
return rnabut;
return but_found;
}
}
else {
/* no active button */
return rnabut;
return but_found;
}
}
return rnabut;
return but_found;
}
static int ui_context_rna_button_active_test(uiBut *but)
{
return (but->rnapoin.data != NULL);
}
static uiBut *ui_context_rna_button_active(const bContext *C)
{
return ui_context_button_active(C, ui_context_rna_button_active_test);
}
uiBut *uiContextActiveButton(const struct bContext *C)
{
return ui_context_button_active(C, NULL);
}
/* helper function for insert keyframe, reset to default, etc operators */

View File

@@ -252,11 +252,6 @@ struct uiBut {
/* pointer back */
uiBlock *block;
#ifdef WITH_PYTHON_UI_INFO
char py_dbg_fn[240];
int py_dbg_ln;
#endif
};
struct uiBlock {

View File

@@ -61,6 +61,10 @@
#include "WM_api.h"
#include "WM_types.h"
/* only for UI_OT_editsource */
#include "ED_screen.h"
#include "BKE_main.h"
#include "BLI_ghash.h"
/* ********************************************************** */
@@ -474,6 +478,240 @@ static void UI_OT_reports_to_textblock(wmOperatorType *ot)
ot->exec= reports_to_text_exec;
}
/* ------------------------------------------------------------------------- */
/* EditSource Utility funcs and operator,
* note, this includes itility functions and button matching checks */
struct uiEditSourceStore {
uiBut but_orig;
GHash *hash;
} uiEditSourceStore;
struct uiEditSourceButStore {
char py_dbg_fn[240];
int py_dbg_ln;
} uiEditSourceButStore;
/* should only ever be set while the edit source operator is running */
struct uiEditSourceStore *ui_editsource_info= NULL;
int UI_editsource_enable_check(void)
{
return (ui_editsource_info != NULL);
}
static void ui_editsource_active_but_set(uiBut *but)
{
BLI_assert(ui_editsource_info == NULL);
ui_editsource_info= MEM_callocN(sizeof(uiEditSourceStore), __func__);
memcpy(&ui_editsource_info->but_orig, but, sizeof(uiBut));
ui_editsource_info->hash = BLI_ghash_new(BLI_ghashutil_ptrhash,
BLI_ghashutil_ptrcmp,
__func__);
}
static void ui_editsource_active_but_clear(void)
{
BLI_ghash_free(ui_editsource_info->hash, NULL, (GHashValFreeFP)MEM_freeN);
MEM_freeN(ui_editsource_info);
ui_editsource_info= NULL;
}
static int ui_editsource_uibut_match(uiBut *but_a, uiBut *but_b)
{
#if 0
printf("matching buttons: '%s' == '%s'\n",
but_a->drawstr, but_b->drawstr);
#endif
/* this just needs to be a 'good-enough' comparison so we can know beyond
* reasonable doubt that these buttons are the same between redraws.
* if this fails it only means edit-source fails - campbell */
if( (but_a->x1 == but_b->x1) &&
(but_a->x2 == but_b->x2) &&
(but_a->y1 == but_b->y1) &&
(but_a->y2 == but_b->y2) &&
(but_a->type == but_b->type) &&
(but_a->rnaprop == but_b->rnaprop) &&
(but_a->optype == but_b->optype) &&
(but_a->unit_type == but_b->unit_type) &&
strncmp(but_a->drawstr, but_b->drawstr, UI_MAX_DRAW_STR) == 0
) {
return TRUE;
}
else {
return FALSE;
}
}
void UI_editsource_active_but_test(uiBut *but)
{
extern void PyC_FileAndNum_Safe(const char **filename, int *lineno);
struct uiEditSourceButStore *but_store= MEM_callocN(sizeof(uiEditSourceButStore), __func__);
const char *fn;
int lineno= -1;
#if 0
printf("comparing buttons: '%s' == '%s'\n",
but->drawstr, ui_editsource_info->but_orig.drawstr);
#endif
PyC_FileAndNum_Safe(&fn, &lineno);
if (lineno != -1) {
BLI_strncpy(but_store->py_dbg_fn, fn,
sizeof(but_store->py_dbg_fn));
but_store->py_dbg_ln= lineno;
}
else {
but_store->py_dbg_fn[0]= '\0';
but_store->py_dbg_ln= -1;
}
BLI_ghash_insert(ui_editsource_info->hash, but, but_store);
}
/* editsource operator component */
static ScrArea *biggest_text_view(bContext *C)
{
bScreen *sc= CTX_wm_screen(C);
ScrArea *sa, *big= NULL;
int size, maxsize= 0;
for(sa= sc->areabase.first; sa; sa= sa->next) {
if(sa->spacetype==SPACE_TEXT) {
size= sa->winx * sa->winy;
if(size > maxsize) {
maxsize= size;
big= sa;
}
}
}
return big;
}
static int editsource_text_edit(bContext *C, wmOperator *op,
char filepath[240], int line)
{
struct Main *bmain= CTX_data_main(C);
Text *text;
for (text=bmain->text.first; text; text=text->id.next) {
if (text->name && BLI_path_cmp(text->name, filepath) == 0) {
break;
}
}
if (text == NULL) {
text= add_text(filepath, bmain->name);
}
if (text == NULL) {
BKE_reportf(op->reports, RPT_WARNING,
"file: '%s' can't be opened", filepath);
return OPERATOR_CANCELLED;
}
else {
/* naughty!, find text area to set, not good behavior
* but since this is a dev tool lets allow it - campbell */
ScrArea *sa= biggest_text_view(C);
if(sa) {
SpaceText *st= sa->spacedata.first;
st->text= text;
}
else {
BKE_reportf(op->reports, RPT_INFO,
"See '%s' in the text editor", text->id.name + 2);
}
txt_move_toline(text, line - 1, FALSE);
WM_event_add_notifier(C, NC_TEXT|ND_CURSOR, text);
}
return OPERATOR_FINISHED;
}
static int editsource_exec(bContext *C, wmOperator *op)
{
uiBut *but= uiContextActiveButton(C);
if (but) {
GHashIterator ghi;
struct uiEditSourceButStore *but_store= NULL;
ARegion *ar= CTX_wm_region(C);
int ret;
uiFreeActiveButtons(C, CTX_wm_screen(C));
// printf("%s: begin\n", __func__);
ui_editsource_active_but_set(but);
/* redraw and get active button python info */
ED_region_do_draw(C, ar);
for(BLI_ghashIterator_init(&ghi, ui_editsource_info->hash);
!BLI_ghashIterator_isDone(&ghi);
BLI_ghashIterator_step(&ghi))
{
uiBut *but= BLI_ghashIterator_getKey(&ghi);
if (but && ui_editsource_uibut_match(&ui_editsource_info->but_orig, but)) {
but_store= BLI_ghashIterator_getValue(&ghi);
break;
}
}
if (but_store) {
if (but_store->py_dbg_ln != -1) {
ret= editsource_text_edit(C, op,
but_store->py_dbg_fn,
but_store->py_dbg_ln);
}
else {
BKE_report(op->reports, RPT_ERROR,
"Active button isn't from a script, cant edit source.");
ret= OPERATOR_CANCELLED;
}
}
else {
BKE_report(op->reports, RPT_ERROR,
"Active button match can't be found.");
ret= OPERATOR_CANCELLED;
}
ui_editsource_active_but_clear();
// printf("%s: end\n", __func__);
return ret;
}
else {
BKE_report(op->reports, RPT_ERROR, "Active button not found");
return OPERATOR_CANCELLED;
}
}
static void UI_OT_editsource(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Reports to Text Block";
ot->idname= "UI_OT_editsource";
ot->description= "Edit source code for a button";
/* callbacks */
ot->exec= editsource_exec;
}
/* ********************************************************* */
/* Registration */
@@ -485,5 +723,6 @@ void UI_buttons_operatortypes(void)
WM_operatortype_append(UI_OT_reset_default_button);
WM_operatortype_append(UI_OT_copy_to_selected_button);
WM_operatortype_append(UI_OT_reports_to_textblock); // XXX: temp?
WM_operatortype_append(UI_OT_editsource);
}

View File

@@ -104,11 +104,6 @@
static GHash *global_ops_hash= NULL;
#ifdef WITH_PYTHON_UI_INFO
# include "DNA_text_types.h"
# include "BKE_text.h"
#endif
/* ************ operator API, exported ********** */
@@ -3509,79 +3504,6 @@ static void operatortype_ghash_free_cb(wmOperatorType *ot)
MEM_freeN(ot);
}
#ifdef WITH_PYTHON_UI_INFO
static ScrArea *biggest_text_view(bContext *C)
{
bScreen *sc= CTX_wm_screen(C);
ScrArea *sa, *big= NULL;
int size, maxsize= 0;
for(sa= sc->areabase.first; sa; sa= sa->next) {
if(sa->spacetype==SPACE_TEXT) {
size= sa->winx * sa->winy;
if(size > maxsize) {
maxsize= size;
big= sa;
}
}
}
return big;
}
static int wm_text_edit_exec(bContext *C, wmOperator *op)
{
Main *bmain= CTX_data_main(C);
Text *text;
char filepath[240];
int line= RNA_int_get(op->ptr, "line");
RNA_string_get(op->ptr, "filepath", filepath);
for (text=bmain->text.first; text; text=text->id.next) {
if (text->name && BLI_path_cmp(text->name, filepath) == 0) {
break;
}
}
if (text == NULL) {
text= add_text(filepath, bmain->name);
}
if (text == NULL) {
BKE_reportf(op->reports, RPT_WARNING, "file: '%s' can't be opened", filepath);
return OPERATOR_CANCELLED;
}
else {
/* naughty!, find text area to set, not good behavior
* but since this is a dev tool lets allow it - campbell */
ScrArea *sa= biggest_text_view(C);
if(sa) {
SpaceText *st= sa->spacedata.first;
st->text= text;
}
txt_move_toline(text, line - 1, FALSE);
WM_event_add_notifier(C, NC_TEXT|ND_CURSOR, text);
}
return OPERATOR_FINISHED;
}
static void WM_OT_text_edit(wmOperatorType *ot)
{
ot->name= "Edit Text File";
ot->idname= "WM_OT_text_edit";
ot->exec= wm_text_edit_exec;
RNA_def_string_file_path(ot->srna, "filepath", "", FILE_MAX, "Path", "");
RNA_def_int(ot->srna, "line", 0, INT_MIN, INT_MAX, "Line", "", 0, INT_MAX);
}
#endif /* WITH_PYTHON_UI_INFO */
/* ******************************************************* */
/* called on initialize WM_exit() */
void wm_operatortype_free(void)
@@ -3624,11 +3546,6 @@ void wm_operatortype_init(void)
WM_operatortype_append(WM_OT_collada_export);
WM_operatortype_append(WM_OT_collada_import);
#endif
#ifdef WITH_PYTHON_UI_INFO
WM_operatortype_append(WM_OT_text_edit);
#endif
}
/* circleselect-like modal operators */