Posts Tagged ‘Tutorials’

Mac OS X on a Dell Vostro A90 (Mini 9)

Wednesday, August 19th, 2009

mac vostro openOver the summer I had a little argument with a coworker about the “Mac tax.” I was telling him that a Mac uses pretty much the same hardware you will find in a “PC” (that word, PC, used in that context annoys me because PC is Personal Computer, so technically as Mac is a PC, but marketing prevails I guess) but Mac’s are a lot more expensive. So in an attempt to prove my point, I tried to install Mac OSX on to my HP laptop. After about 15 tries, all I could get it to do was finish the installation. Never got it to boot. I gave up, moved to California, bought a MacBook Pro because I wanted a Mac and the USC Bookstore was having a sale.

Very happy with my MacBook Pro I did not pursue ihackintosh any more. Then after the netbook craze, I found a lovely Mac OSX netbook compatability chart and noticed everything works on the Dell Mini 9/Vostro A90 (they are the SAME computer). A Mac netbook, that would be cool!

I waited, trying to save up some splurging money. Meanwhile I helped two of my friends pick out netbooks for themselves (both were HP Mini 10, one with solid state and one without), which made me want to buy one. On top of that I found some Dell discounts from a friend, and I went to the Dell Outlet and bought a Vostro A90 with 16GB SSD and Ubuntu for $280 delivered.

Since I am going to be hacking and all that, I figured I would buy a nice retail copy of Mac OSX 10.5.6 (which I also got at the USC Bookstore, seeing as they sell it for $99).

With my new-to-me netbook and fresh retail copy of Mac OSX, I went home and stayed in on a Friday night, to bump up my geek cred!

This is not meant to be a full tutorial, there are many many online, but more of a checklist of items needed and the guide I followed, and some road blocks. And a little review of my Mac Vostro A90 at the end.

I only had one issue worth noting. After I booted off of the DellMiniBoot 8.02b1 and swapped the disc for the retail Mac OSX install disc it took a few tries for the OSX installer to load. The Vostro didn’t recognize the install disc right away after I swapped the discs. I had to wait about a 15 count before I hit ENTER on the boot screen after I put in the retail Mac OSX install disc. So if you get stuck and the intaller will not load, just keep trying! It took me about 10 minutes of fiddling before I go it to load the installer. Other than that, follow the guide to the letter, they do a very good job of outlining what you need to do.

UPDATE: To get to the BIOS hit 2 at boot up, and hit 0 to get to the boot menu.

UDPATE: ***For sleep to work you must deselect usb wake from sleep and usb legacy mode in bios***

mac vostro closed

Checklist:

I have been using my Dell Vostro for about 2 weeks now. I took it on a trip to Chicago, and it played about 4 hours of TV shows from a USB stick on the plane ride. Which is pretty good considering its a refurb and I know that batter is not at 100%. The computer is very small though. The screen is nice, but the resolution is only 1024 x 600. Most web pages look fine, and you kinda get used to it. It does have a VGA port if so you can hook up an external monitor. I got it to play relatively smooth streaming video from Hulu at 1280 x 1024 full screen. The biggest issue I have with the computer is the keyboard layout. The quote ( ‘ ) is not in the normal place by your right pinky, but down below the period next to the spacebar. So I hit enter instead of ‘, which is really annoying when you are IMing.

Most of the time I use it at work, I have Synergy installed on my work Windows XP machine, and SynergyKM installed on the Mac Vostro. Mich is great for testing websites. Just copy the URL and move my mouse down to the Mac Vostro and paste it in and see how it looks! Aside from that, everything works, runs quite smooth, and quiet. Overall, I am really happy with it.

Google App Engine and dynamic Django Forms

Wednesday, January 28th, 2009

Let me define dynamic form: a form that can have 0 to x number of entries for a field. For example a form that contains a list of items, like a grocery list. Its part of the same form but can have more than one entry. In PHP, they can be grouped by appending “[]” to their name attribute, and PHP stores them the $_POST variable as array (i.e. $_POST['list'][0]). I am working a project using Google App Engine, which uses Django forms, and I needed a dynamic form (list).  I found this can be done using the get_all() function of the self.request object (i.e. self.request.get_all(‘list’)) will return a list object.

Cool! But how do I use that with the Django form model with this list?  Make a list of form models. Loop through the posted list, create a form object with that data, append it to the form list, check if its valid and repeat.  If there was an error, just send the form list to the template, and loop through the forms displaying them with error messages. Else, the entire form is valid, save it to the data object.  Here is some code:

#main.py

import wsgiref.handlers
from google.appengine.ext import db
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
from google.appengine.ext.db import djangoforms

class Groceries(db.Model):
	quantity = db.IntegerProperty()
	name = db.StringProperty(required=True)

class GroceryForm(djangoforms.ModelForm):
	class Meta:
		model = Groceries

class MainHandler(webapp.RequestHandler):
	def get(self):
		groceryform = GroceryForm()
		values = {'groceriesformlist': [groceryform]}
		self.response.out.write(template.render('main.html',values))
	def post(self):
		postedQuantities = self.request.get_all('quantity')
		postedNames = self.request.get_all('name')
		groceriesList = []
		allGroceriesValid = True;
		n = 0;
		for i in self.request.get_all('quantity'):
			groc = GroceryForm(data={'quantity':postedQuantities[n],'name':postedNames[n]})
			allIngredientsValid = allIngredientsValid and groc.is_valid()
			groceriesList.append(groc)
			n += 1
		if allGroceriesValid:
			for grocerydata in groceriesList:
				grocery = grocerydata.save(commit=False)
				#do something with data
				grocery.put()
			self.redirect('/')
		else:
			values = {'groceriesformlist': groceriesList}
			self.response.out.write(template.render('main.html',values))
def main():
	application = webapp.WSGIApplication([('/', MainHandler)],debug=True)
	wsgiref.handlers.CGIHandler().run(application)

if __name__ == '__main__':
	main()

The commit=False is useful when you do not want to save the data right away, like some other variable manipulation. Then there is the template file. There are numerous ways to output the form, it even has a built in table or paragraph method. If you wanted to just use the default table method to output the form, with errors, simple use <table>{{groceryform}}</table> (the output omits the table declartions, just the rows and columns) and your are done. I like a little more control, so to output the erros: {{ groceryform.quanity.errors }} and then output the input tag: {{groceryform.quantity}. Here is the template file, main.html:

<h3 class="form_headers">Groceries</h3>
<ol id="directions_form">
	{% for groceryform in groceriesformlist %}
		<li>{{ groceryform.quanity.errors }}{{groceryform.quantity}}{{ groceryform.name.errors }}{{groceryform.name}}</li>
	{% endfor %}
</ol>
<input type="button" value="+" id="add_btn" onclick="AddLi(this.previousSibling.previousSibling)" />

You also need to toss in some javascript for adding new grocery items:

function AddDirLi(ol)
{
	var li = ol.firstChild.nextSibling.cloneNode(true);
	ol.appendChild(li);
}

There are many ways to accomplish this, with AJAX or just posting items one at a time. But my project actually had a few sections of this nature and it this method seemed to work the best. I hope that made sense. The next post will cover Using Relationships with the Google App Engine Datastore. Creating and storing multiple grocery lists. The grocery list would be the the parent to many grocery items.

Reading and Writing Files in AIR – using a simple text editor

Monday, January 26th, 2009

Monstagon asked me if I ever saved or opened files in Adobe AIR. Yes. I have. I made a simple text editor to demonstrate the basics of reading files in (letting the user browse for a file on their machine) and writing a save (also letting the user specify where to save the new file).

Some issues I encountered with making the text editor were the different FileModes (READ, WRITE, UPDATE, and APPEND). UPDATE and APPEND basically just add whatever you write to the FileStream to the end of the file. WRITE deletes the destination and writes only what is sent to the FileStream. READ only opens the file for reading. After erasing some files accidentally by opening it with WRITE, I realized for the text editor to work, first READ the file in, close the FileStream. When the user hits Save, open the file in WRITE mode, and send the contents of the editor to the FileStream.

I also had to removeEventListener from the FileStream because it was listening for two Event.SELECT’s: user selects which file to open, and user selects where to save. This was throwing errors when the user selects where to save and the program tries to open a file that doesn’t exist.

If you just want to know how to read a file, look at private function Open() and follow the code. For writing, private function Save(). Note that in ActionScript, its all about event listeners. So reading the file contents into the TextArea is 3 function, because we have to wait until each step is ready. Else, if you don’t setup the Event Listeners nothing will happen.

<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script>
<![CDATA[
import mx.events.FileEvent;
private var stream:FileStream;
private var file:File = File.documentsDirectory;
private var newFile:Boolean = true;
private function New():void
{
	newFile = true;
	editor.text = '';
}
private function Open():void
{
	try
	{
	    file.browseForOpen("Open");
	    file.addEventListener(Event.SELECT, LoadFile);
	}
	catch (error:Error)
	{
	    trace("Failed:", error.message);
	}
}
private function LoadFile(evt:Event):void
{
	file.removeEventListener(Event.SELECT, LoadFile);
	file = evt.currentTarget as File;
	stream = new FileStream();
	stream.addEventListener(Event.COMPLETE, ReadFile);
	stream.openAsync(file,FileMode.READ);
}
private function ReadFile(evt:Event):void
{
	stream.removeEventListener(Event.COMPLETE,ReadFile);
	var str:String = stream.readUTFBytes(stream.bytesAvailable);
	editor.text = str;
	newFile = false;
	stream.close();
}
private function Save():void
{
	if(!newFile)
	{
		stream = new FileStream();
		stream.openAsync(file,FileMode.WRITE);
		stream.writeUTFBytes(editor.text);
		stream.close();
	}else
	{
		file.browseForSave("Save");
		file.addEventListener(Event.SELECT, SaveFile);
	}
}
private function SaveFile(evt:Event):void
{
	file.removeEventListener(Event.SELECT, SaveFile);
	var file:File = evt.currentTarget as File;
	stream = new FileStream();
	stream.openAsync(file,FileMode.WRITE);
	stream.writeUTFBytes(editor.text);
	stream.close();
	newFile = false;
}
]]>
</mx:Script>
<mx:VBox width="100%" height="100%">
<mx:HBox>
	<mx:Button label="New" click="New();" />
	<mx:Button label="Open" click="Open();" />
	<mx:Button label="Save" click="Save();" />
</mx:HBox>
	<mx:TextArea id="editor" width="100%" height="100%" />
</mx:VBox>
</mx:WindowedApplication>