Tuesday, January 24, 2012

Opera: Using Firefox style keyboard shortcuts in Opera

Getting sick of Firefox and their stupid rolling releases. Even more so with the speed and memory usage. Switching between browsers hasn't really been a problem for me when it comes to vanilla installs, except for Opera.

What the heck is that Ctrl+K shortcut? Most browsers seem to focus to the search or address controls when it's pressed. Opera on the other hand goes to some weird profiles thing.

To make it more like Firefox:

  • Just open up your Opera browser and click/paste this link.
  • When a dialog shows up asking if you want to use the keyboard layout, click "Yes".

image

  • That's it! New settings already applied.

If you want to go all out and make it look and feel like Firefox, see the source link below.

Source

Wednesday, January 18, 2012

Django: Displaying form errors under a certain field during clean()

For the most part, the forms class works pretty well. Unless you're trying to specify exactly where an error should show up in the clean() function...

If you're using fieldname_clean() methods, then this isn't a problem.

However, during your clean() method you find that it makes more sense to target an error towards a certain field, you can't do it by simply raising a forms.ValidationError.

Luckily, it's still relatively simple to do.

def clean(self):
data = self.cleaned_data

# This error shows up under form.non_field_errors
try:
shirt = Shirt.objects.get(title__iexact = data['title'])
raise forms.ValidationError("A shirt with a similar name already exists.")
except Shirt.DoesNotExist:
pass

# Show an error under the "description" field
self._errors["description"] = self.error_class(forms.ValidationError("error message of your choice).messages)

return data

Now you're able to specify error messages to any field in the form.

xf2srb
<3 Django

Tuesday, January 17, 2012

Windows 7: Downloading Service Pack 1

My my, so many damn files to choose from for SP1.

image

Take a look for yourself!

Files of interest

  • 7601.17514.101119-1850_Update_Sp_Wave1-GRMSP1.1_DVD.iso

The first one contains the whole SP1 she-bang for 32bit, 64bit AMD and 64bit Intel chipsets. It assumes that you're going to be using this DVD multiple times on various machines.

  • windows6.1-KB976932-IA64.exe
  • windows6.1-KB976932-X64.exe
  • windows6.1-KB976932-X86.exe

The last 3 are the specific files for each chipset architecture. This saves you from downloading the packs you don't need.

  • Windows_Win7SP1.7601.17514.101119-1850.AMD64CHK.Symbols.msi
  • Windows_Win7SP1.7601.17514.101119-1850.AMD64FRE.Symbols.msi
  • Windows_Win7SP1.7601.17514.101119-1850.IA64CHK.Symbols.msi
  • Windows_Win7SP1.7601.17514.101119-1850.IA64FRE.Symbols.msi
  • Windows_Win7SP1.7601.17514.101119-1850.X86CHK.Symbols.msi
  • Windows_Win7SP1.7601.17514.101119-1850.X86FRE.Symbols.msi

The ones in between aren't terribly useful for the majority of us. It's for people who want to debug the installation process and stuff like that.

Source

Django: Send email with attachment

Usually send_mail() will suffice for most emailing functionality, but when you need to attach something, the helpful Django wrapper function won't allow it.

If you need to add attachments to your emails, you'll have to go deeper.

image

Alright, down to the nitty gritty.

from django.core.mail.message import EmailMessage

email = EmailMessage()
email.subject = "New shirt submitted"
email.body = html_message
email.from_email = "ThatAwesomeShirt! <no-reply@thatawesomeshirt.com>"
email.to = [ "somefakeaddress@hotmail.com", ]



email.attach_file("hellokitty.jpg") # Attach a file directly

# Or alternatively, if you want to attach the contents directly

file = open("hellokitty.jpg", "rb")
email.attach(filename = "hellokitty.jpg", mimetype = "image/jpeg", content = file.read())
file.close()

email.send()

And that is all folks.

Source

Django docs: Sending email

Disable auto playing video on SMH.com.au (and other Fairfax sites) without logging in

Fuck having to log in to disable autoplay of videos. That shit shouldn't be on unless you turn it on.

DogHumpsCatsHead
It's like being raped in the skull... but given a choice if you want to sign up or not.

This snippet removes the video altogether, but to be honest you don't miss it at all.

These instructions are for Firefox, but are probably similar for other browsers.

  • Install the AdBlockPlus Firefox addon.
  • Tools menu
  • AdBlockPlus
  • Filter Preferences

image

  • Custom Filters
  • Add filter
  • Paste in "smh.com.au,theage.com.au,brisbanetimes.com.au,nationaltimes.com.au,watoday.com.au,domain.com.au##div.cT-imageMultimedia" without quotes
  • Save and close. That's it!

image 

Source

Where Greasemonkey scripts have failed, a big thanks goes to Tim Bennett for posting this tip!

Python: Various ways to sort lists and tuples

I was amazed to how many ways there were to sort lists in Python. Better yet, you DON'T need to create a new function to sort things like you do in PHP.

Basic Sorting

Create a copy of the list

sorted([5, 2, 3, 1, 4])

[1, 2, 3, 4, 5]

Sort and modify the list

This method only works for lists.

a = [5, 2, 3, 1, 4]
a.sort()
a

[1, 2, 3, 4, 5]

Sort by Key

Pyhon 2.4 brings the "key" argument to sorted().

For example, we use the tuple:

student_tuples = [
('john', 'A', 15),
('jane', 'B', 12),
('dave', 'B', 10),
]
sorted(student_tuples, key=lambda student: student[2]) # sort by age

[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]

Or a class:

class Student:
def __init__(self, name, grade, age):
self.name = name
self.grade = grade
self.age = age

student_objects = [
Student('john', 'A', 15),
Student('jane', 'B', 12),
Student('dave', 'B', 10),
]
sorted(student_objects, key=lambda student: student.age) # sort by age

[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]

Sort by key has some helper functions called itemgetter() and attrgetter() which do what the above examples do. It also allows for multiple levels of sorting.

from operator import itemgetter, attrgetter

sorted(student_tuples, key=itemgetter(1,2))
[('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]

sorted(student_objects, key=attrgetter('grade', 'age'))
[('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]

Reverse order

Easy enough, there's a "reverse" argument in sorted() to do that.

sorted(a, reverse = True)

Source

This post was an extract of the things I found helpful from the Python wiki docs. See the link below for more information.

vim: Delete all lines matching a search pattern

A great little command that definitely saves you time!

:g/.*foo.*/d

the "d" at the end is replaceable so you can use other commands if needed.

Source

Thursday, January 12, 2012

Linux: Script to backup files/folders and copy it onto another server

There's no need to glorify how a backup can save the day. If you've been hit by a critical hard drive error, you'll know what I mean.

pgIyE
They don't have a clue how it feels to be hit by a hdd error...

So without further adieu, let's begin.

Setting up automatic access:

Your source machine will need to be able to access the destination machine without requiring a password. Why? It's better than leaving your passwords laying around in the script files.

You'll need to generate the private/public key files and then allow access on the destination machine.

Open up a terminal window and do the following:

  • ssh-keygen -t rsa
  • Press Enter (default file is fine)
  • Press Enter (empty password is how it connects without needing one)
  • Press Enter (confirm empty password)
  • cat ~/.ssh/id_rsa.pub (to display the public key)
  • Copy it to your clipboard

Now to do some preparation on your destination server.

  • Log into your remote server
  • vi .ssh/authorized_keys (to edit your access list)
  • Paste the key from your clipboard into a new line at the bottom of the file
  • Save and exit

Now try "ssh remoteuser@server.com". It should be able to connect without asking for a password.

Preparing the backup script

You'll need a place to store the backups without cluttering up your home folder.

From this point forward, I will be assuming the following:

  • I'll be storing the backup archives in
    ~/backups/
  • The folder I want to back up
    /code/

A little explanation about what's about to happen.

We'll create a script called "backup.sh" which will:

  • compress the contents of /code/ into a TGZ file
  • The TGZ filename will depend on the current date (so you can have multiple archives)
  • When it's done, we use scp to copy the archive over to the remote server.
  • After it's been uploaded, we delete the file from our source machine.
  • Just to do a bit of maintenance cleaning, we'll delete all the old archives on the remote machine apart from the newest 3.

Now to make the script that'll do the magic.

  • "vi backup.sh" to create the script file and open it up. Paste in:
FILE="/home/user/backups/backup_code_`date +%Y.%m.%d`.tgz"
FOLDER="/code/"

tar czf - $FOLDER > $FILE
scp $FILE remoteuser@server.com:~/backups/code/
rm $FILE
ssh remoteuser@server.com '~/bin/clean_backups.sh'
  • "chmod +x backup.sh" to make it executable.
  • Use "cron" to schedule the script. Edit /etc/crontab to schedule the file under YOUR username (default is "root" user). Google the syntax for usage.

Keeping a certain number of backups

"clean_backups.sh" is a script on the remote machine which automatically deletes every backup file apart from the latest 3.

This step is optional, so it's up to you if you want to do it.

On the remote server, create a script in "~/bin/clean_backups.sh" and make it executable.

Paste in:

cd ~/backups/
ls -t backup_code* | sed -e '1,3d' | xargs -d '\n' rm

For testing purposes, replace "rm" at the end with "echo". It'll print out all the files it wants to delete.

Now, if a critical hard drive failure decides to show up in your face... you're ready!

pniyp

Sources

Sunday, January 8, 2012

Android: How to use True Type Fonts (TTF) in your View

The stock fonts provided with Android aren't bad, but if you need to give your app/game a bit more mood then you need some custom fonts.

To embed a custom font into your app, you need to create an "assets/fonts" folder and copy your TTF file there.

In your code:

Typeface font = Typeface.createFromAsset(this.getContext().getAssets(), "fonts/Jokerman.ttf");
TextView tv = (TextView) v.findViewById(res);
tv.setTypeface(font);

zl3c8
Can't get much easier than that!

Source

Android: Displaying items in a listview

Wow, I thought I wrote something about this some time ago but I guess I didn't. Ran into this issue again when writing my Diablo II Runewords app.

image

The ListView isn't exactly the most intuitive thing to pick up and use. It's some clever work, but the whole thing is also a mess of views, adapters and layouts. A by-product of over engineering, probably second worst case after Activities.

friday_gif_collection_151
Over engineering - you only realise when it's too late. 

Overview

A listview needs an "adapter" to hold and understand how to render the information.

Each item you see in a listview is actually another "view". This view is generated and populated by the adapter.

So, you use Listview.setAdapter() to specify which adapter you want to use.

ListView lv = (ListView) findViewById(R.id.lvRunewords);
lv.setAdapter(new RunewordListAdaptor(currentActivity, parser.runewords));

Item Layout

Instead of creating the layout by hand, we just use the layout editor. In this example, create a file called "runeword.xml" and position all the TextViews accordingly.

The Adapter

Ok, it's a lot to digest at the moment but I'll run through it.

public class RunewordListAdaptor extends ArrayAdapter<Runeword> {
public RunewordListAdaptor(Context context, List<Runeword> objects) {
// R.layout.runeword is the layout used for each item.
// R.id.tvRunewordName is the TextView used to display the item text
super(context, R.layout.runeword, R.id.tvRunewordName, objects);
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
Runeword rw = this.getItem(position);
View v;

// Android reuses views where possible.
if (convertView != null) {
v = convertView;
}
else {
// Need to create a new for the new item.
LinearLayout layout = new LinearLayout(parent.getContext());
LayoutInflater layoutInflater = (LayoutInflater) this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
layoutInflater.inflate(R.layout.runeword, layout);

v = layout;
}

// Fill in data onto the layout
((TextView) v.findViewById(R.id.tvRunewordName)).setText(rw.name);
((TextView) v.findViewById(R.id.tvStones)).setText(Rune.listToString(rw.stones));
((TextView) v.findViewById(R.id.tvNotes)).setText(rw.notes);
((TextView) v.findViewById(R.id.tvSockets)).setText(String.valueOf(rw.sockets));

return v;
}
}

In the constructor I just called the base class ArrayAdapter constructor, giving it the name of the layout we want to use (runeword.xml) and the id of the target TextView containing the item label (R.id.tvRunewordName).

In getView(), sometimes convertView will be given to us. This is Android's way to saving us the computational time of recreating the layout for each item.

If it needs to be created, simply inflate the layout into a view we can use.

The rest of the code is just spent filling in data from the Runeword object.

Return the view when done.

PsvJe

It's clunky, seems inefficient but it works!

Built-in Adapters

There are a few built-in adapters you can use and in this instance I used the ArrayAdapter. To see what works best for you, see the ListAdapter documentation.

Source