Embedded Components Tutorial - Page 4
Add Boilerplate KParts Code
The Plan
In this step, you will convert aKtion into an embedded component using "standard" boilerplate code. After this step, when you click on an animation file, it will embed aKtion instead of spawning it off in a separate process. Since no aKtion specific code is used in this step, it won't actually play the animation -- that's reserved for step 3.
The code in this step is completely generic. You can drop it into any application with no modifications!
You will do this in three baby steps:
- Add the aktion_part.cpp and aktion_part.h files
- Modify the Makefile.am to reflect the new files
- Modify the aktion.desktop file to indicate that it is an embedded component
Add KParts Files
Add the following two files to your project with no modifications.
aktion_part.h
|
|
Line By Line: Factory
All KParts components need to construct two classes: A factory class derived from KLibFactory and a view class derived from KParts::ReadOnlyPart. In this tutorial, they are:
#include <kparts/browserextension.h> #include <klibloader.h> class AktionFactory : public KLibFactory class AktionPart : public KParts::ReadOnlyPart
The factory object is responsible for instantiating the components and returning a pointer to them. This is how Konqueror gets a reference to your component.
The entire process start here:
void *init_libaktion()
{
return new AktionFactory;
}
This is the first function that is called in the loading process. The form of the name is void *init_libyourapp() Keep the part after init_ in mind -- that is the string you will use in the X-KDE-Library entry later on. This function always returns a new instance of your factory object
You also need to overload two functions in the factory class: create() and instance().
QObject *AktionFactory::create(QObject *parent, const char *name, const char*,
const QStringList& )
{
QObject *obj = new AktionPart((QWidget*)parent, name);
emit objectCreated(obj);
return obj;
}
The create() function is called each time your component is needed. It is responsible for instantiating a new view object and returning it.
KInstance *AktionFactory::instance()
{
if ( !s_instance )
{
KAboutData about("aktion", I18N_NOOP("aKtion"), "1.99");
s_instance = new KInstance(&about);
}
return s_instance;
}
The instance() function returns an instance of type KInstance. The above code is very standard. Just use it.
|
Line By Line: View
There are six methods that you need to overload for your view class... but a lot of the code is very cut and paste. The code in bold (related to QLabel) is the only application specific code in the view class! Here is what each function is doing:
AktionPart::AktionPart(QWidget *parent, const char *name)
: KParts::ReadOnlyPart(parent, name)
{
setInstance(AktionFactory::instance());
// create a canvas to insert our widget
QWidget *canvas = new QWidget(parent);
canvas->setFocusPolicy(QWidget::ClickFocus);
setWidget(canvas);
m_extension = new AktionBrowserExtension(this);
// as an example, display a blank white widget
widget = new QLabel(this);
widget->setText("aKtion!");
widget->setAutoResize(true);
widget->show();
}
The constructor is responsible for initializing your internal variables as well as your "workhorse" object. Typically, you do not do much processing inside of your KParts derived class. Rather, you have an existing class that has all of the functionality and you just use that inside of your view class. In this example, a QLabel label is used just so there is something displayed when you run it.
Notice that a blank "canvas" is the main widget. This is because Konqueror will resize the component to the full width of the view. In many cases, you will want to control the size of your component; both the QLabel and the actual aKtion component are examples of this. In this case, you set a blank widget as the resized widget and just use that as the parent of your "real" class.
bool AktionPart::openFile()
{
widget->setText(m_file);
return true;
}
The openFile method is arguably the most important method in this class. It is what is called when Konqueror wants your application to display a file. There is a lot going on behind the scenes of this function, though. The KParts framework itself handles all file downloads. That means that by the time openFile is called, the file to play is already local.
Note that if your application can handle remote URLs already, then you can overload the openURL function instead of openFile
widget->setText(m_file);
The m_file variable is set by the KParts framework. It is a QString with a path (not a URL) to a local file. If the original URL was a local file, then it will be a path to the actual file. If it the original URL was remote, then the path will likely be in the /tmp directory.
|
Building the Component
Makefile.am
|
The two parts files that you just added to the project need to be added to the Makefile just like any other file.. and are done so above. You also need to link to the KParts library since we make extensive use of it now.
|
Letting "The System" Know of the Component
aktion.desktop
|
So far, you've made all the changes necessary to make aKtion an embedded component (albeit one that doesn't do much).. but there is no way (yet) for Konqueror to know that when it clicks on a Quicktime file, it should embed the component instead of spawning an external viewer.
This is where the aktion.desktop file comes in to play. When you install the desktop file, the KDE mimetypes system becomes aware of all of its fields (if it doesn't do it immediately, you can force a reload by running the kbuildsycoca command). The three that matter in this case or the MimeType, ServiceTypes, and X-KDE-Library entries.
MimeType=video/mpeg;video/x-msvideo;video/quicktime;video/x-flic; ServiceTypes=Browser/View X-KDE-Library=libaktion
These lines tell the mimetypes system that aKtion can handle the mimetypes specified in MimeType; it implements an embedded component of type Browser/View; and the name of the component is libaktion.
When Konqueror is asked to execute a Quicktime file, it asks the mimetype system for a corresponding app that can handle video/quicktime. It also asks if the app can handle "Browser/View" embedding. When a pointer to aKtion is returned, it uses X-KDE-Library to tell it that the component it needs to load is 'libaktion'.
|
Visible Result
Practical Matters
If your own application uses a standard automake like the one above, then converting it to a shared library uses exactly the same steps (and code). There is little specific to aKtion in this procedure.
[ Edit ]

