Saturday, 26 May 2012

KDE Ubuntu One Dolphin Plugin


So a while ago I switched to KDE because Unity wasn't really for me. While I've tried Unity again since and its much improved. I'm really liking KDE so I see no point in going back. However there were a few issues to overcome with my transition from Gnome 2 to KDE. Chief among them were the keyboard shortcuts and Ubuntu One Integration. Obviously the key board shortcuts were not a major issue because KDE is easily configurable but in terms of Ubuntu One it was a bit more of a struggle. There is a client out there  made by apachelogger but its old and still in alpha and the PPA didn't work for me. So I decided to use the Gnome client under KDE. Which worked but with a few issues.
  • KDE's file manager didn't have a plugin for Ubuntu One, like Nautilus does, so I had to use u1sdtool on the command line or the web interface to publish files and do other operations. 
  • It used the Gnome Keyring to store the token and I had to enter the password to it every time I logged in. 
  • The Control Panel was written in python and GTK and was ugly and slow under KDE.
As of 12.04 the Control Panel is now written in QT. So that issue is fixed. Also I learned that if I switch my login manger to lightdm it with automatically unlock gnome keyring if it has the same password as my login. So that was 2 issues down especially considering I like lightdm better than the kdm anyway.

That only  leaves the dolphin integration. Unfortunately the dolphin plugin was actually the only part of apache logger's Ubuntu One for KDE project that he didn't really like. He says it is no where near production quality. I therefore decided to roll up my sleeves and write my own.

First I decided to add some context context menus so I would be able to carry out common Ubuntu One operations without the need to use the console. So created a few .desktop files to configure them and created a ruby script to run the necessary commands.

#!/usr/bin/ruby

require "open3"

class UbuntuOne
  def unsync_folder input
    streams =  Open3.popen3 "u1sdtool --info="+input
    info = ""
    while(info != nil && !(info.include? "share_id"))
      info = streams[1].gets
    end
    if(info != nil)
      info["  share_id: "] = ""
      share_id = info.chomp
      exec "u1sdtool --delete-folder="+share_id
    end
  end

  def publish_file input
    streams =  Open3.popen3 "u1sdtool --publish-file="+input
    url = streams[1].gets
    puts url
    url["File is published at "] = ""
    streams.each do |i|
      i.close
    end
    exec "qdbus org.kde.klipper 
/klipper org.kde.klipper.klipper.setClipboardContents "+url
  end
end


#arg0 is the function to call
#arg1 is the file
input = ""
ARGV[1].each_char do |c| #put the spaces back
  if(c != " ")
    input += c
  else
    input += "\\ "
  end
end

puts ARGV[0]+" "+input
if(ARGV[0] == "unsync_folder")
  UbuntuOne.new.unsync_folder input
elsif ARGV[0] == "publish_file"
  UbuntuOne.new.publish_file input
else
  puts "Something went wrong :("
end

Note the ruby script only contains methods for the commands that needed some logic.

At the moment the menu for files support :
  • Publish and Copy Weblink 
  • Stop Publishing
And the menu for folders support:
  • Synchronize 
  • Stop Synchronizing
Honestly these context menus do nearly everything nautilus does except for showing you which files are in sync. Which means, I no longer have to drop to the command line to share files which is awesome.

To install the menu plugin just extract this tar ball into "home/yourusername/.kde/share/kde4/services/ServiceMenus/UbuntuOne/" and yes the tar ball was published with the plugin :)

If you have any issues or questions don't hesitate to ask.

I'm now going to take a look at apachelogger's old code for the version control plugin he wrote and the code for the git and svn dolphin plugins to see about showing what files are in sync, like nautilus does. I'm starting a job on Monday so I probably won't have the time for it for a while but I'll post it here whenever I finish it. Also on a side note I'll have to do it in C++ and I don't like C++ as a language but it'll get done ;)