Let's show it on the real example:
I want to create a new submenu for an abandonware games which I love. However, I've got many of them. So, my goal is to create a new menu: Applications → Games → Old Games. A tool for an automatic creation of menu entries would be also nice.
New menus should be created in /etc/xdg/menus/applications-merged/. I've created file old-games.menu here:
<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" "http://www.freedesktop.org/standards/menu-spec/menu-1.0.dtd"> <Menu> <Name>Applications</Name> <!-- Games --> <Menu> <Name>Games</Name> <Directory>Game.directory</Directory> <Include> <And> <Category>Game</Category> </And> </Include> <Menu> <!-- Old Games --> <Name>old-games</Name> <Directory>old-games.directory</Directory> <Include> <Category>OldGame</Category> </Include> </Menu> <!-- End Old Games --> </Menu> <!-- End Games --> </Menu> <!-- End Applications -->
The next step is to create a specification for the new submenu. The default location is in /usr/share/desktop-directories. My old-games.directory:
[Desktop Entry] Type=Directory Name=Old games Name[sk]=Klasické hry Icon=folder
Icon property, you can set some nice icon for your submenu
A item of our new submenu should look like this:
[Desktop Entry] Encoding=UTF-8 Name=Sample app Comment=Its comment Exec=dosbox /home/old-games/app/app.exe -fullscreen -exit Icon=dosbox Terminal=false Type=Application Categories=OldGame;
Because I love using apps with nice GUI and I need to generate many .desktop files the simple application in python & PyGTK was created:
#!/usr/bin/env python # -*- coding: utf-8 -*- import os import sys try: import pygtk pygtk.require("2.0") import gtk except: os.stderr.write("Application needs at least PyGTK 2.0") os.exit(1) class DesktopFileGenerator: def __init__(self): """ Prepare GUI """ self.window = gtk.Window() self.window.connect("destroy", gtk.main_quit) self.window.set_border_width(10) self.window.set_title("Generator of Desktop Files") # Vertical layout vbox = gtk.VBox(spacing = 10) # Heading heading = gtk.Label("<b>Generator of Desktop Files</b>") heading.set_use_markup(True) vbox.pack_start(heading) # Defining inputs input = [] input.append( ('File to execute', gtk.FileChooserButton("Choose File to Execute")) ) boxFileName = gtk.HBox() entryFileName = gtk.Entry() boxFileName.pack_start(entryFileName) sufixFileName = gtk.Label(".desktop") boxFileName.pack_start(sufixFileName) input.append( ('Filename', boxFileName) ) input.append( ('Application name', gtk.Entry()) ) input.append( ('Comment', gtk.Entry()) ) input.append( ('Icon', gtk.FileChooserButton("Choose Icon for the application")) ) # Table of input fields table = gtk.Table(rows = len(input), columns = 2) self.fields = {} for line, field in enumerate(input): name = field[0] + ":" nameLabel = gtk.Label(name) table.attach(nameLabel, 0, 1, line, line+1) table.attach(field[1], 1, 2, line, line+1) # Nasty hack if field[0] == "Filename": self.fields[ field[0] ] = entryFileName else: self.fields[ field[0] ] = field[1] vbox.pack_start(table) # Buttons buttonBox = gtk.HButtonBox() buttonBox.set_layout(gtk.BUTTONBOX_END) createButton = gtk.Button(stock = gtk.STOCK_SAVE) createButton.connect("clicked", self._generateFile) buttonBox.pack_start(createButton) quitButton = gtk.Button(stock = gtk.STOCK_CLOSE) quitButton.connect("clicked", gtk.main_quit) buttonBox.pack_start(quitButton) vbox.pack_start(buttonBox) self.window.add(vbox) self.window.show_all() def run(self): """ Run application """ gtk.main() def _generateFile(self, button): """ Generate a desktop file """ try: name = self.fields['Application name'].get_text().strip() if not name: raise Exception, "You have to input the name of the application" comment = self.fields['Comment'].get_text().strip() if not comment: raise Exception, "You have to input the comment of the application" execFile = self.fields['File to execute'].get_filename() if not execFile: raise Exception, "You have to choose some file" icon = self.fields['Icon'].get_filename() if not icon: icon = "dosbox" fileName = self.fields['Filename'].get_text().strip() + ".desktop" if not fileName: raise Exception, "You have to enter name of generated file" file = open(fileName, "w") file.write("""[Desktop Entry] Encoding=UTF-8 Name=%s Comment=%s Exec=dosbox %s -fullscreen -exit Icon=%s Terminal=false Type=Application Categories=Application;Game;OldGame; """ % (name, comment, execFile, icon) ) file.close() except: # Any error message = "Caught error =>\n\t%s" % str(sys.exc_value) errorMessage = gtk.MessageDialog(parent = self.window, flags = gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, type = gtk.MESSAGE_ERROR, buttons = gtk.BUTTONS_OK, message_format = message) errorMessage.set_title("Error!") errorMessage.run() errorMessage.destroy() return message = "File '%s' successfully generated!" % fileName reportMessage = gtk.MessageDialog(parent = self.window, flags = gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, type = gtk.MESSAGE_INFO, buttons = gtk.BUTTONS_OK, message_format = message) reportMessage.set_title("File generated") reportMessage.run() reportMessage.destroy() # Cleaning for name, object in self.fields.iteritems(): if isinstance(object, gtk.Entry): object.set_text("") self.fields['File to execute'].grab_focus() if __name__ == "__main__": generator = DesktopFileGenerator() generator.run()
I run this application in empty directory. I generate desktop file for each program. Afterwards I copy these files into /usr/share/applications.
To apply these changes you have to log out and afterwards log in. The new submenu should wait for you.