void BuildSubmenuFromModel()

in shell/browser/ui/gtk/menu_util.cc [153:244]


void BuildSubmenuFromModel(ui::MenuModel* model,
                           GtkWidget* menu,
                           GCallback item_activated_cb,
                           bool* block_activation,
                           void* this_ptr) {
  std::map<int, GtkWidget*> radio_groups;
  GtkWidget* menu_item = nullptr;
  for (int i = 0; i < model->GetItemCount(); ++i) {
    std::string label = ui::ConvertAcceleratorsFromWindowsStyle(
        base::UTF16ToUTF8(model->GetLabelAt(i)));

    bool connect_to_activate = true;

    switch (model->GetTypeAt(i)) {
      case ui::MenuModel::TYPE_SEPARATOR:
        menu_item = gtk_separator_menu_item_new();
        break;

      case ui::MenuModel::TYPE_CHECK:
        menu_item = gtk_check_menu_item_new_with_mnemonic(label.c_str());
        break;

      case ui::MenuModel::TYPE_RADIO: {
        auto iter = radio_groups.find(model->GetGroupIdAt(i));

        if (iter == radio_groups.end()) {
          menu_item =
              gtk_radio_menu_item_new_with_mnemonic(nullptr, label.c_str());
          radio_groups[model->GetGroupIdAt(i)] = menu_item;
        } else {
          menu_item = gtk_radio_menu_item_new_with_mnemonic_from_widget(
              GTK_RADIO_MENU_ITEM(iter->second), label.c_str());
        }
        break;
      }
      case ui::MenuModel::TYPE_BUTTON_ITEM: {
        NOTIMPLEMENTED();
        break;
      }
      case ui::MenuModel::TYPE_SUBMENU:
      case ui::MenuModel::TYPE_COMMAND: {
        auto icon_model = model->GetIconAt(i);
        if (!icon_model.IsEmpty())
          menu_item = BuildMenuItemWithImage(label, icon_model.GetImage());
        else
          menu_item = BuildMenuItemWithLabel(label);
#if !GTK_CHECK_VERSION(3, 90, 0)
        G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
        if (GTK_IS_IMAGE_MENU_ITEM(menu_item)) {
          gtk_image_menu_item_set_always_show_image(
              GTK_IMAGE_MENU_ITEM(menu_item), TRUE);
        }
        G_GNUC_END_IGNORE_DEPRECATIONS;
#endif
        break;
      }

      default:
        NOTREACHED();
    }

    if (model->GetTypeAt(i) == ui::MenuModel::TYPE_SUBMENU) {
      GtkWidget* submenu = gtk_menu_new();
      ui::MenuModel* submenu_model = model->GetSubmenuModelAt(i);
      BuildSubmenuFromModel(submenu_model, submenu, item_activated_cb,
                            block_activation, this_ptr);
      gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item), submenu);

      // Update all the menu item info in the newly-generated menu.
      gtk_container_foreach(GTK_CONTAINER(submenu), SetMenuItemInfo,
                            block_activation);
      submenu_model->MenuWillShow();
      connect_to_activate = false;
    }

#if defined(USE_X11)
    ui::Accelerator accelerator;
    if (model->GetAcceleratorAt(i, &accelerator)) {
      gtk_widget_add_accelerator(menu_item, "activate", nullptr,
                                 GetGdkKeyCodeForAccelerator(accelerator),
                                 GetGdkModifierForAccelerator(accelerator),
                                 GTK_ACCEL_VISIBLE);
    }
#endif

    g_object_set_data(G_OBJECT(menu_item), "model", model);
    AppendMenuItemToMenu(i, model, menu_item, menu, connect_to_activate,
                         item_activated_cb, this_ptr);

    menu_item = nullptr;
  }
}