veket官方网站论坛

veket

 找回密码
 要注册
搜索
查看: 28935|回复: 54

veket-7的系统菜单以及.desktop文件的写法

[复制链接]
发表于 2012-11-24 23:36 | 显示全部楼层 |阅读模式
本帖最后由 perryfa 于 2013-3-3 14:38 编辑

[perryfa注:这个教程是很久以前写的,写完后觉得有点深了,菜鸟用不上,就扔在一边了,然后就忘了。前两天整理文件发现了,拿出来根据veket-7的情况速度地改了一下,发出来。如果发现有什么不对头的,请提醒我,我改。另外,我在这里写的其实都是自己积累的经验,我拥有的linux知识99%来自veket系统本身,就是一个纯外行在使用系统过程中连猜带蒙外加试错得到的经验,没读过书、基本不读文档,没任何理论积累,有什么不对的,望专业人士不吝指正]

本教程基于veket-7.86。

Part I 系统菜单
linux的系统菜单是由桌面管理器提供的,所以,系统使用的桌面管理器不同,形成菜单需要的文件也是不同的。本文只介绍 xfce桌面管理器的菜单。因为veket-7和之前的lucy8k-veket系列采用xfce作为桌面管理器。
注意:之前的veket系列采用icewm桌面管理器,系统菜单的机制是不同的。本文介绍的内容不适用。
系统菜单的形成原理是这样的,首先是系统里要有定义菜单结构的文件,就是我们通常说的menu文件,这个文件定义系统菜单应该有多少分类(即子菜单)、每个子菜单应该包含哪些应用程序的分类、子菜单的名字是什么、子菜单项应该显示什么样的图标等等。有了这个菜单结构文件,当某个应用程序被安装时,系统会去找这个程序带来的桌面文件(即.desktop文件,任何一个linux程序如果需要有菜单的话必然会有这个.desktop文件,这不是veket独有的),从中找到该应用程序的分类名字,然后和菜单文件对照,确定这个应用程序应该被放在哪个位置。

系统菜单的结构来自这个文件:
/usr/etc/xdg/menus/xfce-applications.menu
这个文件定义了系统菜单的结构和分类,下面的介绍应该结合这个文件来读,否则就不知道我在说什么了。
如果把menu文件的内容看作是一段程序,那么它是超简单的。虽然它很简单,但要想搞清楚它的写法,还是需要稍微那么一点点编程的知识,至少知道程序嵌套是怎么回事(这种句子打出来有点不好意思,因为我自己就没有编程基础,就是胡乱摸索的)。如果你是纯小白,也没有自己去定制、修改系统菜单的需求,建议你就没必要往下读了,知道这个文件是定义系统菜单的就可以了。
menu文件的创建和编辑和普通的文本文件一样,用文本编辑器就可以。建议用Geany编辑,这样做出来的文件的嵌套结构比较整齐。
要提醒一点,menu文件中的任何一点微小的错误都会造成整个系统菜单消失,所以,编辑修改之前最好要备份。不过也只是系统菜单消失,不会影响系统的其它功能,把备份文件放回就瞬间恢复了,不必过于惊慌。

(1)xfce-applications.menu文件的结构
菜单(包括子菜单)的基本结构是这样的:
<Menu>
    <Name>。。。</Name>
    <Directory>。。。</Directory>
    <Include>。。。</Include>
    <Layout>。。。</Layout>
    <Menu>
         。。。
    </Menu>
</Menu>
“Menu”是嵌套结构,多嵌套一层就意味着多一层子菜单,一个menu嵌套里面有多少个<Directory>,就必须有多少个<memu>子嵌套,因为它们是一一对应的。veket-7.8的菜单最深是三层,整个结构就是这样:
<Menu>
。。。。。。
    <Menu>
      。。。。。。
      <Menu>
      。。。。。。
      </Menu>
    </Menu>
</Menu>

(2)系统菜单文件内容
在<Menu></Menu>里面就是具体的菜单内容了。

(i)<Name>。。。</Name>
     定义菜单或子菜单的名字。
     
(ii) <Directory>。。。</Directory>
     当某个菜单项并非是具体的应用程序,而是一个应用程序组时,这个部分定义应用程序组的名字和图标。注意,只要出现一个<Directory>,那么后面就必须跟有一个子菜单嵌套<menu>...</memu>。
     举例说明。在第一层系统菜单里有一个“开发编程”的菜单项,你点它就开出第二层子菜单,而不是开启某个具体的应用程序,所以它是个子菜单。在系统菜单文件中它的写法是:
          <Directory>xfce-development.directory</Directory>
         这一句定义的是“开发编程”这个子菜单,意思是系统应该去xfce-development.directory这个文件找子菜单的具体信息,这些信息包括子菜单名字和图标等。如果去读一下这个文件你会发现,这个文件定义的东西很少,只有菜单名字和图标之类,至于这个子菜单里放什么类别的应用程序,应用程序之间怎么排列,这些都没有写。这些详细内容需要在后面加一个<menu>嵌套来描述。
        directory文件放在这里:
         /usr/share/desktop-directories/xfce-development.directory
         在/usr/share/desktop-directories/这个目录里有很多.directory文件,每个文件定义一组子菜单。
         
(iii)  <Include>。。。</Include>
        这个部分定义一组菜单里显示的应用程序的类别。也就是说,应用程序应该出现在哪个子菜单里。具体的结构是这样的:
         <Include>
            <Category>Development</Category>
              。。。。。。
            <Category>Shell</Category>
        </Include>
        用<Include>括起来,里面含有N个<Category></Category>。
        一套<Category></Category>定义一个分类名。
        当xfce从系统指定的applications目录读到某个应用程序的.desktop文件时,它会寻找该文件里的Categories参数,根据该参数决定把这个应用程序显示在菜单中的哪个位置。
       注意,除非你刻意为之,一个分类名在menu文件中只能出现一次,如果你在不同的子菜单嵌套里写入同一个分类名,那么系统菜单就会出现重复的菜单项。
        
(iv)  <Layout>。。。</Layout>
        这个部分定义菜单的排序。它是可选的,如果不写这个部分,系统就自动按英文字母顺序排列菜单项。
        一个<Layout></Layout>里可以有下列主要内容:
        <Menuname>某子菜单的菜单名</Menuname> 指定子菜单的位置
        <Filename>某应用程序的.desktop文件的文件名</Filename>指定某个具体的应用程序菜单项的位置
        <Separator/>分割线
        <Merge type="all"/>未被指定位置的菜单项就显示在这里
        例如,“办公应用”这个菜单的layout是这样的:
         <Layout>
            <Filename>Abiword-wordprocessor.desktop</Filename>
            <Filename>Gnumeric-spreadsheet-editor.desktop</Filename>
            <Separator/>
            <Menuname>Document Tools</Menuname>
            <Menuname>Personal Tools</Menuname>
            <Separator/>
            <Merge type="all"/>
        </Layout>
        最上面两项是Abiword和Gnumeric这两个应用程序,然后是一条分割线,然后是两个子菜单项(“文件阅读转换工具”和“个人工具”),再一条分割线,最后就是未被指定位置的应用程序项了,不管有多少,都按程序名的英文字母顺序排列下去。
       注意:
        a. 虽然<Layout>部分是可以不写的,但一旦你写了,最好写有<Merge type="all"/>这一行,因为,就算你把系统里所有相关类别的.desktop文件都罗列在Layout里面了,暂时看起来菜单里已经不缺什么了,但你不知道将来还会不会安装属于这些类别的程序,如果你不写<Merge type="all"/>,将来安装的程序就不知道该放在哪里了。
       b. <Layout>里面罗列的.desktop文件的Categories必须和同一层里的<Include>里定义的对应,例如“办公应用”子菜单的<Include>里定义了11种Categories,如果某个程序的.desktop文件里的Categories不属于这11种,就算你把这个.desktop文件写入<Layout>里了,那也是白写,这个程序是不会出现在“办公应用”子菜单里的。
      c. 如果你在<Layout>里写入了一个子菜单,例如上面写的<Menuname>Document Tools</Menuname>,那么,在这一层里(Layout后面)必须写有对应的<Menu></Menu>嵌套,这个<Menu></Menu>里的子菜单名必须和<Layout>里写的一模一样。

    菜单文件还有一些其他的内容,例如分类名还可以有“与”和“非”的操作,“与”是用来定义某个子菜单必须同时拥有某几个分类名才能显示出来,如果.desktop文件里只有一个分类名符合,那菜单就不显示。“非”就更简单了,不管.desktop文件里面有多少个分类名符合某个子菜单的定义,只要出现一个分类名是被定义为“非”的,那么这个子菜单就坚决不显示这个程序。具体的去看veket-7的菜单文件,里面都写有的。
   
(待续)
 楼主| 发表于 2012-11-24 23:37 | 显示全部楼层
本帖最后由 perryfa 于 2013-3-3 14:51 编辑

Part II 应用程序.desktop文件
这个部分不依赖桌面管理器,对lucy8k和veket系列都适用的。

.desktop文件(我有时叫它应用程序桌面文件)是个可执行文件,在文件管理器里双击它是可以运行的。但它不是任何一种脚本,文件内容的构成也没有任何逻辑结构,类似某种 conf 设置文件,里面记录了各种参数,这些参数定义了它用于菜单或者桌面快捷方式时需要的一些信息。
创建和编辑.desktop文件和一个普通的文本文件没什么区别,只是文件名必须带有.desktop后缀。

每个应用程序通常至少带有一个.desktop文件(可以有多个,不限)。这个文件的用处很多,不仅仅是用在系统菜单。常用的:
(1)将应用程序显示在系统菜单上,形成应用程序菜单项;
(2)拉到/root/Desktop/目录就是桌面快捷方式(xfce桌面管理器);
(3)建立某一类或几类文件和应用程序之间的关联,在文件管理器里显示右键菜单(打开方式)。

veket系统里有三个地方放.desktop文件。就是:
/usr/share/applications
/usr/local/share/applications
/root/.local/share/applications
前两个目录,存放一般的应用程序桌面文件。如果你的程序放在/usr目录下,桌面文件就放在/usr/share/applications;如果你的程序放在/usr/local/下,桌面文件就放在/usr/local/share/applications。
而/root/.local/share/applications这个目录里的.desktop文件,我们一般用来定义文件管理器里的右键菜单。当然,其他applictions目录里的.desktop文件也能定义右键菜单的显示,但是,/root/.local/share/applications里面的文件在右键菜单的排序时优先级较高,当某个文件类型可以有多个应用程序来打开时(例如文本文件,可以用leafpad、Geany等等程序来打开),哪个程序放在第一个、成为默认打开的应用程序,这就需要特别的指定,否则文件管理器就会按照应用程序的英文字母顺序来排列右键菜单,有可能会不方便了。所以,需要排在第一个的应用程序就在/root/.local/share/applications目录里单独放一个.desktop文件。

下面,我以mtPaint这个程序为例,介绍一下.desktop文件的写法。
.desktop文件的文件名是可以随便写的,但为了便于管理,一般就是应用程序的名字加上.desktop的后缀,mtPaint的桌面文件名是“mtPaint-image-editor.desktop”,有点罗嗦,但人家也是好意,怕你认不出它是什么。
mtPaint-image-editor.desktop的内容:
  1. [Desktop Entry]
  2. Encoding=UTF-8
  3. Name=mtPaint image editor
  4. Name[zh_CN]=mtPaint画图
  5. Icon=applications-graphics
  6. Comment=mtPaint image editor
  7. Exec=mtpaint
  8. Terminal=false
  9. Type=Application
  10. Categories=RasterGraphics
  11. GenericName=mtPaint image editor
  12. MimeType=image/png;image/jpeg;
复制代码
下面我介绍一下这些内容:

1. 基本内容

首先,.desktop文件里的内容是以行区分的,一行就是一个参数,各行的上下排列顺序没有要求,也就是说,除了第一行文件标识,其他行的排列是无所谓的。
其次,除了第一行标识,.desktop文件的其他内容是可选的。也就是说,你可以根据需要选择写什么,不写什么。例如,你可以自己决定是否要写入程序的注释。

[Desktop Entry] 这是.desktop文件的标识,必须在第一行。
Encoding=UTF-8  这是编码集
Type=Application 表示是应用程序
上面三行是雷打不动的,不用改。

Name=mtPaint image editor
等号后面是应用程序的英文名字。
Name[zh_CN]=mtPaint画图
等号后面是应用程序的中文名字。在Name后面的方括号里括的是语言标识,系统在读.desktop文件时,会自动去找你的系统的默认语言,如果你的默认语言是中文,系统就会找“Name[zh_CN]=”后面的内容,如果你的.desktop文件里没有这一行,那系统就直接显示“Name=”后面写的名字了。
GenericName=mtPaint image editor
通用名/别名
也可以有中文的,加一行:
GenericName[zh_CN]=画图

Comment=mtPaint image editor
等号后面是应用程序的英文注释。
注释也可以有不同的语言,如果要写中文的注释,就加一行:
Comment[zh_CN]=mtPaint图像编辑器

Exec=mtpaint
等号后面就是运行该程序的命令了。根据需要,运行命令是可以有参数的。
一开始我说过,一个应用程序的.desktop文件可以有多个。可以用多个.desktop文件来运行多个不同的命令,分别实现不同的功能。
例如,smplayer播放器,如果.desktop文件中是这样的内容:
Exec=smplayer
这就意味着运行命令“smplayer”,就是打开播放器。这个.desktop文件用于系统菜单或桌面快捷方式。
如果是这样写的:
Exec=smplayer -add-to-playlist
后面的参数就意味着是把某个音乐文件加入播放器的播放列表,显然,这个.desktop文件是专门用于文件管理器的右键菜单的,显示在系统菜单里是毫无意义的。
问题来了,系统怎么知道这个.desktop文件不需要显示在系统菜单里呢?在.desktop里加一行就可以了:
NoDisplay=true
在/usr/share/applications目录里看到的很多.desktop文件都没有出现在系统菜单里,就是因为文件里有这一行。

Icon=applications-graphics
等号后面定义在菜单或桌面上显示什么图标。
如果所选用的图标放在系统默认的图标目录,例如/usr/share/icons,/usr/share/pixmaps,/root/.icons这些,那就不用写图标文件的路径和后缀名。上面的“applications-graphics”就是个系统默认的图标。
如果图标文件不是系统默认的,放在你自己定义的目录里,那么在等号后面就要写全图标文件的全名,即路径、文件名、后缀名写全了才行。例如这样:
Icon=/root/lucky8k/mtpaint.png

Terminal=false
这行定义在运行“Exec=”定义的命令时,是否同时要打开终端。通常都是用“false”,表示不打开。

通常就是上面这些基本内容了,还有一些不常用的这里就不作介绍了。
下面介绍两个重要的参数,因为比较复杂一点,所以单独介绍。

2. 应用程序分类名
应用程序的分类名定义了该程序在系统菜单中所处的位置。
在.desktop文件里,表达方式就是这样:
Categories=RasterGraphics
“RasterGraphics”就是mtPaint这个程序的分类名。

“Categories=”后面的分类名是可以有多个的,用“;”隔开。
当你从网上下载一个应用程序包,通常它的分类名会有很多个。如果你不加修改直接拿来就用,其后果就是,在系统菜单的多处都显示有这个程序,重复重复再重复,比较郁闷。每个分类名在系统菜单文件里都有确定的位置,例如这个“RasterGraphics”,它在veket-7的菜单文件里出现在“Graphics”子菜单的<Include>里面:
<Category>RasterGraphics</Category>
如果某个应用程序的.desktop文件里的“Categories=”后面写有多个分类名,那么该应用程序就会出现在菜单的多个位置。
产生这种问题的原因,我瞎猜一下,大概是做程序的人不可能猜到自己的程序会被安装在哪个linux系统里,因为不同的系统的系统菜单结构是不同的,能识别的分类名也会有差异,为了以防万一,写程序的人都会秉承宁多勿少的原则,把他认为可能的分类名全写上,菜单里有重复总比完全找不到好。这是从程序编写者的角度比较合适的做法,但对于针对veket分享的程序来说,应该在打包前做好修改,把多余的分类名删除,只保留一个。

当然,还有一种可能是,网上下来的程序包安装后菜单里根本找不到。因为程序编写者使用的系统不是veket,他系统里用的分类名veket里没有。这样的话,在veket-7里就会出现在“其他”菜单,因为在菜单文件的最后,我写入了这样的内容:
        <Include>
            <All/>
        </Include>
意思是,如果分类名在菜单文件里没有,那就统统归入此类。
注意,之前的veket系列的菜单没有这个分类,分类名对不上就彻底没菜单项了。
遇到这种情况,打包者应该修改分类名,使程序项出现在正确的子菜单里。

怎样确保分类名的正确书写呢?
正规的做法,查两个系统文件:
/etc/xdg/menus/hierarchy
这个文件书写的是系统的分类结构。每个菜单名下有哪些分类名都写在这里,不过菜单名是英文的。
/etc/xdg/menus/veket_hierarchy_xfce4
这个文件是个中英文的对照表,英文的菜单名对应中文的菜单名就是写在这里。(注意,veket-7之前的版本没有这个文件,所以,你安装pet时,安装完毕跳出的提示信息里关于菜单部分是英文的,而且菜单分类有可能是错的)。
以前我介绍过一个简单的做法。就是直接从菜单上找到你要放置菜单项的位置,找到邻居,然后直接到applications目录找邻居的.desktop文件,复制粘贴邻居的分类名就没错了。

3. 文件类型关联
文件类型关联最直观的表现就是thunar文件管理器的右键菜单。就是你在文件管理器里看到一个文件,对准文件点鼠标右键,选“打开方式”,你会看到一个列表,表示该文件可以用这些应用程序来打开。(注意:rox 文件管理器的右键菜单做法不同,在此不作介绍,因为用rox的人很少)
要让你的应用程序出现在某种文件的右键菜单上,就要在应用程序的.desktop文件里加入文件类型名,就是这样:
MimeType=image/png;image/jpeg;
这是mtPaint的关联列表,表示在png和jpeg两种图片文件的打开方式菜单里会出现mtPaint这个应用程序。
image/png和image/jpeg是两个文件类型名。一些文件操作相关的应用程序中通常会关联多个文件类型名。不同的文件类型名之间用“;”隔开。

那么,veket系统里有哪些文件类型名、这些文件类型名的正确写法是什么呢?看这两个目录:
/usr/share/mime
/root/.local/share/mime
Mime是来自freedesktop.org的一套标准,mime目录是放系统文件类型定义文件的地方。
MIME判断文件类型的方式是这样的。遇到一个文件,mime首先使用magic方式来判断,所谓的magic方式就是直接读文件里的标识性字符,例如我们写shell脚本第一行必然是“#!/bin/sh”,又例如 XPM 图片文件必然以“/* XPM */”开头,这种方式比识别后缀名要更准确,不仅是因为后缀名是可以人工改的,还因为后缀名也常常有重复的,例如.dat,光看这个后缀,谁能告诉我这是一个vcd视频文件呢还是数据文件啊?因为使用了magic方式,linux的文件是可以没有后缀名的(你可以找张PNG图片,修改文件名,即删掉文件名的后缀.png,然后你再看该图片的属性,系统照样能识别,告诉你它是“PNG 图像”)。第二位的判断方式是glob,就是后缀名,如果magic无法分辨,那就用后缀名判断,例如puppy专有的pet包,就是用.pet这个后缀名来标识的。
要想知道某种文件的文件类型名是什么,可以看mime目录里的定义文件。
有个简单的方法,用命令。
假设你有一个png图片文件(/root/veket/test.png),想知道PNG图片的标准文件类型名,打开终端输入:
# file -i /root/veket/test.png
你会看到:
/root/veket/test.png: image/png
这个“image/png”就是PNG图片文件的文件类型名。
发表于 2012-11-24 23:49 | 显示全部楼层
完成了?强烈支持,抢沙发了再慢慢欣赏。

Encoding=UTF-8  这是编码集
难道有其它编码?有含义么?
/usr/share/mime/image/x-xcf.xml
这些之类的还真完全不懂,学习了。
 楼主| 发表于 2012-11-25 00:03 | 显示全部楼层
本帖最后由 perryfa 于 2012-11-25 00:28 编辑

回复 soho366 的帖子

这个说来话长。简单说就是:linux的默认编码就是UTF-8,所以我说是“雷打不动”的,永远这么写。这是世界通用的语言编码,就是国际标准,可以正确显示随便什么文字。而GB2312/GB18030/GBK这些是我国的国家标准,只能显示中文和英文。
发表于 2012-11-25 00:52 | 显示全部楼层
感谢perryfa的热心分享,大家共同进步
您需要登录后才可以回帖 登录 | 要注册

本版积分规则

QQ|手机版|Archiver|veket官方网站论坛 ( 粤ICP备 11052856 )

GMT+8, 2024-4-26 06:10

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表