Archive for November, 2007

Introduction

Core Animation is one very cool and interesting API provided by Apple in the Leopard version of Mac OS X. Core Animation can be used to attain some really cool effects like the Cover Flow view, which is available and seen in both iTunes and Finder. The Cover Flow has also been included in the new iPods and in the iPhone. It is an animated view of the files that one is browsing, whether the files are images, videos or documents. Cover Flow displays the preview…

This functionality is now available in Leopard and allows developers to take advantage of this feature by means of Core Animation. Core Animation is a part of the Quartz Core framework and is programmable by means of the objective-c API. This is nice if one’s application UI is written completely in Cocoa. However, why should Carbon developers not be able to take advantage of Core Animation? Well, Apple has thought of that as well. They have exposed a new API named the HICocoaView.

HICocoaView

The HICocoaView allows the developer to embed an NSVIew or any control derived from NSView into a Carbon HIView. This means that Core Animation could be included in a Carbon application. For more information on embedding Cocoa NSViews in a Carbon HIView please visit this link:

http://developer.apple.com/documentation/Cocoa/Conceptual/CarbonCocoaDoc/Articles/HICocoaView.html

Since Trolltech’s Qt framework is currently sitting directly on top of Carbon, I thought I would try and get Cover Flow working in a Qt Application by means of creating a custom widget, which I call the QtCoverFlowWidget.

QtCoverFlowWidget

The first thing we need to do is locate the code for Cover Flow. Conveniently, Apple has an example which ships with the freely available developer tools and it’s named CovertFlow. The entire CovertFlow project, including implementation is available in the following location on your disk:

/Developer/Examples/Quartz/Core Animation/CovertFlow

Basically, the bulk of the work is already done for us, thanks to Apple’s example. Now we must figure out how to wrap a QWidget around this implementation, such that we can use this CovertFlow view inside our Qt Application. So Let us begin.

Creating the project

I simply created a main.cpp from which I then generated an Xcode project. My main.cpp looked something like this:

#include <QtGui>
#include <QtCore>
class MyWidget : public QWidget
{
   Q_OBJECT
 public:
   MyWidget(QWidget *parent) : QWidget(parent) { }
 virtual ~MyWidget() { }
};
#include "main.moc"
int main(int argc, char** argv)
{
   QApplication app(argc, argv);
   QMainWindow *win = new QMainWindow;
   win->resize(600,300);
   win->show();
   MyWidget *w = new MyWidget(win);
   w->resize(400,200);
   w->show();
   return app.exec();
}

now let’s create the project:

qmake -project
qmake -spec macx-xcode QtCoverFlowExample.pro

The above will generate a QtCoverFlowExample.xcodeproj which we can open using Xcode 3.0.

Once the project is opened, there are some things that must be done. They are as follows:

Right click on main.cpp and click Info. In the General tab switch the File Type to “sourcecode.cpp.objcpp”. This is done to let the compiler know that this file contains objective c++ code.
Add QuartzCore and Cocoa frameworks to the project. AppKit framwork can be removed since the Cocoa framework acts as an umbrella around AppKit.
Import the relevant files from the CovertFlow project into our project. They are:

Catalog.h
Catalog.cpp
Controller.h
Controller.cpp
DesktopImage.h
DesktopImage.cpp
DesktopImageLayout.h
DesktopImageLayout.cpp
View.h
View.cpp

and View.nib must go to the Resources folder (create one if one does not exist)

The project should resemble something similar to this once the aforementioned steps have been completed…

Now that the project is created, we must create our custom widget that will display the CovertFlow view which is written using the Quartz Core framework.

Below is the code to our custom widget named QtCoverFlowWidget

class QtCoverFlowWidget : public QWidget
{
   Q_OBJECT
   public:
      QtCoverFlowWidget(QWidget *parent = 0) : QWidget(parent)
      {
         // instantiate controller for the covertflow view
	 HIViewRef coverFlowRef;
         controller = [[Controller alloc] init];
         //HICocoaView wrapper around covert flow view
         HICocoaViewCreate([controller view], 0, &coverFlowRef);
         create(WId(coverFlowRef));
         // connect resize of parent to resize of ourselves
         connect(parent, SIGNAL(resized(int, int)), this, SLOT(slotResize(int, int)));
      }
      virtual ~QtCoverFlowWidget() { }
   protected slots:
      void slotResize ( int w, int h )
      {
         // resize ourselves
         resize(w, h-20);
      }
   private:
      Controller *controller;
};

We derive the QtCoverFlowWidget from the QWidget class. The CovertFlow example that Apple provides is a classic example of an MVC application. Therefore, in the constructor of our custom widget, we instantiate the controller associated with the CovertFlow example. We then create and HICocoaView which wraps the NSView containing the Cover Flow view and then associate our widget with the HIViewRef associated with the HIView wrapping the NSView which contains the Cover Flow view. This is made possible by the fact that a QWidget is just an HIView on its own. Carbon API can be used to communicate directly to the QWidget, which is an HIView. There are some useful Qt functions which help bridge Carbon and the Qt API. These functions are:

// returns an HIViewRef/WindowPtr which is associated with the QWidget
HIViewRef qt_mac_hiview_for(const QWidget *w)
WindowPtr qt_mac_window_for(const QWidget *w)
// returns HIViewRef for a native Carbon Window and vise versa
HIViewRef qt_mac_hiview_for(WindowPtr w)
WindowPtr qt_mac_window_for(HIViewRef hiview)

In order for the above functions to be used in code, all you need to do is #include <QtGui>.

We also have a slot implemented named slotResize(int, int). This slot is hooked to the resized(int, int) signal which is emitted by the parent of this widget (our QMainWindow implementation). This can be seen in the example code here:

connect(parent, SIGNAL(resized(int, int)), this, SLOT(slotResize(int, int)));

The parent widget is actually a custom widget as well. Specifically, it is a custom implementation of the QMainWindow. Not much happens in this implementation except the interception of the resizeEvent(QResizeEvent *) and the action of emitting the resized(int, int) signal once that occurs.

Last steps

There are also a few things that must be done in order to have a properly integrated Cocoa event loop. The main function needs the following:

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSApplicationLoad();
...
...
...
[pool release];

The above code ensures the Cocoa event loop is running and properly handling Cocoa events.

Now we can simply instantiate our custom QtCoverFlowWidget just like we do any other Qt Widget. All the code, including the Xcode project as well as the binaries can be found here…

QtCoverFlowExample.zip Binary Universal Bundle
QtCoverFlowExample_src.zip Source

And the results are….

Conclusion

The HICocoaView made the above possible. The HICocoaView is a power class allowing developers to mix Cocoa views inside their Carbon application. Perhaps next time we’ll do something with Apple’s QTKit.

Share on Technorati . del.icio.us . Digg . Reddit . Slashdot . Facebook . StumbleUpon

1 Comment

A peek at Xcode 3.0

talks about Programming on November 14, 2007

I have been using Xcode 3.0 for some time now. It has worked quite well in production for me. Full of features and enhancements make it one of the best development environments to work with. One of the features which particularly strikes me as genius is the Project Organizer. This feature is available from the Window menu.

Not only does the organizer allow the developer to maintain a number of Xcode projects in an effectively organized way, but it also allows for building Makefile projects. This is in fact something new from Apple and is extremely convenient. Open source projects fit favorably in the little window which is brilliant to say the least.

But let’s take it one step further, not only is the Organizer an organizer, but it is also a lightweight SCM system. Sure it is a local, file based SCM system, but it is extremely useful.

This lightweight SCM functionality is by no means a replacement for the SCM system one uses. It is extremely light weight and allows for better organizing changes made on the local machine. This is quite beneficial for my needs as I often work on code involving a large number of changes which I perform incrementally. Once I reach a stable or satisfactory state of the development task, I simply create a snapshot. The reason I do so is because quite often it is not desired to check in one’s partial changes to the main code repository used by your project team, as it may inflict unnecessary, yet inadvertent, pain on them. This feature allows the developer to experiment effectively while maintaining a coherent and easily accessible history of changes. I often code in a location where there is no internet access and I am unable to check in my desired changes for example. During those times, I can simply create a snapshot and restore later when I am ready to perform the check in to the public code tree.

Let’s move on… so I began coding and I created a snapshot before hand. I made some changes and decided to Create another snapshot. Let’s see what this looks like…

As you can see, the file differences in the “Files Changed” list are displayed and right below that is the differences results, provided by Xcode’s built-in diff tool. Yes, it does look very similar to filemerge. The toolbar provides few operations but gives the user the ability to create more snapshots, delete snapshots and of course restore your project state to a particular snapshot.

Finally, the Organizer also possesses an editor, thus allowing the developer to perform all of his/her work from inside the Organizer.

Share on Technorati . del.icio.us . Digg . Reddit . Slashdot . Facebook . StumbleUpon

No Comments

Works with TestTrack 2008 and later

Works with Perforce 2007.2

This article outlines how to create a trigger in Perforce, which calls a script that validates defect status before allowing a Perforce submit. This was all developed and tested against TestTrack 2008 and Perforce 2007.2.
Continue reading…

Share on Technorati . del.icio.us . Digg . Reddit . Slashdot . Facebook . StumbleUpon

No Comments

Tags: , , ,

Works with TestTrack 2008

Works with Surround SCM 2008

When creating a build, it is imperative to include the revision of the source code files that contain the changes that fix defects that are supposed to be included in the build.

Poor change management can lead to builds that do not include fixed defects or, even worse, reintroduce old defects.

Seapine’s ALM solutions are aimed at avoiding these types of problems. Seapine CM gives you the ability to attach source code files to a defect and associate a defect fix event with the revision of the source code file that addresses that specific fix.

If a build is needed and it has to include a fix for a specific defect, you need to make sure that the correct revision of the source code file is included in the build.

The following example illustrates how you can use TestTrack automation rules and the TestTrack SDK to facilitate this process.
Continue reading…

Share on Technorati . del.icio.us . Digg . Reddit . Slashdot . Facebook . StumbleUpon

No Comments

Tags: , , ,

Anatomy of a Share

talks about Surround SCM on November 01, 2007

Applies to Surround SCM 2008 and earlier

Improper understanding of Surround SCM file sharing can lead to undesired situations. This article explains more of what actually occurs in the backend database. It should help you understand how Surround SCM shares files and its benefits.
Continue reading…

Share on Technorati . del.icio.us . Digg . Reddit . Slashdot . Facebook . StumbleUpon

No Comments

Tags:

Page optimized by WP Minify WordPress Plugin