Tips and Tricks About Computers, Web Development, Linux, the Internet and the Like
Linux
scp-notifications for GNOME and Ubuntu – Expanding on My Original Python Script
Jun 26th
Posted by Tyler Mulligan in Compiz
I’ve only been coding Python for ~12 hours total, so don’t expect this to be perfect. Knowing what I know about creating/testing other software and doing my best to scour through very light pynotify documentation, I’ve begun to build out this script to be more useful / portable / configurable. As the Version 0.6 indicates, I’m not quite at my goal yet and there is still more to learn to bring it up to that point.
I’m releasing this early on my blog just in case I caught any people yesterday who’ve been experimenting with my research / code so far. I’ll share it on github when I evolve it just a bit more.
#!/usr/bin/env python
#
# Title: scp-notifications
# Author: Tyler Mulligan (tyler@detrition.net)
# Date: 06/26/2010
# Version: 0.6
# Description:
# Used in combination with an event, such as an action or cronjob, this script
# will scp the latest file from a folder to your server.
#
# Optionally, it can copy the url to your clipboard and/or show a popup with a
# link to the file after succesfully uploading
#
# Orginally developed to be piped to from compiz screenshot tool
# http://interwebninja.com/videos/compiz-screenshot-piped-to-notification-daemon-for-upload.ogv
#
# The MIT License
#
# Copyright (c) 2010 Tyler Mulligan
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE
#
import pygtk
pygtk.require('2.0')
import pynotify
import gtk
import sys
import os
import subprocess
# Set Variables
#####################################
user = "user"
host = "server.com"
# All should have trailing slashes
lfolder = "/home/user/screenshots/"
hfolder = "/home/remote_user/screenshots/"
httplink = "http://"+host+"/screenshots/"
# Display
#####################################
t1 = 5000 # timeout for screenshot upload dialog
t2 = 3000 # timeout for screenshot preview
t3 = 7000 # timeout for link dialog
screenshot_preview = 1 # If using with the compiz screenshot plugin, you may want this
popup_link = 1 # another popup
copy_to_clipboard = 0 # automatically copy text to keyboard
# Position
#####################################
# Get screensize < < used for relative positioning
display = gtk.gdk.display_get_default()
screen = display.get_default_screen()
x = screen.get_width() - 1
y = screen.get_height() - 1
# 0 for Automatic Placement
"""
x1 = 0
y1 = 0
x2 = 0
y2 = 0
x3 = 0
y3 = 0
"""
# Define Relative Position (assuming top-right)
x1 = x-1
y1 = 12
x2 = x1
y2 = y1 + 100
x3 = x-1
y3 = 12
# Define Static (1920 puts it on my second monitor)
"""
x1 = 1919
y1 = 12
x2 = x1
y2 = y1 + 100
x3 = 1920
y3 = 12
"""
#####################################
def upload_cb(n, action):
assert action == "upload"
subprocess.call(["scp", os.path.join(lfolder, f), '%s@%s:%s' % (user, host, hfolder)])
# setup URL in
if copy_to_clipboard:
clipboard = gtk.clipboard_get()
clipboard.set_text(httplink + f)
# make our data available to other applications
clipboard.store()
# Notification: Link for the clicking
if popup_link:
n3 = pynotify.Notification("Here is your link","<a href='" + httplink + f + "'>" + httplink + f + "")
helper = gtk.Button()
icon = helper.render_icon(gtk.STOCK_DIALOG_INFO, gtk.ICON_SIZE_DIALOG)
n3.set_icon_from_pixbuf(icon)
n3.set_urgency(pynotify.URGENCY_NORMAL)
if x3:
n3.set_hint("x", x3)
if y3:
n3.set_hint("y", y3)
n3.set_timeout(t3)
n3.connect("closed",closen3_cb)
if not n3.show():
print "Failed to send notification"
sys.exit(1)
closen1_cb(n1)
closen2_cb(n2)
gtk.main_quit()
sys.exit(1)
# Notification 1 was closed
def closen1_cb(n):
n1.close()
if screenshot_preview:
n2.close()
gtk.main_quit()
# Notification 2 was closed
def closen2_cb(n):
n2.close()
gtk.main_quit()
# Notification 2 was closed
def closen3_cb(n):
n3.close()
gtk.main_quit()
# The Ignore button was clicked
def ignore_cb(n, action):
assert action == "ignore"
closen1_cb(n1)
closen2_cb(n2)
gtk.main_quit()
# Main
def main():
gtk.main()
# Init
if __name__ == '__main__':
if not pynotify.init("Notifier 'scp' Option"):
sys.exit(1)
# Get latest file and build uri
start = os.path.abspath(lfolder)
f = max([(os.path.getmtime(os.path.join(start,p)),p)
for p in os.listdir(start)])[1]
uri = lfolder + f
# Notification: Upload to Server
n1 = pynotify.Notification("Upload to Server?","Copy the file '" + f + "' to the server?")
helper = gtk.Button()
icon = helper.render_icon(gtk.STOCK_DIALOG_QUESTION, gtk.ICON_SIZE_DIALOG)
n1.set_icon_from_pixbuf(icon)
n1.set_urgency(pynotify.URGENCY_NORMAL)
if x1:
n1.set_hint("x", x1)
if y1:
n1.set_hint("y", y1)
n1.set_timeout(t1)
n1.add_action("upload", "Yes, Upload", upload_cb)
n1.add_action("ignore", "Ignore", ignore_cb)
n1.connect("closed",closen1_cb)
if not n1.show():
print "Failed to send notification"
sys.exit(1)
# Notification: Screenshot Preview
if screenshot_preview:
n2 = pynotify.Notification("Screenshot Preview", "", uri)
n2.set_urgency(pynotify.URGENCY_LOW)
if x2:
n2.set_hint("x", x2)
if y2:
n2.set_hint("y", y2)
n2.set_timeout(t2)
n2.connect("closed",closen2_cb)
if not n2.show():
print "Failed to send notification"
sys.exit(1)
main()
.
Ubuntu Notifications (osd-notify) Sucks, notifications-daemon Rocks – Exploiting the Goodness with Compiz
Jun 25th
Posted by Tyler Mulligan in Compiz
Introduction
The long name for this blog used to be “Tyler Mulligan’s Tips and Tricks for Increasing your Efficiency“. I love finding ways to increase my efficiency and let computers do the work while I focus on more interests aspects of what the computer is providing me with. When I recognize an issue, I find a way to cut out time by streamlining the process for the most accurate repetition, like any programmer would/should/could.
I noticed myself taking a lot of screenshots with compiz’ built in screenshot tool (I can hold a hotkey and drag a box to take newspaper style clippings). This is very fast and simple, I highly recommend enabling this option and getting used to it. However, I don’t care much for clicking around on clunky websites to upload images.
This is where my adventure starts… when I find out a very useful feature was deprecated and not replaced in Ubuntu. I don’t use the new notification area, it has too much I don’t need, I never liked the behavior of these new osd-notify notifications which I found out now are even more worthless (sorry team).
Using Sane Notifications in Ubuntu
After reinstalling the GNOME default notifications system in Ubuntu I was able to use SANE notifications that actually… KICK ASS! I don’t understand how osd-notify is better than these which even comes with it’s own notification properties panel. Maybe it’s an under the hood thing…
Regardless, there is no doubt in my mind that notifications that you hover, can still slightly see but click through but cannot perform any actions, even a close, are just plan stupid and annoying..

Screenshot of the script I ended up writing using the “better” notification system to ask me if I want to upload the screenshot I just took to the server.
Linking the notifications
I linked the notifications the following way:

Python Script for Notification that Prompts for File Upload to Server
Knowing diddly squat about Python, I chugged forward with my classic notification popups that allow for interaction as it had the most activity around it and some examples available in /usr/share/doc/python-notify/examples/
I ended coming up with the following script thanks to some help from a few people in #python on irc.freenode.org
This is outside of the scope of this blogpost but this script assumes you have setup passwordless ssh to your server.
#!/usr/bin/env python
#
# Title: Notification 'scp' Option
# Author: Tyler Mulligan (tyler@detrition.net)
# Date: 06/25/2010
# Description:
# Used in combination with an event, such as an action or cron
# the latest file from a folder will be scped to your server and will copy
# the http location of the that file to your clipboard
#
# Orginally developed to be piped to from compiz screenshot tool
#
#
# The MIT License
#
# Copyright (c) 2010 Tyler Mulligan
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE
#
import pygtk
pygtk.require('2.0')
import gtk
import pynotify
import sys
import os
import subprocess
user = "user"
host = "server.com"
lfolder = "/home/user/screenshots/"
hfolder = "/home/remote_user/screenshots/"
httplink = "http://"+host+"/screenshots/"
timeout = 5000
# Set position
display = gtk.gdk.display_get_default()
screen = display.get_default_screen()
x = screen.get_width() - 1
y = screen.get_height() - 1
#x = 1919
#y = 12
def upload_cb(n, action):
assert action == "upload"
start = os.path.abspath(lfolder)
f = max([(os.path.getmtime(os.path.join(start,x)),x)
for x in os.listdir(start)])[1]
# setup URL in clipboard
clipboard = gtk.clipboard_get()
clipboard.set_text(httplink + f)
# make our data available to other applications
clipboard.store()
os.system('scp "%s" "%s@%s:%s"' % (lfolder + f, user, host, hfolder) ).wait()
n.close()
gtk.main_quit()
def ignore_cb(n, action):
assert action == "ignore"
n.close()
gtk.main_quit()
if __name__ == '__main__':
if not pynotify.init("Notifier 'scp' Option"):
sys.exit(1)
# Setup Popup
n = pynotify.Notification("Upload to Server?")
n.set_urgency(pynotify.URGENCY_NORMAL)
n.set_timeout(timeout)
n.set_category("device")
n.add_action("upload", "Yes, Upload", upload_cb)
n.add_action("ignore", "Ignore", ignore_cb)
# Set position
n.set_hint("x", x)
n.set_hint("y", y)
if not n.show():
print "Failed to send notification"
sys.exit(1)
gtk.main()
edit: I updated the script with some position information — I love that I can put the notifications ANYWHERE on my screen. I also variablized the timeout.
edit 2: Here is a video of my improved script in action — I’ll post the source later
http://interwebninja.com/videos/compiz-screenshot-piped-to-notification-daemon-for-upload.ogv
Going Beyond
The Compiz example is just something that server my immediate needs. The possibilities are however endless. You can for example, link this script to a cron job asking you if you want to sync some other sort of file. Or perhaps you’d like to add multiple buttons to give yourself a folder / server choice.
Happy hacking
Some Issues I found with Dual Monitors in KDE
May 13th
Posted by Tyler Mulligan in Computers
I had originally made a thread on ubuntu forums essentially asking how to change the way kde or more specifically kwin treats dual monitors.
When trying out KDE 4.4, I was trying to establish a similar workflow to what I have in my GNOME/compiz setup. I use dual monitors and heavily use the expo compiz plugin (equivalent to kwin’s ‘desktop grid’). However, the behavior in KDE is a bit odd to me.
(not my video but gives you an idea about the effect, see below for how I lay mine out)
In compiz, I have 4 virtual desktops with dimensions that spanned both monitors.
[ ] | [ ]
In KDE however, each monitor is considered it’s own “activity” and as such, I have 8 virtual desktops
[ ][ ] | [ ][ ] [ ][ ] | [ ][ ]
This in and of itself isn’t all so bad. What bothers me however, is how they behave.
Labeling the virtual desktops..
[1][2] | [1][2] [3][4] | [3][4]
When I click virtual desktop [1] on the left monitor, [1] on the right monitor zooms with it. The behavior I’m used to in compiz would be to have both [1][2] on the left desktop zoom if I were to click [1].
Sure, this behavior “makes sense” knowing how KDE treats multiple monitors as separate activities but even after setting up matching desktop backgrounds on the monitors, I find it confusing to my workflow.
What’s more, is that KDE seems to know this is what I want… but ignores this fact when creating activities:

Has anyone come up with a clever solution to achieve this? I didn’t see anything about it planned for 4.5.
If it matters, I’m using twinview.
Reseting your system wide cursor theme in ubuntu
May 11th
Posted by Tyler Mulligan in Command Line
If you installed KDE in ubuntu (GNOME based), you may have noticed that when you log back into GNOME, you keep the KDE cursor theme. To fix this, use update-alternatives like so:
0025|z@zentury ~$ sudo update-alternatives --config x-cursor-theme There are 7 choices for the alternative x-cursor-theme (providing /usr/share/icons/default/index.theme). Selection Path Priority Status ------------------------------------------------------------ * 0 /etc/X11/cursors/oxy-white.theme 50 auto mode 1 /etc/X11/cursors/core.theme 30 manual mode 2 /etc/X11/cursors/handhelds.theme 20 manual mode 3 /etc/X11/cursors/oxy-white.theme 50 manual mode 4 /etc/X11/cursors/redglass.theme 20 manual mode 5 /etc/X11/cursors/whiteglass.theme 20 manual mode 6 /usr/share/icons/DMZ-Black/cursor.theme 30 manual mode 7 /usr/share/icons/DMZ-White/cursor.theme 50 manual mode Press enter to keep the current choice[*], or type selection number:
press “7″ for the default
[SOLVED] konversation has no window decorations in GNOME and forces fullscreen
May 9th
Posted by Tyler Mulligan in Computers
This was a very annoying bug for me to deal with and it almost caused me to switch to kde 4 earlier than planned. Luckily I was able to pull up a fix which is simple to replicate but was a pain in the arse to solve.
To fix this, go into CompizConfig Settings Manager >> Workarounds >> uncheck “Legacy Fullscreen Support” as the red circle in the screenshot below indicates.
Fastest way to install the media essentials in ubuntu
May 7th
Posted by Tyler Mulligan in Command Line
If you’re coming from Windows, or like me, find yourself living in a live CD while you figure out which step went wrong; you’ll be interested in the essential media codecs, flash, java, Microsoft fonts, etc.
I thought I’d share the way I did this as quickly as possible in in Ubuntu 10.04 using the command line.
Open up terminal, using ctrl+alt+t (Which I’m very happy about as this has been my default since 8.04). Alternativelty from the main menu -> Applications > Accessories > Terminal
Make a backup in case you’re scared, then remove the comments from repositories you need to unlock to access the restricted (proprietary) packages.
ubuntu@ubuntu:~$ sudo cp /etc/apt/sources.list . ubuntu@ubuntu:~$ sudo sed -i 's/^# deb/deb/' /etc/apt/sources.list
We do this be matching the first 2 characters with ‘# ‘ and replacing them with ” (nothing). See the diff below (> indicate original lines, < are changed).
ubuntu@ubuntu:~$ diff sources.list /etc/apt/sources.list 18,23c18,23 < # deb http://archive.ubuntu.com/ubuntu lucid universe < # deb-src http://archive.ubuntu.com/ubuntu lucid universe < # deb http://archive.ubuntu.com/ubuntu lucid-updates universe < # deb-src http://archive.ubuntu.com/ubuntu lucid-updates universe < # deb http://security.ubuntu.com/ubuntu lucid-security universe < # deb-src http://security.ubuntu.com/ubuntu lucid-security universe --- > deb http://archive.ubuntu.com/ubuntu lucid universe > deb-src http://archive.ubuntu.com/ubuntu lucid universe > deb http://archive.ubuntu.com/ubuntu lucid-updates universe > deb-src http://archive.ubuntu.com/ubuntu lucid-updates universe > deb http://security.ubuntu.com/ubuntu lucid-security universe > deb-src http://security.ubuntu.com/ubuntu lucid-security universe 30,35c30,35 < # deb http://archive.ubuntu.com/ubuntu lucid multiverse < # deb-src http://archive.ubuntu.com/ubuntu lucid multiverse < # deb http://archive.ubuntu.com/ubuntu lucid-updates multiverse < # deb-src http://archive.ubuntu.com/ubuntu lucid-updates multiverse < # deb http://security.ubuntu.com/ubuntu lucid-security multiverse < # deb-src http://security.ubuntu.com/ubuntu lucid-security multiverse --- > deb http://archive.ubuntu.com/ubuntu lucid multiverse > deb-src http://archive.ubuntu.com/ubuntu lucid multiverse > deb http://archive.ubuntu.com/ubuntu lucid-updates multiverse > deb-src http://archive.ubuntu.com/ubuntu lucid-updates multiverse > deb http://security.ubuntu.com/ubuntu lucid-security multiverse > deb-src http://security.ubuntu.com/ubuntu lucid-security multiverse > <pre class="brush:bash">
Now that we uncommented these lines, they will be read next time we update, so lets go ahead and do that now. Once that is done, we can install the extras.
ubuntu@ubuntu:~$ sudo apt-get update ubuntu@ubuntu:~$ sudo apt-get install ubuntu-restricted-extras
Rock and roll.
RabbitVCS is the new Nautilus SVN
May 4th
Posted by Tyler Mulligan in Computers
I should have written about this months ago. Readers have replied to my previous post about nautilus svn, which I claimed to be the first that didn’t suck. This is the evolution of it, RabbitVCS (Version Control System), which aims to use the same intuitive, integrated gui for other version control systems, such as git (check the rabbitvcs roadmap for details on expected support for different versioning system.
Packages for nautilus you wish were installed by default in ubuntu
May 4th
Posted by Tyler Mulligan in Application Management
Intro
Thanks to a tip I picked up at Tombuntu about nautilus, after following up on a trick to add files to mocp through nautilus scripts trackback link from Hilltop Yodler (great article), when doing a google search for GiS for nautilus-actions (apt-get install nautilus-actions). I learned about 3 kick ass additions to the nautilus menu. I realized Fedora Linux and Linux Mint had some of these in their context menus but didn’t make the connection to ubuntu until now.
On with the Show
sudo apt-get install nautilus-open-terminal nautilus-image-converter nautilus-gksu
for some kick ass options in the context (right click) menu of nautilus (your default file manager in ubuntu). For more information, check out the tombuntu article I linked above.
pkill nautilus
to restart nautilus and have the new packages in your context menu
More
If you’re interested in this, you’ll probably also like my article about nautilus-actions.
Adding context (right click) menu options to nautilus (Ubuntu's default file manager) with nautilus-actions
May 4th
Posted by Tyler Mulligan in Application Management
Intro
Previously, I had written about enqueuing files with nautilus scripts. Since then, I have learned (and forgotten about) nautilus-actions. Which is a similar way to attack the issue but it using a more intuitive and decoration approach, as well as having the ability to be on the first level of the context menu hierarchy.
sudo apt-get install nautilus-actions nautilus-actions-config
The approach to getting the example of enqueuing files to mocp accomplished is a bit different using this approach as you don’t need to go through the script as you did before (though you can if you want, it’s an unnecessary step). Here, as my screenshot shows, I directly call mocp from /usr/bin with the -a flag and use the $M variable the legend provided me with to pass a list of files and their full paths to mocp.
You’ll also want to change the conditions on the Conditions tab. I set it to allow multiple files from both folders and files. The default is to allow only a single file.
More
This article was inspired by Making Life Easier With Scripts For Nautilus. If you’re interested in this article, you’ll probably also like my article about nautilus packages you wish were installed by default in ubuntu.
If nvidia-settings cannot save to xorg.conf, do this
Feb 11th
Posted by Tyler Mulligan in Freeware
If you’re using ubuntu and having trouble with nvidia-settings saving to the /etc/X11/xorg.conf file, you may find the following tip helpful in relieving that annoyance.
Looking for something interesting when I login to one of my servers, I decided to whip up the following script I appended to my ~/.bashrc file.
close nvidia-settings
in terminal:
sudo mv /etc/X11/xorg.conf /etc/X11/xorg.conf.backup sudo gedit /etc/X11/xorg.conf
paste the following:
Section "Device"
Identifier "Configured Video Device"
Driver "nvidia"
EndSection
save and close.
back to terminal:
sudo nvidia-settings
and save the file.



