PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Tutorial zu KParts?



TheDodger
12-10-2002, 06:31
Gibt es sowas?

Ich habe zwar eines (KDE2 Programmierung), doch die hören genau da auf, wo es interessant wird und die Beispiele lassen sich z.T. nicht mal kompilieren ... was zeimlich frustrierend ist, wenn man die alle abtippt, weil die nicht mit auf der CD sind ...

Ich will jetzt endlich KParts verstehen! (und nutzen) :)

TheDodger
12-10-2002, 09:01
Also ich geb ja nicht auch ... :D

Ich habe jetzt ein Bespiel gefunden ( hier z.B. (http://phil.freehackers.org/kde/kpart-techno/kpart-techno.html) ) welches ich benuzen möchte ...

Source abgetippt (weil ich z.Z. nur unter Windoof auf'm Notebook surfen kann) und kopiliert ... nach versucht.
Klappt soweit auch alles wunderbar, doch hieran stößt sich der Compilier:



extern "C" {

void *init_libjargo() {

return new JargoFactory;
}
};


Da bekomme ich dann diese Meldung:


cannot allocate on object of type 'JargoFactory'
because the following virtual functions are
abstract:
/usr/kde/3.1/include/klibloader.h:329: virtual QObject*
KLibFactory::createObject( .... )


(sorry, wenn ich nicht alles abtippe :) )

Kann mir jemand sagen, was daran falsch ist?

TheDodger
12-10-2002, 09:43
Ich habe jetzt das virtual QObject* createObject() mit in meine Klasse aufgenommen und siehe da ... gcc hält die Fresse :)

Ist aber schon seltsam ...

anda_skoa
12-10-2002, 11:44
Original geschrieben von TheDodger
Ich habe jetzt das virtual QObject* createObject() mit in meine Klasse aufgenommen und siehe da ... gcc hält die Fresse :)

Ist aber schon seltsam ...

Naja, so seltsam ist das nicht :)
Die Basis Factory ist eben eine abstrakte Klasse und diese Methode ist pure Virtual.
Und von einer abstrakten Klasse kann man nun mal keine Instanz erstellen :)

Das hier ist ein ziemlich aktuelles Tutorial von DAvid Faure:
http://www-106.ibm.com/developerworks/library/l-kparts/

Und noch zwei neuere
http://www-105.ibm.com/developerworks/education.nsf/linux-onlinecourse-bytitle/A96500917FA1DB0786256BC000808C0F?OpenDocument
http://www-105.ibm.com/developerworks/education.nsf/linux-onlinecourse-bytitle/380CD6A86A7ACDBE86256BD50078C711?OpenDocument
die behandlen auch die neuen Factory Macros, die bei KDE3 eingeführt wurden.
Man muß sich dazu bei IBM DeveloperWorks registrieren.

Davids Tutorials sind aber weltklasse.

Ciao,
_

TheDodger
13-10-2002, 06:53
Hmmm ... ich weiß, daß ich bei IBM schon angemeldet bin ... seltsamerweise funktioniert von hier die Anmeldung nicht :(

BTW. ich bin wieder Online! :)
(nachdem mir die Teledumm innerhalb von 4 Tagen mein DSL gekappt hat ... und die NCom 4 Wochen gebraucht hatte, um mich wieder an's Netz zu bringen)

TheDodger
15-10-2002, 05:30
Ich habe mir jetzt eine eigene Factory zusammengebastelt und diese mit in mein Projekt kompiliert.
Soweit war das ja witzig und einfach ... jetzt hab ich aber 'n schwarzes Loch im Kopf ... ich weiß nicht weiter :(
Muß wohl an der Uhrzeit liegen ...

anda_skoa
15-10-2002, 11:33
Die Factory kommt in die Lib deines Kparts, aber vielleicht ist das eh das, weas du gemeint hast :)

Ist dein Part ein spezieller Part, eine eigene Subklasse von KParts::Part oder ein ReadOnly bzw ReadWrite Part und eine Subklasse davon?

Im zweiten Fall ist der ServiceTyp schon festgelegt

Allgemein braucht man einen ServiceType, der durch ein .desltop File in $KDEDIRS/share/servicetypes beschrieben wird.
Jeder Part, der so ein Service implementiert, installiert zusammen mit der lib ein Serivce .desktop, das angibt, welche Services der Part kann.

Das bzw. die benutzenden Programme, benutzen dann KTrader, um eine Listen von Service zu erhalten, die eine bestimmte Query erfüllen (meist ein ServiceType und eventuell noch ein MIME type)

Wenns dazu Fragen gibt, kann ich ein Beispiel posten

Ciao,
_

TheDodger
15-10-2002, 13:53
Original geschrieben von anda_skoa
Die Factory kommt in die Lib deines Kparts, aber vielleicht ist das eh das, weas du gemeint hast :)

eher nein, ich hab die factory in das Programm einkompiliert



Ist dein Part ein spezieller Part, eine eigene Subklasse von KParts::Part oder ein ReadOnly bzw ReadWrite Part und eine Subklasse davon?

im moment (zum testen eine subklasse von ReadWritePart.
Allerdings weis ich nicht, ob das richtig ist.
Meine Parts sollten eigentlich nur von meinem Programm aus sinnvoll genutzt werden können. Wäre es nicht besser, eine Subklasse von KParts::Part abzuleiten?


Wenns dazu Fragen gibt, kann ich ein Beispiel posten

gerne doch :) :)

anda_skoa
15-10-2002, 14:04
Original geschrieben von TheDodger
eher nein, ich hab die factory in das Programm einkompiliert


:)
Ok, aber sie gehört in die Lib.
Das ist nämlich das Symbol, das mit dlsym in der Lib gesucht wird.
Darum auch in extern "C" Klammern.



im moment (zum testen eine subklasse von ReadWritePart.
Allerdings weis ich nicht, ob das richtig ist.
Meine Parts sollten eigentlich nur von meinem Programm aus sinnvoll genutzt werden können. Wäre es nicht besser, eine Subklasse von KParts::Part abzuleiten?


ReadWrite Part oder ReadOnly Part machen nur Sinn, wenn der Part mit einem Document arbeitet, das auf einer URL basiert, also zB im Konqueror als eingebetteter Viewer dienen kann.

Wenn es mehr ein spezielles Plugin für eine Applikation ist, leitet man am besten eine eigene Part Basisklasse ab.

Hat den Vorteil, dass man alle Methoden selber festlegen kann, etc.

Das Beispiel poste ich später, hab gerade nicht so viel Zeit.

Ciao,
_

anda_skoa
15-10-2002, 19:34
Hi!

Ein kleines Beispiel zu KParts

das Interface der speziellen KParts der Beispiel App


class MyPart : public KPart::Part
{
Q_OBJECT
public:
MyPart(QObject* parent, const char* name);
~MyPart();

virtual void setAPI(MyAPI* api) = 0;
virtual void foorBar() = 0;
};


Das Interface, dass die Applikation den Parts gegenüber bietet


class MyAPI
{
public:
virtual QPtrList<MyPart> parts() = 0;
};


Der ServiceType, der mit der Applikation MyApp installiert wird


[Desktop Entry]
Type=ServiceType
X-KDE-ServiceType=MyApp/Part
Name=MyApp KParts


Ein Part


class MyPartImpl : public MyPart
{
Q_OBJECT
public:
MyPartImpl(QObject* parent, const char* name);
¨MyPartImpl(MyAPI* api);

void setAPI(MyAPI* api) {
m_api = api;
}

void fooBar() {
if (m_api == 0) return;
QPtrList<MyPart> parts = m_api->parts();
qDebug("Die Applikation hat gerade %d Parts geladen", parts.count());
}
protected:
MyAPI* m_api;
};


Der Part installiert dann mit seiner lib folgendes .desktop FIle


[Desktop Entry]
Type=Service
Comment=really useful part
Name=MyPart Example Implementation
ServiceTypes=MyApp/Part
X-KDE-Library=libmypartimpl


Hier ist wichtig, das Type=Service ist, dass ServiceTypes den Type enthält, den die Applikation erwartet und dass der Name der Lib korrekt ist (im "modules" Verzeichnis befindet sich dann die Lib libmypartimpl.la)

Die Applikation eght nun so vor


void MyApp::loadParts()
{
KTrader::OfferList offers;
KLibFactory* factory=0;
MyPart* part = 0;

// Query nach Services unseres ServiceTypes
KTrader::OfferList offers = KTrader::self()->query("MyApp/Part");
KLibLoader* loader = KLibLoader::self();

for (uint i = 0; i < offers.count(); ++i)
{
factory = loader->factory(offers[i]->library());
if (factory != 0 && factory->inherits("KParts::Factory"))
{
KParts::Factory* fac = static_cast<KParts::Factory*>(factory);
KParts::Part* p = fac->createPart(this, 0, this);
if (p != 0 && p->inherits("MyPart"))
{
part = static_cast<MyPart*>(p):
part->setAPI(this); // nehmen wir an MyApp implementiert MyAPI selbst
m_parts.append(part); // m_parts sei eine QPtrList<MyPart>
}
}
}
}

QPtrList<MyPart> MyApp::parts()
{
return m_parts;
}

void MyApp::callFooBar()
{
for (uint i = 0; i < m_part.count(); ++i)
{
m_parts.at(i)->fooBar();
}
}


Ein "Real World" Beispiel, das zusätzlich eine spezielle Factory Subklasse benutzt, ist Kmud2
www.kmud.de
Dort werden sowohl Parts, als auch KParts::PLugin verwendet.

Ciao,
_

TheDodger
17-10-2002, 09:21
Danke!

Ich werd's testen, sobald ich wieder etwas Lust habe und es mir etwas besser geht.
Einwas verstehe ich allerdings in deinem Beispiel nicht ganz ...

und zwar ist die myAPI Klasse ...

Versteh ich das so richtig, das in der myAPI Klasse die ganzen Definitionen wi open() close(), save() etc. definiert werden und ich mittels virtula vois setAPI( myAPI* ) quasi diese Definitionen in meine Part Klasse 'hinzulade' und ich dies dort nicht auch komplett angeben muß?

Oder liege ich falsch?

anda_skoa
17-10-2002, 10:33
Die MyAPI Klasse brauchst du nicht unbedingt.
Nur, wenn die Applikation den Parts ein Interface bieten will, das sie benutzen können.

Man kann auch einfach nur mit SIGNAL/SLOT arbeiten, dann muß der Part nix wissen, sondern emittet nur ein signal.
In diesem Fall connectet die Applikation die Sache so wie sie will.
Ist weniger stark gebunden.

Ciao,
_

TheDodger
17-10-2002, 10:36
Mal abgesehen davon ...
Wo kommen eigentlich die ServiceType Dateien hin?
Und die erzeugten (Part)libs?

Mittlwerweile kompiliert das soweit ohne Fehler ... er zeigt mir auch via


qDebug( " ------------------------- " );
for( ; it != offers.end() ; ++it ) {

KService::Ptr ptr = (*it);

qDebug( ptr->name().latin1() );
}
qDebug( " ------------------------- " );


Denn einzigen gefunden Part an, aber ich glaube, das hier läuft nicht so wie es soll:

factory = loader->factory( offers[i]->library() );

denn die nachfolgende if() Schleife wird nicht weiter genutzt ...

anda_skoa
17-10-2002, 19:08
Original geschrieben von TheDodger
Mal abgesehen davon ...
Wo kommen eigentlich die ServiceType Dateien hin?


im Makefile.am sieht das so aus


servicetypedir = $(kde_servicetypesdir)
servicetype_DATA = myservicetype.desktop


der Part


servicedir = $(kde_servicesdir)
service_DATA = mypart.desktop




Und die erzeugten (Part)libs?


Wieder im Makefile.am


kde_module_LTLIBRARIES = libmypart.la
libmypart_la_LDFLAGS = $(all_libraries) -version-info 1:0 $(KDE_PLUGIN)
libmypart_la_LIBADD = eventuelle_teil_libs.la $(LIB_KPARTS)





Denn einzigen gefunden Part an, aber ich glaube, das hier läuft nicht so wie es soll:

factory = loader->factory( offers[i]->library() );

denn die nachfolgende if() Schleife wird nicht weiter genutzt ...

Was sagt er, wenn du aus der Konsole startest und die Debug Areas für Trader und LibLoader aktiviert hast?
(kdebugdialog)

Vielleicht kann das factory symbol nicht gefunden werden oder sie ist keine KLibFactory bzw. Subklasse davon.

Ciao,
_

TheDodger
18-10-2002, 07:48
Original geschrieben von anda_skoa
im Makefile.am sieht das so aus
[...]

ich nutze kein KDevelop, oder automake ich erstelle meine Makefiles via qmake.
Ich habe aber gestern abend noch rausgefunden, was wohin gehört:

$(KDEDIR)/share/services/
$(KDEDIR)/share/servicetypes/



Wieder im Makefile.am


grummel :)

Naja, dann such ich halt.
wie sieht's mit $(KDEDIR)/lib aus ?



Was sagt er, wenn du aus der Konsole startest und die Debug Areas für Trader und LibLoader aktiviert hast?
(kdebugdialog)

Hab ich noch nie mit gearbeitet ...



Vielleicht kann das factory symbol nicht gefunden werden oder sie ist keine KLibFactory bzw. Subklasse davon.


gut möglich ...
mit strace habe ich nicht mal gefunden, daß nach der lib gesucht wird ...

anda_skoa
18-10-2002, 08:36
Original geschrieben von TheDodger
ich nutze kein KDevelop, oder automake ich erstelle meine Makefiles via qmake.
Ich habe aber gestern abend noch rausgefunden, was wohin gehört:


Ah, bei einem KDE Programm bin ich davon ausgegangen, dass du zumindest das autmoake Framework von KDE benutzt.
Ein entsprechendes AppTemplate gibt es im kdesdk Paket.
So mußt du alle Include und Linker Flags selber definieren und das möglichst System unabhängig :(



$(KDEDIR)/share/services/
$(KDEDIR)/share/servicetypes/


Ja, abhängig vom prefix, in dem das Programm installiert wird.
kde-config --paths servicetypes
bzw
kde-config --oaths services
listen alle Verzeichnissse auf, in denen gesicht wird (immer share/services in allen Dirs aus KDEDIRS, etc)

kde-config --install service
etc. sollte ansich den Pfad liefern, wenn mit dem selben Prefix konfiguriert wird, mit dem die KDE Installation konfiguriert wurde.



Naja, dann such ich halt.
wie sieht's mit $(KDEDIR)/lib aus ?


Lib nicht, sondern lib/kde2 bzw lib/kde3
kde-config --paths module



Hab ich noch nie mit gearbeitet ...


Du startest einfach kdebugdialog und kreuzt die Nummern an, deren Output du willst.
zum Beispiel 150 for kdecore (KLibLoader)
Wenn du dann das KDE Programm aus der Konsole startest, dann kommt der entsprechende Debugoutput.

Ciao,
_

TheDodger
18-10-2002, 09:12
Original geschrieben von anda_skoa
Ah, bei einem KDE Programm bin ich davon ausgegangen, dass du zumindest das autmoake Framework von KDE benutzt.
Ein entsprechendes AppTemplate gibt es im kdesdk Paket.
So mußt du alle Include und Linker Flags selber definieren und das möglichst System unabhängig :(

das geht aber ganz gut :)
Ich hab hier auf arbeit ein SuSE7.2 zu Hause eine SuSE8.0 und ein gentoo 1.4 und hab nix in den Project Dateien ändern müssen ...


Ja, abhängig vom prefix, in dem das Programm installiert wird.
kde-config --paths servicetypes



bodo@heino:~/src/jargo/jargo > kde-config --paths servicetypes
kde-config: Unknown option '--paths'.
kde-config: Use --help to get a list of available command line options.

:mad:


Lib nicht, sondern lib/kde2 bzw lib/kde3
kde-config --paths module

s.o. aber schau in den verzeichnissen mal nach ...


Du startest einfach kdebugdialog und kreuzt die Nummern an, deren Output du willst.
zum Beispiel 150 for kdecore (KLibLoader)
Wenn du dann das KDE Programm aus der Konsole startest, dann kommt der entsprechende Debugoutput.

Hab ich getan, aber auf der console habe ich (ausser meinen eigenen Debugausgaben) keine Fehlermeldung erhalten.

anda_skoa
18-10-2002, 09:30
Original geschrieben von TheDodger
das geht aber ganz gut :)
Ich hab hier auf arbeit ein SuSE7.2 zu Hause eine SuSE8.0 und ein gentoo 1.4 und hab nix in den Project Dateien ändern müssen ...


Ich dachte auch mehr an Systeme, bei denen Libraries anderes heißen.
Anderer Unixe zum Beispiel.
Zwei Linux Distributionen sind da ja gleich.



bodo@heino:~/src/jargo/jargo > kde-config --paths servicetypes
kde-config: Unknown option '--paths'.
kde-config: Use --help to get a list of available command line options.


Sorry:
--path

(hint, hint) kde-config --help bzw kde-config --help-all ;)



Hab ich getan, aber auf der console habe ich (ausser meinen eigenen Debugausgaben) keine Fehlermeldung erhalten.
Hmm, komisch.
Vielleicht wurde dein KDE mit --disable-debug kompiliert.
Evetuell probier noch
#> export KDE_DEBUG=1
vor dem Programmstart.

Kannst du debug Output in den Factory Konstructor geben und schauen, ob er ausgeführt wird?

Ciao,
_

TheDodger
18-10-2002, 09:52
Original geschrieben von anda_skoa
Ich dachte auch mehr an Systeme, bei denen Libraries anderes heißen.
Anderer Unixe zum Beispiel.
Zwei Linux Distributionen sind da ja gleich.

im moment denk ich noch nicht mal soweit! :)


Sorry:
--path

(hint, hint) kde-config --help bzw kde-config --help-all ;)

Ich weiß! :)



bodo@heino:~/src/jargo/jargo > kde-config --help
Usage: kde-config [Qt-options] [KDE-options] [options]

A little program to output installation paths

Generic options:
--help Show help about options
--help-qt Show Qt specific options
--help-kde Show KDE specific options
--help-all Show all options
--author Show author information
-v, --version Show version information
--license Show license information
-- End of options

Options:
--expandvars expand ${prefix} and ${exec_prefix} in output
--prefix Compiled in prefix for KDE libraries
--exec-prefix Compiled in exec_prefix for KDE libraries
--localprefix Prefix in $HOME used to write files
--version Compiled in version string for KDE libraries
--types Available KDE resource types
--path type Search path for resource type
--userpath type User path: desktop|autostart|trash|document
--install type Prefix to install resource files to


da steht nur nix mit path usw.



Hmm, komisch.
Vielleicht wurde dein KDE mit --disable-debug kompiliert.
Evetuell probier noch
#> export KDE_DEBUG=1
vor dem Programmstart.

also hier habe ich die original SuSE rpm's installiert ....
Beim gentoo System ... bin ich mir nicht sicher ...

Ich probiers einfach mal.


Kannst du debug Output in den Factory Konstructor geben und schauen, ob er ausgeführt wird?

er kompiliert grad ... :)

TheDodger
18-10-2002, 10:39
[QUOTE]Original geschrieben von anda_skoa

Kannst du debug Output in den Factory Konstructor geben und schauen, ob er ausgeführt wird?
[quote]

Der Konstuctor wird überhaupt nicht aufgerufen ... ???

anda_skoa
18-10-2002, 10:58
Hmm, sehr eigenartig.

Heißt die Funktion richitg, die im extern "C" Block steht.
init_libname
wenn das lib File libname heißt?
Steht der Name auch im service.desktop?

Ciao,
_

TheDodger
18-10-2002, 14:35
Ich glaube, ich fang da noch mal von vorn an zu programmieren ...

(Ich hatte bislang nur die KLibFactory genutzt ...)

BTW.noch mal für dumme, die Factory ... muß ich für jedes Plugin eine schreiben? Denke mal nicht.
Bislang habe ich die Factory in mein Programm kompiliert und nicht in die plugins ...

Ich denke mal, der Fehler liegt bei mir, weil ich da einiges noch nicht richtig verstanden habe ... :mad: :mad:

anda_skoa
18-10-2002, 16:33
Eine Factory pro Plugin lib.

Der LibLoader lädt die Pluginlibrary mit dlopen.
Wenn man KLibLoader->factory() macht, wird das Symbol init_libname geholt und ausgeführt, dann der resultieren void* Pointer auf KLibFactory gecastet und zurück gegeben.

Wenn man für alle Plugins eine gemeinsame BasisFactory gemacht hat, von denen die einzelnene Factories der Plugins ableiten, dann kann man jetzt auf diese BasisFactory casten.

Wenn jede Pluginfactory direkt von KlibFactory ableitet, dann benutzt man hier eben das KLibFactory Interface.

Zusammenfassend:
In jeder Pluginbibliothek ist eine direkte oder indirekte Klasse von KLibFactory.
Diese Klasse wird bei init_libname instanziert und zurückgeliefert.
Das ist dann die Instanz, die bei KLibLoader::factory() als Returnwert kommt.

Ciao,
_

TheDodger
19-10-2002, 07:07
Oooohhhhhhhh, dann habe ich hier einiges missverstanden! :(
Ich bin immer davon ausgegangen, das die Factory so eine Art Plugin-aufrufende Klasse sei und diese somit nur einmal vorhanden sein muß!

Danke nochmals!!!

anda_skoa
19-10-2002, 14:16
Original geschrieben von TheDodger
Oooohhhhhhhh, dann habe ich hier einiges missverstanden! :(
Ich bin immer davon ausgegangen, das die Factory so eine Art Plugin-aufrufende Klasse sei und diese somit nur einmal vorhanden sein muß!


Ansich hast du schon recht.
Die Factory ist im allgemeine immer die Klasse, die die Plugins erzeugt.
Tut sie eigentlich auch in diesem Fall, die Plugininstanz wird ja von der Factory erzeugt.

Man könnte das sicher auch so lösen (wenn man nciht KLibLoader verwendet), dass man eine Factory im Programm hat, die dann den Namen des plugins bekommt und so das extern C Symbol zusammen baut, das dann direkt das Plugin erzeugt.

Der Nachteil dabei ist, dass man dem Pluginkonstruktor dann keine Parameter übergeben kann und man immer nur ein Plugin pro lib haben kann, oder man für jedes Plugin in der lib eine dlsym machen muß.
(Außerdem muß die Factory dann rigendwie wissen, ob sie für eine Anfrage iene neu Lib laden muß, oder ab es mit der schon geladenen auch geht)

So gesehen ist der Ansatz der kdelib hier mit einer zweistufigen Factory flexibler, aber auch ein bischen verwirrender.
Die erste Factory ist KLIbLoader, die zweite Factory ist dann die KLibFactory Subklasse.

Ciao,
_

TheDodger
19-10-2002, 15:03
Bin grad dabei den code umzustricken ...

TheDodger
20-10-2002, 08:56
Hmm ... irgendwie funktioniert das wohl doch nicht mit qmake ...
Ich kann über qmake static & shared libs erzeugen. Klappt auch wunderbar.
Dabei kommen dann lib mit *.so oder *.a Endung heraus.
Der KLibLoader will aber libs mit der Endung *.la haben.
Wenn ich meine *.a jetzt nach *.la umbenenne, habe ich einen crash. :(

Aber bis dahin bin ich nun schonmal gekommen :)

anda_skoa
20-10-2002, 10:47
Hmm, vielleicht gibt es da noch einen Lib typ.
Oder man braucht spezielle Flags, um aus einem .so oder .a ein .la zu machen.

Ciao,
_

TheDodger
20-10-2002, 11:51
Hmm ... ich habe nicht's weiter gefunden, als staticlib (*.a) sharedlib( *.so) plugin(*.so)
Was anderes bietet mir qmake nicht. :(

Jedenfalls steigt er hier aus:

factory = KLibLoader::self()->factory( svcptr->library() );

Ich habe in den Konstruktor meiner Factory ein qDebug eingebaut, aber das wird schon nicht mehr ausgeführt.

*grummel*

Ich bin sooo dicht dran ...

anda_skoa
20-10-2002, 13:01
Ich hab jetzt was rausgefunden :)

Die Plugins sind .so Files.
Die .la Files sind nut Textdateien, eine Art Beschreibungdatei.

Schau dir mal eine auf deinem System an.

Ciao,
_

TheDodger
20-10-2002, 13:15
Original geschrieben von anda_skoa
Ich hab jetzt was rausgefunden :)

Die Plugins sind .so Files.
Die .la Files sind nut Textdateien, eine Art Beschreibungdatei.

Schau dir mal eine auf deinem System an.


Richtig, danke für den Tip!

Die *.la Dateien werden von einem schript names ltmain.sh erzeugt ... ich versuche das mal mit Hand nachzuvollziehen ...

TheDodger
20-10-2002, 17:32
Ich habe gerade eben 2 Stunden vergeblich versucht, mein Projekt in KDevelop zu übernehmen ... ich wusste schon, weshalb ich das nicht nehmen wollte ... :-(

Ich habe mir jetzt von Hand eine *.la Datei erzeugt und schon stürtzt das Programm erstmal nicht ab :) dafür landet er woanders ...



if( factory == 0L ) {

kdDebug( ) << "Could not create a factory for KTrader's offer!" << endl;
part = 0L;
}

anda_skoa
20-10-2002, 18:20
Ich benutze KDevelop auch nur zum Programmieren und zum Generieren des Grundframeworks.
Ab dann mache ich das Ändern der Makefile.am, etc händisch.

Im kdesdk Paket gibt es auch eine autocont/-make framework, das sogenannte kapptemplate.

Aber ich hatte auch mit dem von KDevelop noch nie Schwierigkeiten.

Ciao,
_

TheDodger
20-10-2002, 19:52
Nun, mein Projekt ist mittlerweile etwas umfangreich geworden.
Eigene Designer Widgets, eigene Projektlib, das Projekt an sich und jetzt noch die Parts.
ich bekam meine Schwierigkeiten, da mir KDevelop nicht alles in ein einziges Projekt packen konnte.
Beim einbinden der Designer Widgets hab ich es nicht hinbekommen, das er mir eine *.so Biblothek erzeugt und diese auch an die richtige Stelle kopiert. Und da habe ich ständig in den Makefile.am rumgefummelt. Sobald ich aber ein automake/autoconf aufgerufen hatte, das KDevelop mit da seine Vorgaben wieder mit untergejubelt. Meine Einträge waren zwar noch da, doch beim anschließenden configure bekam ich dann die ersten Fehler.

Beim erzeugen meiner Projekt-Lib ein ähnliches Problem ... keine shared Lib ...

Beim Projekt hab ich dann die Schnauze gestrichen voll gehabt und aufgegeben.

Es ist schon etwas schwieriger, ein bestehendes Projekt komplett in eine IDE reinzuverfrachten. Ich hab's heut nicht geschafft.
Vielleicht, wenn ich ganz von vorn begonnen hätte ...

anda_skoa
20-10-2002, 20:05
Wenn ich ein externes Prog übernehme, mach ich das immer so:
KDE Mini Projekt erstellen, so dass Programmname, etc passt.
Wenn ich Unterverzeichnisse mit libs habe, leg ich die auch an.
KDevelop generiert für alle Verzeichnisse Makefile.am usw.

Dann in den Projekt Optionen, das automaitsche Makefilegenerieren abschalten, Projekt schließen.
Dann make distclean.

Alle file in die richtigen Verzeichnisse kopieren.
Die Makefile.am Dateien in allen Verzeichnissen anpassen.
Meist muß man eh nur die Zeilen für Sources erweitern (ui gelten da auch als source).

Wenn man dann ohne KDevelop weiterarbeiten will, braucht man nichts mehr zu tun.
make -f Makefile.dist
./configure

Wenn man mit KDevelop arbeiten will, muß man das Projekt öffnen und im tab Files alle Dateien hinzufügen, die Klassen enthalten, die man im Classbroser haben nöchte.

Die ersten paar Mal ist das Syntax der Makefile.am noch bischen kompliziert, aber das lernt man schon.
Wenn man mal nicht weiterkommt, kann man in einem Dummy Projekt die enstprechende Regel von KDevelop generieren lassen und dann nachsehen.

Kann sein, dass es mit dem kapptemplaet aus kdesdk in weniger Schritten geht, hab ich noch nie probiert.
Vorallem weil ich auch KDevelop verwenden möchte und dadurch nur einen Nachteil hätte.

Ciao,
_

TheDodger
21-10-2002, 05:15
Da sitz ich gestern vor meinem Notebook (SuSE8.0) und bekomme keinerlei Fehlermeldung und heute morgen, gentoo1.4 selber Code dieses hier:


kdecore (KLibLoader): WARNING: library=libjargoadmin: file=/home/dodger/.kde3.1/lib/libjargoadmin.la: /home/dodger/.kde3.1/lib/libjargoadmin.so: undefined symbol: _ZTI9JargoPart
jargo: Could not create a factory for KTrader's offer! 'libjargoadmin'

Na bitte, mit sowas kann ich doch was anfangen :D

TheDodger
24-10-2002, 17:05
*schlonk*
Soweit klappt alles. Das Plugin wird erkannt und auch korrekt geladen und dargestellt.
Aber wie kriege ich es jetzt so hin, das ich die Funktionen in den Plugins nutzen kann?

Alles Plugins basieren auf eine Klasse JargoPlugin. Alle sollen davon abgeleitet werden.
In meinem Pluginloader läd diese Funktion mein Plugin:


factory = KLibLoader::self()->factory( ((ModulItem*)lastItem)->library );

if( factory == 0L ) {

kdDebug( ) << "Could not create a factory for KTrader's offer!" << endl;
part = 0L;
} else {

factory->setName( "JargoFactory" );

KParts::Factory* fac = static_cast<KParts::Factory*>( factory );

part = static_cast<JargoPart*>( fac->createPart( workSpace, 0, this ) );


part wurde im Headerfile als 'JargoPart* part' angelegt.

JargoPart besitzt eine virtuelle void Function names dump(), welche eigentlich nur, mittels qDebug(), etwas ausgeben soll.
Diese Funktion ist im Plugin komplett ausgecodet.

Wenn ich jetzt die Funktion mit

part->dump();

aufrufe stürtzt der ganze Kram ab :(

Ich denke mal, das der Aufruf der Funktion gar nicht richtig sein kann, aber wie dann richtig?

anda_skoa
24-10-2002, 17:19
Hmm, sieht für mich richtig aus.

JargoPart ist JargoPlugin von weiter oben?

Kannst du in deiner Factory einen Debug output machen?
Vielleicht klappt was bei der Erzeugung nicht.

Oder du gibts im Part Konstruktor den Wert von this aus und im Programm den Wert von part und vergleichst dann.

Ciao,
_

TheDodger
25-10-2002, 05:02
Original geschrieben von anda_skoa
Hmm, sieht für mich richtig aus.

JargoPart ist JargoPlugin von weiter oben?

Nicht ganz.

Ungefähr so aufgebaut.
Jargo == Application
JargoPart == allgem. Part

Jargo<Name>Part == PluginPart
Jargo<Name>Factory == PluginFactory

Jargo<Name>Part wird abgeleitet von JargoPart.
Und die Jargo<Name>Factory direkt von der KLibFactory.



Kannst du in deiner Factory einen Debug output machen?


Die Factory wird korrekt erzeugt, aber die dump() Funktion dort wird nicht aufgerufen.
Muß ich diese auch public static machen wie aboutData()?
... selbst dann klappt's nicht.



Oder du gibts im Part Konstruktor den Wert von this aus und im Programm den Wert von part und vergleichst dann.



Debug : Jargo::createJargoPlugin( QListViewItem* item )
Requesting factory for service Jargo/Part
Debug : JargoAdminFactory::JargoAdminFactory()
Got factory (0x811afb0). Creating KPart...
Debug : JargoAdminFactory::create
Debug : JargoPart::JargoPart
Debug : -> 'workSpace'
Debug : AdminPart::AdminPart
Debug : -> 'workSpace'
Debug : JargoAdminFactory::instance()
Debug : JargoAdminFactory::aboutData()
Debug : Jargo::slotNewRecord()

nach slotNewRecord() müsste mein dump() kommen ...
:(
Also irgendwie kommt der mit dem 'JargoPart* part' nicht so klar :(

TheDodger
25-10-2002, 06:18
Nachdem ich _jede_ Funktion mit qDebug()'s gespickt habe (wat für 'ne Arbeit) bin ich fast draufgekommen.
In der loadPlugin() Funktion, die mir meine Plugins erzeugt, stand nodh 'JargoPart* part = 0;' :(
Na toll ... scheiß Fehler!
Nach 'part = 0;' geändert und schwupps .. klappt es.

Aber ich denke, es ist nicht die letzte Frage zu diesem Thema ... :D

anda_skoa
25-10-2002, 09:18
So eine lokale Deklaration hab ich auch mal gehabt.
Fand ich damals selber nicht, das hat erst ein anderer rausgefunden.

Fein, dass es jetzt klappt :)

Ciao,
_

TheDodger
25-10-2002, 10:05
Find ich auch! :)

Derzeit arbeite ich am löschen eines einzelnen Parts ... Der Part wird auch schon gelöscht, aber mit der Factory gibt es noch kleinere Probleme

anda_skoa
25-10-2002, 10:16
Vielleicht hilft ein KLibray::unload()

Ciao,
_

TheDodger
25-10-2002, 17:36
Ja, denn hier wird zumindest der Destruktor aufgerufen.
Allerdings klappt ein erneutes Aufrufen nicht mehr ganz. Die Konstruktoren werden zwar aufgerufen, aber mein CustomWidget wird nicht mehr dargestellt ...

anda_skoa
25-10-2002, 17:59
Wenn du unload machst, mußt du die lib neu laden.

Ciao,
_

TheDodger
25-10-2002, 18:18
Iss klar :)

Das ganze sieht jetzt ungefähr so aus: (Nicht erschrecken, da ist bestimmt einiges dabei, was dir bekannt vorkommt! :D )


// Query nach Services unseres ServiceTypes
offers = KTrader::self()->query( s );

qDebug("Requesting factory for service " + s );

svcptr = offers.first();

if( part != 0L ) {

qDebug( "... deleting old part ..." );
delete part;
part = 0L;

qDebug( "... unloading library ..." );
library->unload();

qDebug( "... done ..." );
}


part = 0L;
factory = 0L;

if( svcptr == 0L ) {

kdDebug() << "No offers for service " << s << endl;
kdDebug() << "This might be caused by an incomplete installation," << endl;
kdDebug() << "or by KDE not recognizing the new services." << endl;

factory = 0L;

} else {

library = KLibLoader::self()->library( ((ModulItem*)lastItem)->library );

if( !library ) {

qDebug( "Could not create a KLibrary" );
return;
}

factory = library->factory();//KLibLoader::self()->factory( ((ModulItem*)lastItem)->library );//svcptr->library() );

if( factory == 0L ) {

qDebug( "Could not create a factory for KTrader's offer!" );

library->unload();
part = 0L;
} else {

factory->setName( "JargoFactory" );

kdDebug( ) << "Got factory (" << factory << "). Creating KPart..." << endl;


KParts::Factory* fac = static_cast<KParts::Factory*>( factory );

part = static_cast<JargoPart*>( fac->createPart( workSpace, "name", this ) );
}
}

anda_skoa
25-10-2002, 18:28
Ah, bin ich blind oder wo benutzt du svcptr?

Btw, wenn du eine eigene Factory Basisklasse hast, von denen die einzelnen PartFactories ableiten, kannst du auch auf die casten :)
Und dort zB eine spezielle create Methode haben.
Ganz praktisch, wenn man den eigenen Parts spezielle Parameter an den Konstruktor übergeben will.

Ciao,
_

TheDodger
25-10-2002, 18:56
okay, der Rest noch obendrüber :


QString s = "Jargo/Part";

KTrader::OfferList offers;
KService::Ptr svcptr = 0L;

// Query nach Services unseres ServiceTypes
offers = KTrader::self()->query( s );

kdDebug( "Requesting factory for service " + s );

svcptr = offers.first();

if( part != 0L ) {

qDebug( "... deleting old part ..." );
delete part;


.
.
.


Ja, ich dachte mich das schon mit einr eigenen BasisFactory, doch noch habe ich keine Verwendung dafür, oder sehe sie nicht.

anda_skoa
25-10-2002, 19:17
Original geschrieben von TheDodger
okay, der Rest noch obendrüber :


Ja, das konnte ich mir schon vorstellen :)
Ich meinte, weite unten kommt er nicht mehr vor.
Du machst nur query, nimmst das erste Angebot, kontrllierst ob != 0 und aus.

Ciao,
_

TheDodger
25-10-2002, 20:10
Ja und? :confused:
Muss da noch was folgen?

Ich mein ... in kmud ist das doch auch so ...

anda_skoa
25-10-2002, 22:14
Nein, wir benutzen den Pointer dann:


factory = KLibLoader::self()->factory(svcptr->library());


Ciao,
_

TheDodger
26-10-2002, 04:48
Richtig, ich habe das in der zwischenzeit (wegen library->unload() ) etwas anders gemacht.


library = KLibLoader::self()->library( libName );

if( !library ) {

qDebug( "Could not create a KLibrary" );
return;
}

factory = library->factory();


Okay, ich habe jetzt alles was 'KService::Ptr', 'KTrader', 'offers' & 'svcptr' betrifft auskommentiert.
Läuft auch (was erzeugt man doch für Overhead ...)
Aber ändert nichts an meinem Problem, daß das Plugin zwar erzeugt, aber nicht dargestellt wird :(

anda_skoa
26-10-2002, 11:15
Hmm, blöde Frage, aber hast du schon show() am Widget des Parts probiert?

Ciao,
_

TheDodger
26-10-2002, 12:21
Du weist, das ich blöd bin, oder? :mad:

Ohne Scheiß ... ich hatte es nicht da stehen ... warum auch, beim ersten mal Anzeigen klappte es ja auch ohne show()!

BTW. wo muß ich jetzt eigentlcih meine signals unterbringen?
Im JargoPart(), oder Jargo<PluginName>Part() ?

Ach was, ich probiers ... ich kann ja weiter fragen, wenn's nicht funktioniert :)

TheDodger
26-10-2002, 16:31
es klappt, es klappt *freu* *freu*