Skip to main content

Notice

Please note that most of the software linked on this forum is likely to be safe to use. If you are unsure, feel free to ask in the relevant topics, or send a private message to an administrator or moderator. To help curb the problems of false positives, or in the event that you do find actual malware, you can contribute through the article linked here.
Topic: Dynamical context menu and "Context menu" in preferences (Read 2393 times) previous topic - next topic
0 Members and 1 Guest are viewing this topic.

Dynamical context menu and "Context menu" in preferences

I want to add dynamic context menu. I tried this and that, and finally - when I got context menu called 'Legacy Command (unsorted)' - I must admit I need help.

I have a cfg_objList, storing structs 'pict_prefs'

Code: [Select]
struct pict_prefs {
    pfc::string8 cfg_Name;//Unique for each object pict_prefs
    pfc::string8 cfg_DefPath;
    GUID guid;
//(...)
};
//FB2K_STREAM_WRITER/READER_OVERLOAD, defPictPrefs etc.
cfg_objList<pict_prefs> g_cfg_PictPrefs(guid_cfg_PictPrefs, defPictPrefs);

I can add, change and delete stored pict_prefs in preferences, and of course number of pict_prefs is variable.

I'm creating context menu with this code:

Code: [Select]
static const GUID guid_mygroup_menu = //(...)

class my_contextmenu_leaf : public contextmenu_item_node_root_leaf{
public:
my_contextmenu_leaf(unsigned p_index) : m_index(p_index){ }

bool get_display_data(pfc::string_base & p_out, unsigned & p_displayflags, metadb_handle_list_cref p_data, const GUID & p_caller) {
p_out = g_cfg_PictPrefs.get_item( m_index ).cfg_Name;
return true;
}

void execute(metadb_handle_list_cref p_data,const GUID & p_caller){
//(...)
}

bool get_description(pfc::string_base & p_out){
p_out = "Downloading pictures of ";
p_out += g_cfg_PictPrefs.get_item( m_index ).cfg_Name;
return true;
}

GUID get_guid(){
return g_cfg_PictPrefs.get_item( m_index ).guid;
// return pfc::guid_null;//With guid_null works too. Which one is correct version?
}

bool is_mappable_shortcut(){ return true; }
private:
        unsigned m_index;
};

class contextmenu_popup : public contextmenu_item_node_root_popup
{
public:
contextmenu_popup(){ }

bool get_display_data(pfc::string_base & p_out,unsigned & p_displayflags,metadb_handle_list_cref p_data,const GUID & p_caller){
p_out="Download picture";
return true;
}

t_size get_children_count(){
return g_cfg_PictPrefs.get_size();
}

contextmenu_item_node * get_child(t_size p_index){
return new my_contextmenu_leaf(p_index);//I hope this is correct
}

GUID get_guid(){
return guid_mygroup_menu;
}

bool is_mappable_shortcut(){
return true;
}
};


class pictdownload_contextmenu : public contextmenu_item_v2{
public:
unsigned get_num_items(){
return 1;//Maybe I should check if g_cfg_PictPrefs.get_size() == 0...
}

contextmenu_item_node_root * instantiate_item (unsigned p_index, metadb_handle_list_cref p_data, const GUID &p_caller){
return new contextmenu_popup();
}

GUID get_item_guid (unsigned p_index){
return guid_mygroup_menu;
}

void get_item_name (unsigned p_index, pfc::string_base &p_out){
p_out = "Download picture";
}

bool get_item_description (unsigned p_index, pfc::string_base &p_out){
p_out = "Downloading pictures from Google";
return true;
}

t_enabled_state get_enabled_state (unsigned p_index){
return contextmenu_item::DEFAULT_ON;
}

void item_execute_simple (unsigned p_index, const GUID &p_node, metadb_handle_list_cref p_data, const GUID &p_caller){
// Is this function ever called?
}
};

static contextmenu_item_factory_t<pictdownload_contextmenu> g_myitem_factory;

My menu works, but I have a problem with 'Preferences/Display - Context Menu'. Now it shows only checkbox with "Download picture" and description "Downloading pictures from Google". I can disable/enable only my whole menu. How to add 'submenu', with list of menu options?

Additional questions:

- about my_contextmenu_leaf ::get_guid - can I return pfc::guid_null without problems? Is 'guid' field in pict_prefs necessary? I think it's necessary for disabling/enabling menu leafs in 'Preferences/Display - Context Menu' (when somebody shows me how to do this), but maybe I'm wrong?

- about pictdownload_contextmenu::item_execute_simple - is this function ever executed?

Dynamical context menu and "Context menu" in preferences

Reply #1
Firstly I don't know which code calls item_execute_simple(), but if it is easy enough for you to implement it then I would do it.

Secondly I think your contextmenu_popup::is_mappable_shortcut() should return false. Also the contextmenu_popup::get_guid() could return pfc::guid_null, since a non-leaf node normally does not need to be identifiable, i.e. for saving shortcut settings.

Finally you should leave my_contextmenu_leaf::get_guid() as it is. The combination of your guid_mygroup_menu and the leaf GUID will be used to uniquely identify the command. It doesn't actually matter how you generate the GUID for the dynamic entries, as long as they are stable across different runs of the application. You could hash the name of a preset if you wanted, even though that would break keyboard shortcuts when the user renames a preset. Personally I think an explicit GUID that is generated when the preset is created is a good choice.

 

Dynamical context menu and "Context menu" in preferences

Reply #2
I have done simular dynamic context menus as you did.
void item_execute_simple () is called when menu command is bind to the toolbar button.