How to install KDE 4.1 on Ubuntu Hardy 8.01 and my impressions of it

With yesterday’s announcement of the 4.1.0 release of KDE, my willpower did not allow me to go another day without giving KDE4 another shot. For a bit of history, I have been using Gnome for several years. In the past 3 months or so I began using KDE 3.5.9 long enough that I began to enjoy it and realize that it is a nice desktop environment as well. At this point I really have no favorite between the two and like different things about both of them.

When the first releases of KDE 4 started showing up several months ago, I gave it a shot but was extremely underwhelmed. While it came with all the warnings from the community that the 4.0 release was nothing more than the introduction of a new platform which developers would expand, some of the basic pieces of it just felt wrong. I can clearly say that after spending most of an afternoon using it, running my development environment, and doing basic daily functions, 4.1 is light years beyond the first peak I had of it. I am *really* enjoying it so far and I have a feeling it will be my desktop of choice for the immediate future.

One thing that seems to not be common knowledge to some people is that you can just install it and try it out without affecting your existing desktop environments, be it KDE 3.5.x or Gnome. For example, my current installation started out as Kubuntu 8.04 Hardy Heron. Shortly after installing I added Gnome by running:

sudo apt-get install ubuntu-desktop

Then in the GDM or KDM login window, I had options for either logging in using Gnome or the default KDE. Thankfully the two coexist without bothering each other, and I can switch back and forth at will. I took the same approach today when installing KDE 4.1, planning to keep both Gnome and KDE 3.5 as fallback positions or simply to use when I am in the mood.

If this type of setup sounds like something you want to try out, do the following. First, add the following repo into your /etc/apt/sources.list file:

deb hardy main

After adding that you will want to update your repos by running:

sudo apt-get update

Then to install KDE 4.1 you will run the following:

sudo apt-get install kubuntu-kde4-desktop kdeplasma-addons amarok-kde4 and kontact-kde4 kate-kde4 kmail-kde4

Notice that I am also updating several applications, such as kate, amaroK, kmail, and kontact. Kdeplasma-addons also brings you some extra goodies beyond the base install. During that installation you will be prompted to choose your login manager. KDE4 brings you yet another option beyond GDM and KDM. I chose it and it is a really nice clean look. I recommend giving it a look. Once the installation completes, restart X or reboot and have fun!

Dependent objects made even easier in Mach-II 1.6

In case you were wondering if Mach-II could get any cooler, the answer is *yes*!

For a few versions now, Mach-II has added the ability to inject ColdSpring beans in to your framework components (listeners, plugins, and filters) by use the parameter resolveMachIIDependencies when instantiating the ColdSpring plugin or property.

Take this example… Say that I have a LoginListener.cfc that is dependent on a ColdSpring bean LoginService that lives in our /com directory. I would first define that bean in our ColdSpring config like this:

<bean id="LoginService" />

Then, in our LoginListener we would need to create a setter that matched the Bean that we have defined in ColdSpring like so:

<cffunction name="setLoginService" access="public" output="false" returntype="void">
	<cfargument name="LoginService" required="true" type="com.LoginService" />
	<cfset variables.LoginService = arguments.LoginService />

By taking these two actions, and insuring that your LoginService as an init() method as a constructor, when you initialize your application, variables.LoginService will automatically be available to you as an instance of your LoginService bean. That alone was pretty dang cool.

But wait there’s more!

With Mach-II 1.6, this process has become even less cumbersome. In some CFML tags, you can add unexpected attributes without throwing exceptions and are in essence ignored to offer a better solution for managing dependent objects. By default, Mach-II will look for a “depends” attribute in your tags, which can contain a comma separated list of your dependencies. For our simple LoginListener, our tag would look like this:

<cfcomponent output="false" extends="MachII.framework.Listener" depends="LoginService">

Now, instead of repetitive getters/setters, just by merely having that attribute, our LoginListener will now contain the method getLoginService() which will return an instance of the LoginService. That is just ridiculously easy!

As I said, the attribute actually accepts a comma separated list, so as we add dependencies, our tag might look more like this:

<cfcomponent output="false" extends="MachII.framework.Listener" depends="LoginService,UserService,LoggingService">

If you have made it this far, you have probably deducted that we will now have access to getLoginService(), getUserService(), and getLoggingService().

As I mentioned earlier, Mach-II will look for the attribute “depends” by default, but you can customize it to use other attribute names if you wish. You can find that information and more on the Mach-II wiki.

Related checkbox validation with JQuery

I was given a problem yesterday where I needed to do the following client-side validation. If a user selects a checkbox that they wish to enable credit card transactions, I need to display a panel of specific credit card companies and they need to select at least one before submitting.

If you think about writing the JS to do this without a library it is a somewhat lengthy task. In essence, you would need to do some type of an onsubmit function on your form, check the value of the key checkbox. If it was checked, check the value of each credit card checkbox to see if the user had selected one of the children. After writing this in JQuery, I thought it might be worth demonstrating what an easy task this is.

Let’s start with the specific part of my form that has my checkboxes:

<label for="RequireCCInfo">Require Credit Card Information?</label>
<input name="RequireCCInfo" id="RequireCCInfo" value="1" type="checkbox">
<div id="CreditCardCompanyPanel">
		<input id="ccAmex" value="1" type="checkbox">
		<label for="ccAmex">American Express</label>
		<input id="ccVisa" value="1" type="checkbox">
		<label for="ccVisa">Visa</label>
		<input id="ccDiscover" value="1" type="checkbox">
		<label for="ccDiscover">Discover</label>
		<input id="ccMc" value="1" type="checkbox">
		<label for="ccMc">Master Card</label>

There is nothing too notable in all of that other than the fact that you should notice that I have added a class “ccCheckBox” to all of my dependent checkboxes. I will explain more on that in a bit, but I wanted to point out that it is there. You will also notice that I am not doing anything in the way of hiding the “CreditCardCompanyPanel” div. We need to determine at request time whether that will be hidden or not based on whether the “RequireCCInfo” checkbox is checked.

Now, here is the fun part… I am including the JS that I use for this task below:

<script language="javascript">
	function toggleCreditCardCompanyPanel()	{
		if ($("#RequireCCInfo").attr("checked") == true) 	$("#CreditCardCompanyPanel").show();
		else $("#CreditCardCompanyPanel").hide();
		var pass = false;
		if ($("#RequireCCInfo").attr("checked") == true){
			$(".ccCheckBox").each(function() {
               			if ($(this).attr("checked") == true) pass = true;
		else pass = true;
		if (pass) $("#frmMyForm").submit();
		else alert('You must select at least on credit card company if "Require Credit Card Information" is checked.');

First, by using the $(document).ready() function we are telling JQuery to run this JS once the DOM has been completely loaded. Let’s look at each section within that ready() block…

The first thing you will see is the $(“#RequireCCInfo”).change() method. JQuery gives us the concept of binding a listener to an element. For our example, this listener says that anytime that an element with an ID of “RequireCCInfo” is changed, that we will run the code in its function(). You will see that anytime our “RequireCCInfo” checkbox is changed we are going to run a function called toggleCreditCardCompanyPanel(). As you can see we have that method defined immediately after our “RequireCCInfo” checkbox.

In our toggleCreditCardCompanyPanel() method, we are making the decision as to whether or not our “CreditCardCompanyPanel” will be displayed based on whether our user has decided to check the box labeled “Require Credit Card Information?”. By using the JQuery selectors we are in essence saying: If a checkbox with an ID of “RequireCCInfo” is checked, display an element with the ID “CreditCardCompanyPanel”. Otherwise we will hide this element.

Next comes our validation on form submit… and pretty cool stuff!

Basically I have added a listener which is bound to our submit button with the ID of “SaveButton” which will submit our form “frmMyForm”. Anytime that this button is clicked, we will run the code in the function() block. We start this function by setting a value pass=false. We will use this variable to determine whether our form has passed validation. Next we get just a small taste of the magic of JQuery selectors. First, as we did in the toggleCreditCardCompanyPanel() function, we are determining if the element with the ID of “RequireCCInfo” is checked. If so, by using the each() function, we are going to loop through all elements on the page with the class “ccCheckBox” (remember that from above?). In each iteration of the loop we are going to determine if the element has been checked. If so, we are going to set pass=true since we know that our validation has passed.

Lastly, now that we have determined that our form is either going to pass/fail, we take the appropriate action. If pass==fail, we are simply going to alert a message telling the user that if they are going to enable credit cards that they have to choose at least one credit card company. Otherwise, we are going to call the submit() method on our form.

I almost took the time to write out the equivalent of this in POJS (plain old JavaScript) to show how much easier life is with JQuery, but I realized I didn’t have the time, patience, or will. JQuery has spoiled me!