Thanks krivov!
I continued development somewhat and here is v0.2 of the applet:
See version history for changes. Mainly I added support for different backgrounds for each desktop.
Source code:
#! /usr/bin/env python
# -*- coding: UTF-8 -*-
"""
* Copyright (C) 2008 Sergei Krivov <krivov@yahoo.com>
* Copyright (C) 2008 Fredrik Wollsén <fredrik.motin@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
"""
"""
Separate desktop for each workspace:
May need to Hit Ctrl-R to refresh desktop, when switched to new workspace.
One nautilus window should be running.
Desktop directories are created in ~/Desktops/ and are called 0, 1, 2 etc
To use different backgrounds for each desktop, put the background files
in ~/Desktops/ with the name of the desktop directory with ".bg" added to
the filename, for instance "~/Desktops/1.bg"
Note - do not use any ordinary file ending such as .jpg or .png - only .bg!
Installations instructions:
Rename and put a copy of this file in /usr/lib/mdesktops-applet/mdesktops-applet:
sudo mkdir /usr/lib/mdesktops-applet/
sudo cp mdesktops.py /usr/lib/mdesktops-applet/mdesktops-applet
Then run:
sudo python /usr/lib/mdesktops-applet/mdesktops-applet install
Uninstallation instructions:
sudo python /usr/lib/mdesktops-applet/mdesktops-applet uninstall
A recommendation is to make the first virtual desktop point to your original desktop:
rmdir ~/Desktops/0
ln -s ~/Desktop ~/Desktops/0
Version history:
0.2 - Fredrik Wollsén
* Different backgrounds for each desktop (~/Desktops/0.bg used for first desktop etc)
* Changed structure:
The desktop folders are now found in ~/Desktops instead of ~/.desktops - this way it's easier to find them for new users
The symlink to the current desktop is named .current instead of current_desktop so that it isn't visible
The desktop directories are named nothing but a number - makes the applet more discrete and avoids duplicate "Desktop" in path names (ie Desktops/Desktop1 etc)
Desktop folders ranged 1-6 instead of 0-5 - for easier human interpretation of which folder belongs to which workspace
* Commandline uninstallation feature
* Misc changes:
Added UTF-8 encoding declaration to file
Friendlier installation and uninstallation messages
* Renamed application file and bonobo server files to comply with debian and GNOME policies (next version will be packaged as a debian package)
0.1 - Sergei Krivov
* Original Applet - Different Icons for each desktop
"""
import gtk,wnck,os,sys
import pygtk
pygtk.require('2.0')
import gnomeapplet
import gnome
import pickle
import commands
class Mdesktops_Applet(gnomeapplet.Applet):
def __init__(self,applet,iid):
self.__gobject_init__()
gnome.init("mdesktops","1.0")
self.applet=applet
self.menu=gtk.Menu()
self.litem=[]
self.applet.connect("button-press-event",self.button_clicked,self.menu)
self.screen=wnck.screen_get_default()
self.screen.connect("active_workspace_changed",self.active_workspace_changed)
self.home=os.path.expanduser('~')
self.desktops=self.home+'/Desktops'
self.check_desktops_dir()
self.load_state()
self.label=gtk.Label("0")
self.applet.add(self.label)
self.applet.connect("destroy",self.cleanup)
self.applet.show_all()
self.ordinary_background = commands.getoutput('gconftool -g /desktop/gnome/background/picture_filename')
def button_clicked(self,widget,event,menu):
if event.type == gtk.gdk.BUTTON_PRESS and event.button == 1:
self.fill_menu(menu)
menu.show_all()
menu.popup(None,None,None,event.button,event.time)
return True
def response(self,widget,desktop):
if desktop in self.history:self.history.remove(desktop)
self.history.insert(0,desktop)
if len(self.history)>5:self.history.pop()
ws=self.screen.get_active_workspace().get_number()
self.ws2dt[ws]=desktop
self.set_desktop(ws)
def response_new(self,widget,desktop):
chooser = gtk.FileChooserDialog(title=None,action=gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,\
buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK))
chooser.set_current_folder(self.desktops+'/..')
response=chooser.run()
if response == gtk.RESPONSE_OK:
desktop=chooser.get_filename()
chooser.destroy()
self.response(None,desktop)
chooser.destroy()
def fill_menu(self,menu):
for item in self.litem:self.menu.remove(item)
self.litem=[]
items=list(self.history)
items.append(None)#separator
ldir=os.listdir(self.desktops)
ldir=[os.path.join(self.desktops,d) for d in ldir]
ldir=[d for d in ldir if os.path.isdir(d) and not os.path.islink(d)]
ldir.sort()
items+=ldir
items.append('..')
for desktop in items:
if desktop==None:item=gtk.SeparatorMenuItem()
else:
item=gtk.MenuItem(os.path.basename(desktop))
if desktop=='..':item.connect("activate",self.response_new,desktop)
else:item.connect("activate",self.response,desktop)
menu.add(item)
self.litem.append(item)
def active_workspace_changed(self,screen,bla=None):
ws=screen.get_active_workspace().get_number()
self.set_desktop(ws)
def set_desktop(self,ws):
if self.ws2dt.has_key(ws):desktop=self.ws2dt[ws]
else:
desktop='%s/%s' %(self.desktops,ws+1)
if not os.access(desktop,os.F_OK):# desktop does not exist, take default
desktop='%s/1' % self.desktops
com='rm %s \n ln -s %s %s' %(self.current_desktop,desktop,self.current_desktop)
os.popen(com)
self.label.set_text(os.path.basename(desktop))
os.popen('gconftool-2 --type bool --set /apps/nautilus/preferences/show_desktop false')
os.popen('gconftool-2 --type bool --set /apps/nautilus/preferences/show_desktop true')
# load special desktop background (named the same as the desktop directory but with .bg added to the path) if available - otherwise restore the original background
desktop_bg='%s.bg' %(desktop)
if not os.access(desktop_bg,os.F_OK):
desktop_bg=self.ordinary_background
os.popen('gconftool -s -t string /desktop/gnome/background/picture_filename \"%s\"' %(desktop_bg))
def load_state(self):
name='%s/.mdesktops' % self.desktops
self.ws2dt,self.history={},[]
if os.access(name,os.F_OK):
f=open(name)
self.ws2dt,self.history=pickle.load(f)
def save_state(self):
name='%s/.mdesktops' % self.desktops
f=open(name,'w')
pickle.dump((self.ws2dt,self.history),f)
def cleanup(self,event):
self.save_state()
os.popen('xdg-user-dirs-update --set DESKTOP %s/Desktop' %self.home)
del self.applet
def create_about_menu(self):
self.applet.setup_menu(self.propxml,self.verbs,None)
def about_info(self,event,data=None):
about = gnome.ui.About("Desktop selection applet",0.2,"GPL",\
"GNOME Applet to manage multiple desktops (separate for each workspace). v0.2 by Fredrik Wollsén <fredrik.motin@gmail.com>",["Sergei Krivov <krivov@yahoo.com>"],\
["Sergei Krivov <krivov@yahoo.com>"],"Sergei Krivov <krivov@yahoo.com>",None)
about.show()
def check_desktops_dir(self):
if not os.access(self.desktops,os.F_OK):os.popen('mkdir '+self.desktops)
for i in range(6):
name=self.desktops+'/%i' %(i+1)
if not os.access(name,os.F_OK):os.popen('mkdir '+name)
name=self.desktops+'/.current'
self.current_desktop=name
os.popen('xdg-user-dirs-update --set DESKTOP %s' %self.current_desktop)
def sample_factory(applet,iid):
Mdesktops_Applet(applet,iid)
return gtk.TRUE
def install(): #create bonobo server file
com="""<oaf_info>
<oaf_server iid="OAFIID:mdesktops_Factory"
type="exe" location="%s">
<oaf_attribute name="repo_ids" type="stringv">
<item value="IDL:Bonobo/GenericFactory:1.0"/>
<item value="IDL:Bonobo/Unknown:1.0"/>
</oaf_attribute>
<oaf_attribute name="name" type="string" value="Multiple desktops"/>
<oaf_attribute name="description" type="string" value="Multiple desktops"/>
</oaf_server>
<oaf_server iid="OAFIID:mdesktops"
type="factory" location="OAFIID:mdesktops_Factory">
<oaf_attribute name="repo_ids" type="stringv">
<item value="IDL:GNOME/Vertigo/PanelAppletShell:1.0"/>
<item value="IDL:Bonobo/Control:1.0"/>
<item value="IDL:Bonobo/Unknown:1.0"/>
</oaf_attribute>
<oaf_attribute name="name" type="string" value="Multiple desktops"/>
<oaf_attribute name="description" type="string" value="Multiple desktops"/>
<oaf_attribute name="panel:category" type="string" value="Utility"/>
<oaf_attribute name="panel:icon" type="string" value="bug-buddy.png"/>
</oaf_server>
</oaf_info>
"""
try:
f=open('/usr/lib64/bonobo/servers/GNOME_Mdesktops.server','w')
f.write(com % '/usr/lib/mdesktops-applet/mdesktops-applet')
f.close()
except:
try:
f=open('/usr/lib/bonobo/servers/GNOME_Mdesktops.server','w')
f.write(com % '/usr/lib/mdesktops-applet/mdesktops-applet')
f.close()
except:
print "Can not create bonobo server file; need root permisions"
sys.exit(1)
print "Multiple Desktops applet installed successfully. You may need to logout and log back before you can add it to the GNOME Panel."
def uninstall(): #remove bonobo server file
server_64file='/usr/lib64/bonobo/servers/GNOME_Mdesktops.server'
os.popen('rm -f %s' %(server_64file))
server_file='/usr/lib/bonobo/servers/GNOME_Mdesktops.server'
os.popen('rm -f %s' %(server_file))
if not os.access(server_64file,os.F_OK) | os.access(server_file,os.F_OK):
print "Multiple Desktops applet uninstalled successfully"
else:
print "Can not remove bonobo server file; need root permisions"
sys.exit(1)
if len(sys.argv) == 2 and sys.argv[1] == "run-in-window":
main_window = gtk.Window(gtk.WINDOW_TOPLEVEL)
main_window.set_title("Mdesktops Applet")
main_window.connect("destroy", gtk.main_quit)
app = gnomeapplet.Applet()
sample_factory(app, None)
app.reparent(main_window)
main_window.show_all()
gtk.main()
sys.exit()
if len(sys.argv) == 2 and sys.argv[1] == "install":
install()
sys.exit()
if len(sys.argv) == 2 and sys.argv[1] == "uninstall":
uninstall()
os.popen('xdg-user-dirs-update --set DESKTOP %s/Desktop' % os.path.expanduser('~'))
sys.exit()
if __name__ == '__main__':
gnomeapplet.bonobo_factory("OAFIID:mdesktops_Factory",\
gnomeapplet.Applet.__gtype__,"hello","0",sample_factory)