Facebook: Update your account recovery information for additional security

I remember seeing a link to this before, but Facebook decided to make it one of those random links that shows up once or twice and never appears again.

Click below to configure alternate emails in case your primary email gets hacked, security questions and mobile number.

image

uTorrent: How to fix the disgusting user interface changes in uTorrent 2.2

image 
Look at that shit! Just look at it.

Here I am, updating my uTorrent to v2.2 in blind trust because in the past, their updates have always been awesome.

Not this time. They've fucked the UI and joined the app bandwagon. The fuck is this shit? For Christ sake, it isn't a mobile phone! Why the hell do I need apps to play games on uTorrent?

This update was a gigantic waste of time. Time which they could have spent making progress on the 97+ page bug tracker.

Looking through the first page of the forums, there was no problem finding other people who were even angrier than me about it!

Anyway, I'm glad they took the time to make a skin for us that brought back the v2.04 theme icons. It was posted on the release information.

  • Download the skin and save it on your computer.
  • Open up the uTorrent window
  • Drag the skin file into your uTorrent window
  • The skin should apply immediately

image
Beautiful again.

The progress bars are still retarded, but that can be changed in the advanced settings in preferences. Change "gui.color_progressbars" to false.

Please uTorrent, I've always advocated your use but don't do anything stupid like this again.

Sources

Python: How to generate a random string with letters and numbers

This is probably one of the shortest and simplest implementations I've seen in any language. Nice work MasterPi !

import string
import random

"".join([random.choice(string.letters+string.digits) for x in range(1, desired_length)])

[ Source ]

Git: Do a "git status" on each submodule using foreach

Strangely enough, its fine doing a git branch on each submodule using "git submodule foreach git branch".

However, if you try "git status" it wont be happy. It'll spit out this error after the first submodule.

Stopping at 'firstmodule'; script returned non-zero status.

Instead, use:

git submodule foreach "git status || true"

This will go through each submodule and perform a status, without any errors.

Now go forth and celebrate your success!

wvrex2

Android: How to parse an XML string

There are quite a few examples on how to parse XML from a resource or InputStream, however only a handful will show you how to parse a String in XML format.

Luckily, the method is very similar to most of the other examples as you still need to use a SAX ContentHandler.

Consider the example XML file:

<?xml version="1.0" encoding="UTF-8"?>
<scoreboard lastUpdated="1292447376" version="1.0">
<highscores players="8579">
<score points="587" player="twig" when="1292447376"></score>
<score points="447" player="sheik" when="1292437376"></score>
<score points="396" player="tux" when="129242000"></score>
<score points="276" player="nunkii" when="129241000"></score>
<score points="187" player="Anonymous" when="129240000"></score>
</highscores>
<scores submitted="50">
<score points="587" player="twig" when="1292447376"></score>
<score points="104" player="twig" when="1292447370"></score>
<score points="103" player="twig" when="1292447360"></score>
<score points="50" player="twig" when="1292447350"></score>
<score points="20" player="twig" when="1292447340"></score>
</scores>
</scoreboard>

Once you've got your XML string, parse it using:

ContentHandler parser = new ScoreboardXmlParser();
Xml.parse(strXML, parser);

Scoreboard sb = parser.scoreboard;

Now for the ContentHandler class. The main functions to implement are:

  • startDocument(): You can use this to initialise any lists to store data.
  • endDocument(): To know when you've finished parsing and clean up after yourself.
  • startElement(): When the parser reaches a new element. You can also access the element attributes here.
  • endElement(): When the element is done with the current element and ready to move onto the next.

Everything else you can leave empty.

This is the complete class.

import java.util.ArrayList;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;

public class ScoreboardXmlParser implements ContentHandler {
private long lastUpdated;
private int totalPlayers;
private int totalSubmissionsFromPlayer;
private ArrayList<Score> highScores;
private ArrayList<Score> playerScores;
private ArrayList<Score> m_currentList;
public Scoreboard scoreboard;

@Override
public void startDocument() throws SAXException {
highScores = new ArrayList<Score>();
playerScores = new ArrayList<Score>();
lastUpdated = 0;
totalPlayers = 0;
totalSubmissionsFromPlayer = 0;
}

@Override
public void endDocument() throws SAXException {
scoreboard = new Scoreboard();
scoreboard.lastUpdated = lastUpdated;
scoreboard.totalPlayers = totalPlayers;
scoreboard.totalSubmissionsFromPlayer = totalSubmissionsFromPlayer;
scoreboard.highScores = new ArrayList<Score>(highScores);
scoreboard.playerScores = new ArrayList<Score>(playerScores);
}

@Override
public void startElement(String uri, String localName, String name, Attributes atts) throws SAXException {
if (localName.equals("scoreboard")) {
lastUpdated = Long.parseLong(atts.getValue("lastUpdated"));
}
else if (localName.equals("highscores")) {
totalPlayers = Integer.parseInt(atts.getValue("players"));
m_currentList = highScores;
}
else if (localName.equals("scores")) {
totalSubmissionsFromPlayer = Integer.parseInt(atts.getValue("submitted"));
m_currentList = playerScores;
}

if (localName.equals("score")) {
m_currentList.add(new Score(atts));
}
}

@Override
public void endElement(String uri, String localName, String name) throws SAXException {
if (localName.equals("highscores") || (localName.equals("scores"))) {
m_currentList = null;
}
}
}

A little trick here is that both "highscores" and "scores" lists contain an element called "score". I used "m_currentList" to keep track of which list the scores should be added to. Once the parser is finished with either "highscores" or "scores", the list is set back to null.

When the document ends, I just store all the information into into a Scoreboard object. You don't have to do this, but it was just an example to show you what you can do at the end of the parsing.

You should also implement a custom function such as isParsed() to check if the data was parsed correctly or not.

Sources:

Android: Use tabs in your view without XML layout files and TabActivity class

The Android framework has been pretty good to work with so far, until I tried to add a tab widget onto my view. Bloody hell that was fussy!

I'm not particularly fond of using the WYSIWYG editor for the user interface,

All these weird errors were thrown around were due to some expectations within the TabHost and TabWidget classes.

I'll try to explain what I can remember.

// This simple class just extends the LinearLayout and adds a Tab widget with 2 listviews, each in its own tab.
public class ScoreScreen extends LinearLayout {
private TabHost host;
private TabWidget widget;

public ScoreScreenView(Context context, final Scoreboard scoreboard) {
super(context);

this.setOrientation(VERTICAL);

// Set up the tab widget and put in onto the view
TabSpec tab;

host = new TabHost(context);
host.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));

widget = new TabWidget(context);
widget.setId(android.R.id.tabs);
host.addView(widget, new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));

// the TabHost needs a frame layout for the views on the tab
FrameLayout frame = new FrameLayout(context);
frame.setId(android.R.id.tabcontent);
host.addView(frame, new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));

host.setup(); // Magic function that initialises everything

// Start adding tabs
tab = host.newTabSpec("High Scores").setIndicator("High Scores").setContent(new TabContentFactory() {
@Override
public View createTabContent(String tag) {
ListView lv = new ListView(context);

lv.setAdapter(new ScoreAdaptor(scoreboard.highScores));
return lv;
}
});
host.addTab(tab);

tab = host.newTabSpec("Your Scores").setIndicator("Your Scores").setContent(new TabContentFactory() {
@Override
public View createTabContent(String tag) {
ListView lv = new ListView(context);

lv.setAdapter(new ScoreAdaptor(scoreboard.playerScores));
return lv;
}
});

host.addTab(tab);

// Add the tab to the layout
this.addView(host);

// Set the padding for the frame so the content doesn't cover the tabs
int tabHeight = host.getTabWidget().getChildAt(host.getTabWidget().getChildCount() -1).getLayoutParams().height;
frame.setPadding(0, tabHeight, 0, 0);
}
}

Now I guess we can both go back to doing whatever we were doing...

americapantsp1

Sources

Most of the setup magic cames from PocketMagic.

The code to set the proper non-hardcoded tab height came from StackOverflow.

Android: mBaselineAlignedChildIndex of LinearLayout set to an index that is out of bounds

There are some really whack error messages, and then theres this:

java.lang.RuntimeException: mBaselineAlignedChildIndex of LinearLayout set to an index that is out of bounds"

In laymens terms, all you really need to do is actually add some children to the LinearLayout.

[ Source ]

Android: Set HTTP socket timeout

The default timeout value for a HTTP request is quite long. So long that you'd forget what you were doing and wonder why the game has crashed.

Reduce the timeout value to get more responsiveness out of your app.

HttpParams httpParameters = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParameters, 5000); // Connection timeout
HttpConnectionParams.setSoTimeout(httpParameters, 3000); // Socket timeout

// Create a new HttpClient and Post Header
HttpClient httpclient = new DefaultHttpClient(httpParameters);

Now you can use the HttpClient as per usual for GET or POST requests.

[ Source ]

Android: Close the virtual "on-screen" keyboard

There was a slight quirk that I ran into while working on my app. If I were editing text and clicked "Save" on the activity, it'd close the screen but keep the keyboard open.

I'd then have to press the BACK button to close it. A small but somewhat irritating quirk. Luckily, its an easy thing to fix.

First, define an "OnFocusChangeListener":

private OnFocusChangeListener hideKeyboard = new OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
InputMethodManager imm = (InputMethodManager) v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
}
}
};

When you're creating and setting up your edit boxes, just set the following listeners:

txtEmail.setOnFocusChangeListener(hideKeyboard);
txtUsername.setOnFocusChangeListener(hideKeyboard);

There you have it. It should now hide the keyboard automatically.

If no other objects take focus, then just call the listener manually.

hideKeyboard.onFocusChange(txtUsername, false);
hideKeyboard.onFocusChange(txtEmail, false);

[ Source ]

Apache: Run a Django project using mod_wsgi and .htaccess

To get Django up and running under your Apache configuration, you'll need to install mod_wsgi first. This will let Apache run Python code.

Assuming your files are in the format of:

image

For this example, the "forum" folder is the subdomain (http://forum.example.com) and the "forum_project" should be your Django project folder (containing manage.py, settings.py, etc).

In your subdomain folder, create a file called "dispatch.wsgi". This file will tell Apache what to do with the incoming request. In that file, paste:

import os, sys

sys.path.append("/home/twig/public_html/forum/forum_project");

# This refers to the "settings.py" file in forum_project
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'

#import django.core.handlers.wsgi
#application = django.core.handlers.wsgi.WSGIHandler()

def application(environ, start_response):
"""Simplest possible application object"""
output = "Hello World"
status = '200 OK'
response_headers = [('Content-type', 'text/plain'), ('Content-Length', str(len(output)))]
start_response(status, response_headers)
return [output]

Now to create a file called ".htaccess", which will funnel all the URLs into dispatch.wsgi.

RewriteEngine On
RewriteBase /
RewriteRule ^(media/.*)$ - [L]
RewriteRule ^(admin_media/.*)$ - [L]
RewriteRule ^(dispatch\.wsgi/.*)$ - [L]
RewriteRule ^(.*)$ slowpoke/dispatch.wsgi/$1 [QSA,PT,L]

Lastly, add a few lines in your domain's vhost file so it knows to use Python and WSGI for requests.

<IfModule mod_wsgi.c>
WSGIScriptAlias / /home/twig/public_html/forum/dispatch.wsgi
WSGIDaemonProcess myapp processes=5 threads=1 display-name=%{GROUP}
WSGIProcessGroup myapp
WSGIApplicationGroup %{GLOBAL}
</IfModule>

Time to test the server. Open up the browser and point it to your domain. It should display "Hello world". If not, check your error logs. A useful guide to debugging WSGI errors is available on the mod_wsgi documentation pages.

Once its up and running, uncomment the Django wsgi code and delete the application() function from dispatch.wsgi. Your code should now look like this.

import os, sys

sys.path.append("/home/twig/public_html/forum/forum_project");

# This refers to the "settings.py" file in forum_project
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'

import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()

That should be enough to get your project up and running with Apache, Django and mod_wsgi.

See here to serve CSS/JS/image files out of Django. For anything else Django related see here.

Sources

Linux: Log into a server using SSH without entering password

One of those little handy-things-to-have is the ability to log into a remote computer without having to enter in the password every time.

To do that, we have to generate a pair of authentication keys for the computers A and B.

On computer A, make sure you have a folder called ".ssh". If not, create it.

  • Type in "ssh-keygen -t rsa"
  • Save it to "~/.ssh/id_rsa"
  • Don't enter in a passphrase (just press enter)
  • Open ".ssh/id_rsa.pub" and copy the contents.

Now on computer B, create a folder called ".ssh" (if it doesn't already exist).

Create "~/.ssh/authorized_keys" and paste in the contents of id_rsa.pub. Save and exit.

Now you should be able to connect from computer A to B without any problems.

[ Source ]

Android: MediaPlayer stops playing sounds and AudioFlinger starts throwing "no more track names availlable"

This error occurs when you've created too many MediaPlayer instances without cleaning up your own filthy mess.

AudioFlinger: no more track names availlable
AudioTrack: AudioFlinger could not create track, status: -12
AudioSink: Unable to create audio track
VorbisPlayer: mAudioSink open failed

Instead, you should either reuse MediaPlayer instances or use the SoundPool class.

Note: The strange way of spelling "availlable" is a typo in the framework.

Reuse MediaPlayer

If you want to reuse the MediaPlayer, just remember to clean up after yourself and call MediaPlayer.release() after you're done.

Otherwise, dedicate one MediaPlayer instance to each sound effect and reuse it each time you play that specific sound.

Use SoundPool

This class manages multiple sounds for you, so you can set the maximum number of channels. It also handles stuff like left/right speaker volume, pausing, stopping, etc.

The annoying thing however is that it returns its own "Sound ID", which you have to keep track of. You get the new sound ID after you've loaded it up.

I've written a small class which uses a HashMap to keep track of them.

public class Sound {
private SoundPool m_soundPool;
private HashMap<Integer, Integer> m_soundIDs;

public Sound() {
int[] sounds = { R.raw.menu, R.raw.dizzy, R.raw.pokewrong, R.raw.go, R.raw.ready, R.raw.win, R.raw.music, };

m_soundIDs = new HashMap<Integer, Integer>();
m_soundPool = new SoundPool(8, AudioManager.STREAM_MUSIC, 0);

for (int sfx : sounds) {
m_soundIDs.put(sfx, m_soundPool.load(G.activity, sfx, 1));
}

}

public void play(int resid) {
if (!G.settings.sfx) {
return;
}

m_soundPool.play(m_soundIDs.get(resid), 1.0f, 1.0f, 1, 0, 1.0f);
}

Using this class, all you really have to pass in to play the sound is the resource ID.

Sources

Android: Disable camera sound

This is the most "stock" way of disabling the camera sound. The easiest way by far is to just download a camera app which takes photos silently.

I quite like the app which comes with my Samsung Galaxy S, so I figured I'd keep using it and just change the settings instead.

First of all, you need a rooted phone for this to work.

Second, you'll need "adb.exe" to manage the files.

If you're running Linux as your operating system, you can just mount the system drive and just access it as normal.

Disabling the camera click

  • To copy "default.prop" to your computer, type in: "adb pull /system/default.prop"
  • Now edit the file and search for "ro.camera.sound.forced"
  • If it exists, change it to 0.
  • Otherwise, add this to the file: "ro.camera.sound.forced=0", and remember to leave a blank line at the end
  • Save the file
  • Now copy the file back onto the phone using "adb push default.prop /sdcard/"
  • Connect to the phone: "adb shell"
  • Type in "su" to gain super user access.
  • Type in "cat /sdcard/default.prop > /system/default.prop" to replace your system settings
  • Optionally you can clean up by deleting "default.prop" from your computer and phone "/sdcard" directory.

Some extra reading

The magic line in this method is the "cat" method. Using the usual "mv" command to move files will fail with the error "Cross-device link" as Unix will not allow you to move files mv from device to device. Kudos to darkxsun from androidforums for that one!

Sources

Samsung Galaxy S: Wifi no longer detects any networks and unable to scan networks

My Samsung Galaxy S decided to chuck a hissy fit and ignore WiFi networks. I believe it's because I entered in a blank password with the WP2 encryption method.

The WiFi mode comes on temporarily to scan, decides it can't, displays an error message then turns off by itself. Sadly, to fix this problem you have two options.

Factory reset

The first is to do a factory reset. I personally think this sucks because I customise a great portion of the phone to maximise battery life.

Rooted access?

The second is to root the phone and delete the existing WiFi settings.

  • Root your phone
  • Move or rename "/sdcard/data/wifi/bcm_supp.conf"

To move or rename, you can use "adb shell" and request superuser access with the "su" command.

Another way is to use a file explorer such as ASTRO file explorer which can be downloaded from the market place.

Once the file is removed, just do a WiFi scan again and it should work.

Happy go lucky?

According to skeerthy who posted in the second source link on androidforums.com, he was able to remove the file using "ddms.bat". Search for "SOLUTION - WITHOUT ROOTING" to find his post.

I didn't have any luck with that because the phone would not let me browse the "data" directory.

Sources

Android: Root your phone safely without modifying any files

When I first wanted to root the phone, I got alot of results pointing me to TGA_Gunnman's method of rooting. This method uses the Android's system recovery method with "update.zip" to replace files and run a script which modifies some settings.

I personally found it cumbersome and it didn't work on my Samsung Galaxy S GT-i9000 (running Eclaire 2.1-update1 with Canadian firmware I9000UG JH2).

What's worse is that it required the .NET 4 framework to run a stupid user interface (that doesn't actually load, even with the damn .NOT framework installed!). In the end, all you really had to do is run the root.bat file (for Android 2.1).

  • Wasted time installing .NET framework 4 because the stupid program doesn't work anyway
  • Wasted time figuring out what script file to use
  • Wasted time trying to remove the files it installed
  • Wasted time because it didn't even work!

The solution

To get RyanZA's z4root working on your phone, first check to see if its supported. At time of writing, the list of phones supported by v1.3.0 are:

  • (permanently root)
    • Samsung Galaxy S (All variants)
    • Backflip
    • Sony X10
    • Xperia Mini
    • Droid 2
    • Galaxy Tab
    • Galaxy I5700
    • Galaxy 3 I5800
    • Droid X
    • Samsung Acclaim
    • Cricket Huawei Ascend
    • Motorola Cliq
    • Huawei 8120
    • Hero
    • G1
    • Optimus T
    • Droid 1
    • Garmin Asus A50
    • Motorola Defy
    • LG Ally
    • Motorola Flipside
    • Motorola Milestone 2
    • Dell streak
    • X10 Mini Pro
    • Smartq v7 android 2.

 

  • (temporary root only)
    • Desire (requires nand unlock)
    • Desire HD (requires nand unlock)
    • Magic (unknown)
    • Evo (requires nand unlock)
    • G2 (requires nand unlock)
    • Archos 70 (unknown)
    • myTouch 3G (unknown)
    • Wildfire
    • Droid Incredible

Procedure

Firstly, you need to register to download the latest release from the official thread. If you're ok with downloading from an unofficial source then I'm probably not able to help you if something goes wrong.

Now copy the file onto your phone somehow. You've got 3 options.

  • Using a memory card
    If your phone supports it, just copy the file onto the SD card.
  • Using adb.exe to push it:
    This uses the debugger to copy the file directly onto the phone. I'm assuming you have it installed somewhere. Open up a command prompt and type in:

adb push z4root.1.3.0.apk /sdcard/

  • Using a file explorer
    You'll have to download a file explorer type app from the app market. Most people seem to recommend ASTRO file explorer, but I've personally never used it.

Once the file is on your phone, click it to install it.

Open the "z4root" app and click on the rooting method of your choice.

So painless compared to the other methods, especially without all the brick-anxiety that comes with the whole recovery mode updates.

[ Source ]

Android: Recovery mode stuck on "Installing muti-csc"

A super noob mistake on my behalf, but I've seen a few posts on this issue.

If your phone is stuck in recovery mode and all it says is "Installing muti-csc" and the "reboot system now" option is highlighted, simply select the "apply sdcard:update.zip" option using the volume buttons and select with your select button.

image 

Once you do that, it'll start updating :)

django: Remove ugly "Thank you for your comment" message after posting comments

Django comments are really really easy to use, but one of the strangest quirks is that it displays a really ugly confirmation page after you've posted a comment. Luckily, its easy to fix.

image The first option is to prevent it from being shown altogether.

{% with your_object.get_absolute_url as next %}
{% render_comment_form for your_object %}
{% endwith %}

The second is to override the "content" block with a custom "comments/posted.html" file. That way you can fill it up with all sorts of silly messages.

  • Create "your_project/templates/comments/posted.html"
  • In it, put:

{% extends "your_base_file.html" %}

{% block content %}This is another silly message.{% endblock content %}

This way, you can still get your site's look and feel when displaying the thank you message.

Python: Define a static function in a class

Most functions in a class will refer to a "self" instance.

If you want a static function, you'll have to add the @staticmethod decorator.

class Something(object):
@staticmethod
def get_by_name(name):
return "Hello world"

[ Source ]

Android: Save and load settings

Its always good when an application remembers the last settings you've used. To add that functionality within your app, just add this class to your project.

/**
* This class is responsible for storing and loading the last used settings for the application.
*
* @author twig
*/
public class Settings {
public boolean music = true;
public boolean sfx = true;
public int games_played = 0;
public int high_score = 0;

public Settings() {
this.loadSettings();
}

public void loadSettings() {
SharedPreferences settings = G.activity.getPreferences(Activity.MODE_PRIVATE);

this.music = settings.getBoolean("music", this.music);
this.sfx = settings.getBoolean("sfx", this.sfx);
this.games_played = settings.getInt("games_played", this.games_played);
this.high_score = settings.getInt("high_score", this.high_score);
}

public void saveSettings() {
SharedPreferences settings = G.activity.getPreferences(Activity.MODE_PRIVATE);
SharedPreferences.Editor editor = settings.edit();

editor.putBoolean("music", this.music);
editor.putBoolean("sfx", this.sfx);
editor.putInt("games_played", this.games_played);
editor.putInt("high_score", this.high_score);

editor.commit();
}
}

When you create an instance of it, it'll automatically load up the old settings and the set defaults if it can't find it.

Remember, you'll still have to save when the application exits!

/**
* Activity is stopped by Android OS.
*/
@Override
protected void onStop(){
super.onStop();

G.savePreferences();
}

Android: Center a button or view horizontally but have a margin offset from the top of the layout

For the title screen, I wanted something that used the layout system without hard-coding pixel values.

Ideally, it'd look like this.

image

I needed this to work using the code rather than layout editor, as the editor only allowed me to enter in fixed pixel values for the margin offset.

The red area had to be approximately 45% of the screen, and the rest would be dedicated to the buttons.

The blue areas are just spacing, evenly distributed between the buttons which have a width which is content wrapped.

Using the linear layout, I was able to get this working via the code.

private void addButtons() {
LayoutParams lp; // Instance of LinearLayout.LayoutParams

lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
lp.gravity = Gravity.CENTER_HORIZONTAL;
lp.topMargin = (int) (G.screenH * 0.45);
this.addView(btnPlay, lp); // This uses its own one to be displayed half-screen

lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
lp.gravity = Gravity.CENTER_HORIZONTAL;
lp.topMargin = 5;
this.addView(btnSettings, lp);
this.addView(btnScores, lp);
this.addView(btnAbout, lp);
this.addView(btnExit, lp);
}

The first button needs its own layout parameter, as it has a different offset to the others. The other buttons are separated by a 5 pixel gap.

It'd be a good idea to make that gap a density independant pixel size by converting it first.

Android: Convert pixel (dip) to density dependent pixel (ddp) size

For Android, one of the biggest problems is the wide variety of screen resolutions. What's worse is that the resolution is only one of three possible problems with positioning.

There is also screen size (the physical screen size such as 4.3") and pixel density (the number of pixels in a physical measurement such as CM or inches).

Starting from Android 1.6, this was simplified a great deal. The official documentation for supporting multiple screens can explain this MUCH better than I ever can here, so have a read of it.

Using this snippet, you can convert a hard-coded pixel value to something that is more relevant on the screen.

/**
* Converts the density independant pixel size to a density dependant pixel size.
*
* @param dip The intended pixel size.
* @return int The converted density dependant pixel size.
*/
public static int convertDensityPixel(int dip) {
return (int) (dip * yourActivity.getResources().getDisplayMetrics().density);
}

[ Source ]

Android: Remove titlebar and make your app completely fullscreen

If you're not entirely fond of the WYSIWIG layout creator and prefer to do things with code, use the following snippet to make the app full screen.

public class SlowPokeActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

// Make it completely full screen
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
}

Android: Animate between views

One of the strengths of the iPhone user interface is that things gel together very well. If you click into something, it'll slide or move about to give you an idea of what the app is doing.

Android can do it too, so don't let your app be thought of as an inferior product because of something like that.

To animate between views, you'll need to be using a layout on your Activity. This layout will remain on your activity as the base on which every other view will sit upon.

public class YourActivity extends Activity {
@Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

Animation animation;
View viewLoading = new NowLoadingView();

// Set up the view animator
m_viewAnimator = new ViewAnimator(this);
m_viewAnimator.setAnimateFirstView(true);

animation = new AlphaAnimation(0.0f, 1.0f);
animation.setDuration(2000);
m_viewAnimator.setInAnimation(animation);

animation = new AlphaAnimation(1.0f, 0.0f);
animation.setDuration(2000);
m_viewAnimator.setOutAnimation(animation);

this.setContentView(m_viewAnimator);

m_viewAnimator.removeAllViews();
m_viewAnimator.addView(viewLoading);

This will now fade in your "loading" view. When its time to change the view, simply remove everything and then add the next one. This will automatically fade out the old and fade in the new.

m_viewAnimator.removeAllViews();
m_viewAnimator.addView(new TitleScreenView());

You can use any transition you wish, just take a look through the docs for animations which suit your use case.

An example of using the TranslateAnimation to slide in from the right is below:

Animation animation;

animation = new TranslateAnimation(
Animation.RELATIVE_TO_SELF, 1.0f, Animation.RELATIVE_TO_SELF, 0.0f,
Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f
);

animation.setDuration(400);

Have fun!

Android: Capture the BACK button keypress and display a confirmation dialog

An often useful feature to have is the "Are you sure you wish to exit?" confirmation as someone may accidently touch the back button and exit your application.

To add that, we need to first override onKeyDown() in the application and detect the BACK button keypress.

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
//Handle the back button
if (keyCode == KeyEvent.KEYCODE_BACK) {
//Ask the user if they want to quit
new AlertDialog.Builder(this)
.setIcon(android.R.drawable.ic_dialog_alert)
.setTitle("Exit")
.setMessage("Are you sure you want to leave?")
.setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which){
// Exit the activity
YourActivity.this.finish();
}
})
.show();

// Say that we've consumed the event
return true;
}

return super.onKeyDown(keyCode, event);
}

A word of warning, in Android 2.0 there is a handler purely for the back button called onBackPressed().

[ Source, Docs, onBackPressed() ]

Android: How to stop and exit your application

Normally the "back" button will exit your application, but if you wanted to put that functionality into an "exit" button, then you'll need to call YourActivity.finish().

*update 21/02/2011*
Just keep in mind that this will mark an activity as "ready to be cleaned up" by the OS.
It will not immediately clean it up, so don't worry when you see the activity reside in the emulator for a bit longer.

django: Dump model instances to fixtures

Fixtures are handy when setting up a new copy of your site, but writing them by hand is an absolute pain!

Luckily, the folks at django have saved us yet again.

This little command allows us to select exactly which objects to export, but also how to format it.

from django.core import serializers
from yourapp.models import YourModel

data = serializers.serialize("json", YourModel.objects.all(), indent = 4)

file = open("initial_data.json", 'w')
file.write(data)
file.close()

This will run through and serialise the objects you pass. Just write "data" into the JSON file of your choice!

*update 20/01/2011* Added 3 lines to write the data to a file

[ Source ]

django: custom Feed takes exactly 1 argument (0 given)

It's one of those silly brain fart moments which takes a while to figure out.

I kept getting this error and kept fiddling with argument variables, trying to get it working.

Luckily, I didn't mess up too much before I realised that I was declaring the feed incorrectly.

I noticed that I had it set as a function using "def", rather than a "class" which it should be.

image

Windows: Disable video thumbnails for specific filetypes without losing media summary tab or tooltips

I got sick of video files being locked when I was moving stuff around. The reason they were being locked is that Windows Explorer would open up the file to create a thumbnail while I was browsing without releasing the handle properly.

Normally I'd use Process Explorer to unlock it, but this was happening far too often in a day to put up with.

If you want to disable thumbnails for videos, many sites will tell you to use this command:

regsvr32 /u shmedia.dll

Well that works fine, but you also give up the ability to view ID3 tags on MP3 files and other audio/video formats.

I wanted to keep this functionality, so I had to use another method.

  • Open up RegEdit
  • Navigate to "HKEY_CLASSES_ROOT\.avi\ShellEx"
  • Expand the path and check the default value.

Now for the tricky bit. If the default value is "{c5a40261-cd64-4ccf-84cb-c394da41d590}", then feel free to change it to an empty string (by deleting the text and clicking OK).

Otherwise, copy the value and go to "HKEY_CLASSES_ROOT\CLSID\{your-key-value}\InProcServer32". For me, it was "HKEY_CLASSES_ROOT\CLSID\{c5a40261-cd64-4ccf-84cb-c394da41d590}\InProcServer32".

If the default value has "shmedia.dll" in it, then feel free to go back to the .avi key and delete your key from the default value.

Now, no more thumbnails for just AVI files. You can perform this for other filetypes and the method would remain the same.

Songbird: Stop files from syncing into root folder

Songbird has been a great piece of software for syncing music onto multiple devices.

However, it shits me to no end when I put in a new device and it syncs the files into the root folder, making an absolute mess and mixing all the (potentially) system folders up with lots of music folders.

If this has happened to you already, I'm sorry but you'll just have to manually dig through and move them yourself.

To prevent it from misbehaving like that, simply make a folder called "Music" in the root folder before syncing.

This will be used instead of the root folder.

Sources

Removing "Security Tools" virus/trojan/malware

image

Don't believe anything this trojan says. It's a dirty, filthy little piece of scamware and every threat its reporting is a lie. Security Tools should just report itself and get it over and done with.

It will block most applications from running, so you'll need to somehow get Task Manager up and running before it starts.

Some people use safe mode, others have reported that "CTRL + ALT + DEL" works and can open up the Task Manager without it complaining. If not, try "CTRL + SHIFT + ESC", which does the same thing.

If that doesn't work, you'll have to create a shortcut to "taskmgr.exe" and move it into your "Start Menu > Startup" folder by dragging it with the mouse. Reboot your computer to get access to Task Manager.

Once you have Task Manager up and running, look under "Processes" and close off any program which has all numbers for the filename.

After killing off the pesky little bugger, we're now able to run new programs without any problems.

Run "services.msc" from "Start > Run". Find the following services and then stop and disable each one:

  • Browser Defender Update Service
  • PC Tools Auxiliary Service
  • PC Tools Security Service

Download MalwareBytes Anti-Malware to scan, unlock the files in use and remove the Security Tool Virus. While it scans, we can do some manual removal.

Now go to "Start > Run" again to load up "msconfig". Go to "Startup" tab and disable anything that is within the "Spyware Doctor" folder (or anything that looks suspicious). For me it was "ISTray".

Now open up the following folders and move as much junk out of there as you can. Skip the files that are locked.

  • C:\Program Files\Spyware Doctor
  • C:\Program Files\Common Files\PC Tools
  • C:\ProgramData\PC Tools

Open up "Start > Run" and fire up "regedit". Go to and delete the following registry keys:

  • HKEY_CURRENT_USER\Software\Security Tool
  • HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Browser Defender_is1
  • HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Spyware Doctor

Now the easier part. Search through the registry for anything containing "Spyware Doctor". I've made a list of the items I've found but they may vary from computer to computer.

Best bet is to just do the scan manually.

  • HKEY_CLASSES_ROOT\CLSID\{472734EA-242A-422B-ADF8-83D1E48CC825}
  • HKEY_CLASSES_ROOT\CLSID\{70F8E90E-353A-47AB-B297-C576345EE693}
  • (there was another one here that I forgot to copy before deleting)
  • HKEY_CLASSES_ROOT\CLSID\{F94D9C45-A227-4173-8AC3-6D276B288D9A}
  • HKEY_CLASSES_ROOT\TypeLib\{175B7885-28AB-4D18-8773-7A13A99980A4}
  • HKEY_LOCAL_MACHINE\SOFTWARE\PCTools
  • HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\Browser Defender Update Service
  • HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\sdAuxService
  • HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\sdCoreService
  • HKEY_LOCAL_MACHINE\SYSTEM\ControlSet003\Services\Browser Defender Update Service
  • HKEY_LOCAL_MACHINE\SYSTEM\ControlSet003\Services\sdAuxService
  • HKEY_LOCAL_MACHINE\SYSTEM\ControlSet003\Services\sdCoreService

Now hopefully you've learnt your lesson and started to use a proper antivirus.

Every infected machine I look at is running one of the following 3 security suites; McAfee, Norton or Sophos. Goes to show (again) that they're fucking shit and not worth paying for.

Django: Capture blocks of template data and apply filters

The ability for Django to spit data out to the template so easily using tags and filters is really one of its strengths.

However, if you need to alter the output of some tags and they don't support an option to store the data as a context variable, things might get a little hairy.

Luckily, there is an easy way to apply filters to that data and its even built into the framework.

Use the "filter" tag to apply one or more filters to the data.

<a href="/do/something/here?url={% filter urlencode %}
{% url video-feed '' %}pubid;{{ article.source_publication.pubid }};id;{{ article.id }}
{% endfilter %}&ampid=42" target="_blank">hello</a>

This will apply the urlencode filter to the output URL only, and the rest of the URL will remain untouched.

You can also chain the filters as you do normally, so there isn't a need to nest the filter tags.

{% filter force_escape|lower %}

If you're looking for a way to capture the actual template output to a variable, then use the captureas template tag.

What information does Google have about me?

After signing into my Google account on my Android phone, I quickly realised how much information Google had stored on my activities online and how much it actually sync'd into my phone.

For example; Google Talk, Gmail, Picasa albums, calendar, Google Docs, AdSense, Analytics, blogspot, YouTube, Google Map locations, Google Buzz, Google Reader, Feed Burner and whatever else linked to my Google account.

Feeling a little creeped out, I stumbled upon Google Dashboard, which lets you see all the data they have on you and your digital life.

Android: Disable internet/3G connection to save battery

It's nice to be connected all the time, but when it comes to portable devices I'm quite a frugal user because of battery life. I also don't have any quota allowance on my plan.

So one of the first things I noticed was the 3G symbol was always showing (and annoying me).

The App

Luckily, there was a very handy app on the Android market called "APN on/off Widget". Once installed, edit your dashboard and add the new widget.

image

It'll give you access to a new widget on your dashboard which will enable and disable your internet connectivity. The widget itself will update to reflect the current state of your connection.

This makes it so much easier to turn it on when you need it and then back off once you're done.

The Settings

Apparently this is an Android code, so give it a shot and see if it works.

  • In the phone dialer, enter *#*#4636#*#*
  • It should take you to a new screen
  • Select "Phone Information"
  • Press Menu
  • Press More
  • Select "Disable data on boot" to stop it from automatically connecting when you start your phone.

I'm not sure if this option is permanent, but used in conjunction with the widget its a sure way of keeping in control of your battery life.

You can also use this menu to disable your connectivity, but its alot easier to just use the widget.

Sources

Samsung Galaxy S GT i9000: How to Flash firmware and remove crappy Optus apps

When I purchased an unlocked nice new Android-powered Samsung Galaxy S phone from eBay, one thing I didn't expect to find was vendor bloatware.

Optus (or Vodafone, Virgin, AT&T, Verizon, Sprint, etc) will bundle crappy apps into your phone leave their dirty brand all over it. I hate it and since I'm not even using their services, I don't need it. It's wasting my space and probably my battery too!

So, to get rid of all that crap you have one of two options; to flash or to root. Both of which sound incredibly rude :)

image image

Flashing the firmware means to completely replace it (much like formatting your computer).

To root means to gain super-user access (much like an Administrator level access) to your phone and to delete the applications manually.

I chose to flash, as it would override ANY changes made to the original Samsung firmware which may have introduced bugs. This process however does carry a higher risk of messing up your phone, so please follow instructions precisely.

IMPORTANT!

I (stupidly) forgot to back up my photos but luckily that was still on the phone after the firmware flash! Please remember to back up ALL your important data before performing this. You will lose your apps, settings, contacts, etc.

Look online for some tutorials on how to back up stuff.

Another thing to back up is your APN settings. Go to "Settings > Wireless and network > Mobile Networks > Access Point Names" and write all that information down somewhere.

Once you're ready, lets get cracking!

Hardware

  • Samsung Galaxy S GT i9000 (duh!)
  • USB cable for phone
  • A computer

Downloads

First we'll need 3 main files:

  • Odin3 v1.0 (There is v1.3 and higher, but most tutorials were using 1.0 so I went with that)
  • The selected firmware version for your region
  • The appropriate Samsung Galaxy S .pit file (when selecting your firmware file, it'll tell you which pit file to use)

All of which can be downloaded from samfirmware.com

If you have not installed "Samsung Kies" (or you just don't want to use that crap), then you'll need to get the USB drivers for the SGS so Windows can detect it properly.

Find the Kies setup (disc 1 of 2) that should of come with your phone and open up Windows Explorer. Using WinRAR or 7-zip, extract the contents of "CDROM:\Kies\CabFile\USB Driver\SAMSUNG_USB_Driver_for_Mobile_Phones.exe.cab".

When you've extracted "SAMSUNG_USB_Driver_for_Mobile_Phones.exe" extracted, run and install it. Test that your phone detects correctly by connecting it to the computer via USB.

Preparation

Once downloaded, extract Odin3 and save the pit file into the same folder.

The firmware file can stay in the .tar format after extraction.

Flashing

After backing up your current (and working) firmware, you can start the flashing process.

  • Enable USB debugging mode on your phone.
    To do that, go to Settings > Applications > Development > and tick "USB debugging".
  • Look at your phone, now back to me.
  • Turn off your phone.
  • Run Odin3 and find the:
    • .pit file by clicking on "PIT"
    • firmware .tar file by clicking on "PDA" (do not choose phone, that's for something else!)
    • Everything else can stay default
  • Now start up the phone in download mode by holding "Volume Down + Home + Power" at the same time. (If this doesn't work, see below!)

image

  • Once the phone is in download mode, Odin3 should detect it in the first available COM port slot.
  • Click "Start" to begin the flashing process.
  • The whole process of updating should take about 1 minute. Pray for that minute that your computer doesn't reboot or the power doesn't cut out.
  • The phone will restart once and initialise itself.
  • After the phone restarts and loads up properly again, you should see "All threads completed".
  • When you see your phone home screen again, it is safe to unplug the phone.
  • Now admire your own accomplishment you magnificent bastard.

image

Final steps

Lost 3G and MMS?

If you've suddenly realised that you no longer have 3G or MMS, then that means you forgot to back up the APN settings.

For Australians, you can find your APN settings for most telcos at AusDroid's APN page.

Troubles?

Stuck on "File analysis"

If you've clicked on "Start" in Odin3 and it gets stuck on "File analysis", you probably didn't put the .pit file in the same folder as Odin3.

Don't worry, it's fine to just pull the plug because it hasn't started flashing yet.

Can't get into download mode!

I thought my phone was blocked from firmware updates when I noticed this wouldn't work.

image

If your phone does not show the download mode screen, don't fret! This is merely a small obstacle in the path to victory!

It is not that your phone can't get into download mode, it's just that the "Volume Down, Home, Power" combination just won't work for certain devices.

Instead, you'll need to install the Android SDK (which is a fairly large download). Download and install. When ready, open up a Command Prompt window and type:

adb devices

This will give you a list of connected Android devices (hence why USB debugging should be enabled in step 1).

When the right device shows up in the list, type:

adb reboot download

That should restart the phone into download mode.

1283776863038

The information from Spiz in in AndroidForums.com saved me! Kudos to you Mr Internet!

Now you can continue the flashing process.

Sources

ATI Radeon: Screen blanks out but computer continues to operate

I've noticed this happen a few times on Windows XP, even after I bought a bigger power supply of 600W (which has stopped my random reboots!), but my computer was still suffering from the random black screens.

Normally associated with playing Starcraft 2, but it also happens with other games or when performing other tasks such as messing with stuff on Photoshop (with 3D acceleration enabled).

Being a ridiculously vague topic to search for online, theres alot of solutions.

Symptoms

The screen blanks out, as if the video card decided to go on strike and stop sending out data to the monitor.

The music continues to play and the computer continues to run like usual, still responding to mouse and keyboard commands also.

Fixes

Of course, you've probably tried the usual things already.

  • Update your graphic drivers
  • Reboot your computer (and hope that this freak accident never happens again but it does)
  • Update the software which causes the problem

If you haven't tried those yet, give it a shot.

Shutdown

If you can find yourself a way to shut down and you're willing to lose some data, go for it. I normally (on Windows XP with classic menu) press on the keyboard in the following order:

  • Windows button
  • U
  • U

Then wait for the computer to shut stuff down.

If it stops for a while and there is no harddrive activity, press E. This is to close the "End Task" dialog that halts the shutdown process.

I've never tried to hibernate, so you might want to give that a shot. Let me know how it works out.

Remote Desktop

If you're lucky enough to have a spare computer with network access, then simply remote desktop into the machine. When you log out, it'll give the video card a kick-start.

Excel: Macro security error when opening XLS spreadsheets

It sucks when you try to open a spreadsheet and it whinges about macro security.

Honestly, you can't inspect that shit unless you open it, but you can't open it unless you let it run the macro which you're uncertain about.

Ahh the wonderful catch 22 in the realm of security warnings.

Anyway, if you get this error:

This workbook cannot be opened under High Security Level because it contains a type of macro (Microsoft Excel 4.0 macro) that cannot be disabled or signed.

To open this worbook, click Macro on the Tools menu, then click Security. In the Security dialog box, click Medium.

image
Thats one long ass error message.

Well, thats pretty much it. Do as it says and you'll be able to open it.

image In the Tools menu:

  • Go to Macro
  • and select Security

image

  • Select "Medium"
  • click OK
  • You should now be able to open the file

jQuery: Ajax post calls error handler even when proper response given

When using an AJAX post with the dataType JSON, be careful when returning a valid HTTP response (200) with an empty string as the content.

If the JSON fails to validate, it will call the error handler.

This was encountered when using jQuery v1.2.6, so I updated to v1.4.2 and it worked again.

Otherwise, you can add a check in the error handler to validate the error's status (so if its 200 then ignore) or check the response HTML if its an empty string.

Download certain files from ZIP/RAR/etc archive files

If you're after a particular file from a big archive but don't want to download the whole thing, you can still download it as long as you get some special software.

I've found 2 ways of doing it but I don't see myself using it very often.

LoudScout

First is to use LoadScout. It is a standalone program that lets you paste in the URL of the archive and it'll display its contents.

Select the files you want to download and let it work its magic.

image
LoadScout 3.0 interface

The interface is a bit old but it still works well.
I didn't particularly like the sorting it used for the file list nor the way it displayed the download progress.

ArchView

My preferred choice was the Archview addon for Firefox.

It had a slightly nicer user interface, but I didn't like the way it automatically assumed I wanted to explore every archive I clicked on.

image
ArchView addon for Firefox

I tried ArchView in a separate installation of Firefox, so it didn't affect the way I normally download archive files.

If you've got a better method, I'm happy to try it out!

Starcraft II: Access North America battle.net servers from South-East Asia

First off, let me say that Blizzard's region locking is fucking gay. I have a few mates in the states and not being able to play the SAME GAME against them sucks.

Since patch 1.1 of Starcraft 2, Blizzard was "kind enough" to allow Aussie (and Asian) SC2 players to play against the fat North Americans.

To enable it, you must first log into http://www.battle.net with your SEA account. Under "Your Game Accounts", click on "StarCraft II: Wings of Liberty [SCII-1] North America (NA)" to add the game to your profile.

Now start up the game.

Before you log in, click on the region button on the left side of the screen. Select a region and then log in as per usual.

image

Let's all hope this sort of region locking gayness won't ruin the experience of Diablo III!

*edit 31/10/2010*

If you can't see it, you're probably using the "Remember me" option. Click on the little arrow next to your account name to clear it and the "Region" button will appear.

Happy Halloween! =)

image

django: Create a custom admin model filter

For the majority of the time, the built in Django admin filters are sufficient. However, sometimes we need something a bit more customised which will cater to the behaviour of our models.

For example, I needed a filter which filters any active polls. However, the date of which the poll starts and ends depends on the current time and there is (at the time of writing) no filter for that.

I found it quite difficult to find a tutorial on this topic that covers all steps from A to B for a person who is doing this for the first time.

After a few attempts, I managed to get it working.

Firstly, create the filter in "yourapp/filterspecs.py". Because I needed a filter based on the expiry date of a model, it was based off the DateFieldFilterSpec (and Mark Ellul's example in the StackOverflow link)

from django.db import models
from django.contrib.admin.filterspecs import FilterSpec, DateFieldFilterSpec
from django.utils.translation import ugettext as _
from datetime import datetime

class IsActiveFilterSpec(DateFieldFilterSpec):
"""
Adds filtering by future and previous values in the admin
filter sidebar. Set the is_active_filter filter in the model field attribute 'is_active_filter'.

my_model_field.is_active_filter = True
"""

def __init__(self, f, request, params, model, model_admin):
super(IsActiveFilterSpec, self).__init__(f, request, params, model, model_admin)
today = datetime.now()
self.links = (
(_('Any'), {}),
(_('Yes'), {'%s__gte' % self.field.name: str(today), }),
(_('No'), {'%s__lte' % self.field.name: str(today), }),
)

def title(self):
return "Active"

# Register the filter
FilterSpec.filter_specs.insert(0, (lambda f: getattr(f, 'is_active_filter', False), IsActiveFilterSpec)

This creates a filter which will check a field for the "is_active_filter" attribute. If found, it'll be compatible with the new filter.

Now to enable the filter on our field. Edit "yourapp/models.py".

class Poll(models.Model):
start_date = models.DateTimeField('date published')
end_date = models.DateTimeField()
title = models.CharField(max_length = 100, default = 'Weekly Poll')
question = models.CharField(max_length = 200)

# Filter 
end_date.is_active_filter = True

By adding the "is_active_filter" attribute to "end_date", our new filter will see that we want to use it and present itself if needed.

Lastly, the bit I found least information on, you'll need to edit "yourapp/admin.py" to load the filter and display the field on the filters panel.

from polls.filterspecs import IsActiveFilterSpec

class PollAdmin(admin.ModelAdmin):
list_filter = ('end_date', )

For me, the magic line here was the import statement. Prior to this, no other tutorial implicitly mentioned that it needed to be loaded. Without that magic line, the filter would not be registered and would display the normal date filter.

If all is done correctly, the end result is this!

image

Sources

The most useful sites I found on this topic.

jQuery: Stop event bubbling from propagating up the element chain

You may have noticed that sometimes when you click on an element, the click event handler of (one of) the parents are triggered.
Thats because events in Javascript are like bubbles which rise from the lowest element (the one which you clicked) to the top element, the HTML body.
You can prevent the event from rising up the element chain by using jQuery's event.stopPropagation().


$('#some_id').click(function(e) {

do_something();

e.stopPropagation();

});


That's it!


Note: If an element has multiple event handlers, this will only stop the one handler from passing on the event bubble.


[ Source ]

Django: Stop client side caching with @never_cache

Sometimes you want a page to never be cached on the client side.

This could be achieved in other languages/frameworks by sending the certain HTTP headers which instruct the browser "no-cache" and "must-revalidate".

Luckily in Django, there's a nice little view decorator we can use which does just that!

from django.views.decorators.cache import never_cache

@never_cache
def myview(request):
# Your view code here

And that's it! Hard work over.

[ Source ]

Django: Checking for User Permissions

I found it a little difficult finding solid information about implementing user permission checks for Django.

After reading numerous sites and tutorials, I've combined a few methods to make it a bit easier.

Rather than inserting the permissions into the database manually, use the Meta attribute in your models (from Satchmo Project).

class Caption(models.Model):
"""
Example model with permission.
"""
# Your field declarations
title = model.TextField()
description = model.TextField()

class Meta:
permissions = (
("is_caption_moderator", "Caption Moderator"),
)

After setting up the permissions, use ./manage.py syncdb to install these permissions into the database.

Now you can simply check for sufficient permissions as long as you have the user object.

def your_view(request):
if request.user.has_perm('is_caption_moderator') == False:
# Do something here like return HttpResponseNotAllowed()

# The rest of your view here

Lastly, remember to grant specific permissions to users when moving this code live because the admin user automatically has access to everything.

Sources

Add an image to your RSS feed item

It was surprisingly easy to get images into the RSS feed.

All you have to do is add the following attributes and your feeds should be image ready.

  • xmlns:media="http://search.yahoo.com/mrss/" in the XML tag.
  • <media:thumbnail url='http://link' height='x' width='y' /> element in the item.

<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        <title>ThatAwesomeShirt! Latest Shirts</title>
        <link>http://www.thatawesomeshirt.com/</link>
        ...
        <item>
            <title>AWESOMENESS</title>
            <link>http://www.thatawesomeshirt.com/shirt/209/awesomeness</link>
            ...
            <media:thumbnail url='http://www.thatawesomeshirt.com/images/get/252/shirt_thumbnail' height='75' width='75' />
        </item>
        <item>
            <title>Quit Work, Be A Ninja</title>
            <link>http://www.thatawesomeshirt.com/shirt/208/quit_work_be_a_ninja</link>
            ...
            <media:thumbnail url='http://www.thatawesomeshirt.com/images/get/251/shirt_thumbnail' height='75' width='75' />
        </item>
        ...
    </channel>
</rss>

Now, 2 things to make sure of:

  • Make sure you're using RSS 2.0 onwards.
  • The URL for the image must be an absolute URL.

Disable Apple Software Update

I installed Safari onto my computer (by God it's slow on Windows!) and noticed after a while that a software update window kept popping up once in a while.

Another annoying thing is that it suggests updates for software that isn't even installed on my computer!

image

Curious and annoyed, I wanted to figure out how it was running (and disable it). But alas, I could not find it in the conventional places like startup, registry or services.

A quick search online reminded me of another place I forgot to look, the Task Scheduler.

Go to the Task Scheduler by:

  • Start
  • Programs
  • Accessories
  • System Tools
  • Task Scheduler (You need to run as administrator on Vista and 7)
  • Expand to find the group called "Apple" (only for Vista/7)
  • Select "AppleSoftwareUpdate" and disable or delete

image
The Task Manager (Win7/Vista)

Thou shall not annoy.

[ Source ]

Disable "Read More " Browser Clipboard Copy Paste Hijacking

I've noticed a few sites have some sort of copy/paste hijacking.

It happens when I notice something worth pasting to a friend. When I paste it, boom! They get the text I pasted, a few blank lines and then "Read More <url of webpage here>".

Honestly, thats just annoying. I know you have a site and content to protect, but if your content is worth reading then people will ask me for the URL.

Anyway, a quick search will reveal that the company responsible for this is called "Tynt - the copy paste company".

Blocking with AdBlockPlus

I find this rather annoying, so I disabled it using AdBlockPlus.

To do that:

  • Right click on the AdBlockPlus icon in the status tray.
  • Click on "Open blockable items".
    image
  • Type in "tynt" to filter the results.
  • Select any item that matches and press Enter.
  • Select "Custom"
  • Type in "http://*.tynt.com/*"
  • Click "Add filter" to finish

Refresh the page and you should be Tynt-free!

Blocking with host file

Other people have gone a step further and simply blocked everything from Tynt.

If you REALLY dislike them, edit your hosts file and add in this entry.

127.0.0.1   tcr.tynt.com

Obviously, instructions will vary for Windows, Linux and Mac but its not hard to find instructions for doing so.

Sources

Disable Messenger chat in Hotmail/MSN/Windows Live webmail

Jesus christ! When big companies merge all their technologies together it is annoying as fuck!

I'm already on MSN/WLM using the PC client, but when I saw it automatically polluting my webmail in the browser without my consent I was a little irritated.

image
So err, why is it showing me the same shit twice?

Anyway, I'm glad they made it easy to turn it off.

Simply hover your mouse over your profile name in the top right hand corner and select "Sign out of Messenger".

image 

Rage will subside in given time.

git: Show history with a helpful branching tree

Tracking down branching ancestry in revision control is horrible to say least. At least git has a nice little feature which lets you change the log output into a nicer layout.

git log --graph

To look at a specific revision:

git log --graph commitid

This will give a nice branched log format to help you track down commits.

image

git: Show difference between commits

git diff commitid1..commitid2

C++: Parse command line arguments

First off, you should not use lpCmdLine which is given by the main function of your application.

int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)

Be aware that lpCmdLine will only support ASCII characters. If you are creating a project which works with wide characters or multibyte strings, it will be horrible to deal with.

Not to mention you have to parse the string yourself, which means you also have to manage "strings within quotes" yourself as well.

1263914772happy 
HEAD ASPLODES!

Instead, you should be using CommandLineToArgvW() with GetCommandLine(). They will retrieve the arguments for your program, in the correct character set.

You can also use this anywhere, so there is no need to complicate your code and cause hell by passing lpCmdLine down the initialisation function chain.

The magic code:

// Parse command line arguments
LPTSTR *szArgList;
int argCount;

szArgList = CommandLineToArgvW(GetCommandLine(), &argCount);

if (szArgList) {
for (int i = 0; i < argCount; i++) {
//MessageBox(NULL, szArgList[i], L"Arglist contents", MB_OK);

if (!_tcscmp(L"--no-icon", szArgList[i])) {
bShowTrayIcon = false;
}
}

LocalFree(szArgList);
}

LocalFree() is required to unallocate the memory, which is set by CommandLineToArgvW().

Other than that, this is fairly straight forward.

[ Source ]

 
Copyright © Twig's Tech Tips
Theme by BloggerThemes & TopWPThemes Sponsored by iBlogtoBlog