Well, I figured out the answer to my question, at least partially--for KDE apps that don't have a built-in shortcut-configuration mechanism. The solution involves changing source code, but it is a minor change. The shortcut won't show up in the menu itself (without some additional hackery which I deemed unnecesary since I already know what the shortcut is). But the shortcut will work, it will activate the menu item. For more explanation of this method, see edu.kde.org/development/kaction.php
The code listed below goes into the constructor of the menu object (the object which extends some variant of KPopupMenu). The variables named kk... are my variables. The kk... variables that are newly allocated here (e.g. kkSignalMapper = new...) have to of course be deleted in the menu's destructor. They also have to be added to the member variable list for the menu class, which is usually contained in the header file. The header files that need to be included for the below code are:
So, here is the code:
1) kkSignalMapper = new QSignalMapper(this);
2) connect(kkSignalMapper, SIGNAL(mapped(int)), this, SLOT(activatedSlot(int)));
3) kkActionCollection = new KActionCollection(parent);
4) KAction* kkCurAction = new KAction(i18n("junk"), CTRL+Key_1, kkSignalMapper, SLOT(map()), kkActionCollection, "waste");
5) // Set shortcut to correspond to the index of the menu item you want (item 26 in this case)
6) kkSignalMapper->setMapping(kkCurAction, 26);
Now for a little explanation.
In all the lines, "this" corresponds to the menu object itself, since we are in the menu's constructor.
In line (2), "activatedSlot" is the name of the function in the menu class which defines what to do when a menu item is selected. This function comes with the code--it will be written already by the app author, and it may be called something different from "activatedSlot" of course. Typically this function will be basically a big switch statement that defines what to do if the menuitem index (integer passed in) equals 1 or 2 or whatever.
In line (3), "parent" corresponds to the parent variable passed into the menu constructor--this will usually be the main window, or the containing window. You need to use "parent" in line (3), not "this"--if you use "this", the shortcut will only work when the menu is actually open and displayed on the screen--which of course defeats the whole purpose of this exercise.
Line (4) defines what keystroke combination you want. The second parameter can be replaced by things line "SHIFT+CTRL+Key_P" or whatever you want. The first and last parameters are obviously nonsense and not used for this code. You can repeat this line multiple times, with different KAction* variables each time. Each line will correspond to a different keystroke. You should probably keep the first and last parameters unique for each call. For example, the next line might be:
KAction* kkCurAction2 = new KAction(i18n("junk2"), SHIFT+CTRL+Key_P, kkSignalMapper, SLOT(map()), kkActionCollection, "waste2");
Line 6 maps the action (containing the shortcut) created in line 4 with a menuitem index you want that shortcut to map to. You need one of these lines for every KAction you create above.