This forum has been archived. All content is frozen. Please use KDE Discuss instead.

KParts in Kimono

Tags: None
(comma "," separated)
Way Walker
Registered Member
Posts
17
Karma
0
OS

KParts in Kimono

Sat Jan 15, 2011 2:38 am
I've been meaning to learn C# and the Qt/KDE API so I thought I'd play around with the Kimono bindings. I'm having some trouble reproducing the KParts tutorial at http://techbase.kde.org/Development/Tutorials/Using_KParts. I translated the line:

KService::Ptr service = KService::serviceByDesktopPath("katepart.desktop");

as:

KService service = KService.ServiceByDesktopPath("katepart.desktop");

which crashes at runtime with the message:

Cannot handle 'KSharedPtr<KService>' as return-type of KService::serviceByDesktopPath

Is it possible to use KParts with the Kimono binding? Also, functions like CreatePartInstanceFromQuery() don't appear to be implemented.


Also, is there any way to give a different application name? For example, when I pass the --help option, the usage note says "kde-dotnet.dll" instead of whatever I pass to KAboutData.
pumphaus
Registered Member
Posts
3
Karma
0
OS

Re: KParts in Kimono

Sat Jan 15, 2011 4:10 pm
Ah sorry, this type must've slipped through. I've committed a fix to master and the 4.6 branch, so it should be in 4.6.0.
What currently does work though is the KService::List or QList<KSharedPtr<KService> > types. So you could use KServiceTypeTrader.Self().Query() to get a list of matches and then user KService.CreateInstance<T>() to create an instance from that.

The CreateInstanceFromQuery() methods are not implemented because they are template methods (which are a pain to wrap) and you can easily work around them by first using KServiceTypeTrader.Query() and then KService.CreateInstance() as described above.

Hope this helps :)
Way Walker
Registered Member
Posts
17
Karma
0
OS

Re: KParts in Kimono

Sat Jan 15, 2011 11:47 pm
Thanks for the help!

I can imagine the problems templates cause with bindings. Using KServiceTypeTrader.Self().Query() is working fine till 4.6 comes out, but it revealed another problem. If Smoke doesn't know about a derived class does it try to use the nearest base class in the hierarchy? It looks like, instead of creating a KateFactory object, the bindings are trying to create an instance of the abstract class KParts.Factory.

Code: Select all
Unhandled Exception: System.MemberAccessException: Cannot create an instance of KParts.Factory because it is an abstract class
  at System.Reflection.MonoCMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00000] in <filename unknown>:0
  at System.Reflection.MonoCMethod.Invoke (BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00000] in <filename unknown>:0
  at System.Reflection.ConstructorInfo.Invoke (System.Object[] parameters) [0x00000] in <filename unknown>:0
  at Qyoto.SmokeMarshallers.CreateInstance (System.String className, IntPtr smokeObjectPtr) [0x00000] in <filename unknown>:0
  at (wrapper native-to-managed) Qyoto.SmokeMarshallers:CreateInstance (intptr,intptr)
  at (wrapper managed-to-native) Qyoto.SmokeInvocation:CallSmokeMethod (intptr,int,intptr,intptr,int)
  at Qyoto.SmokeInvocation.Invoke (System.String mungedName, System.String signature, System.Type returnType, System.Object[] args) [0x00000] in <filename unknown>:0
  at Kimono.KPluginLoader.Factory () [0x00000] in <filename unknown>:0
  at Kimono.KService.CreateInstance[ReadWritePart] (Qyoto.QWidget parentWidget, Qyoto.QObject parent, System.Collections.Generic.List`1 args, System.String& error) [0x00000] in <filename unknown>:0
  at Kimono.KService.CreateInstance[ReadWritePart] (Qyoto.QObject parent, System.Collections.Generic.List`1 args, System.String& error) [0x00000] in <filename unknown>:0
  at Kimono.KService.CreateInstance[ReadWritePart] (Qyoto.QObject parent, System.Collections.Generic.List`1 args) [0x00000] in <filename unknown>:0
  at Kimono.KService.CreateInstance[ReadWritePart] (Qyoto.QObject parent) [0x00000] in <filename unknown>:0
  at Kimono.KService.CreateInstance[ReadWritePart] () [0x00000] in <filename unknown>:0
  at KPartTutorial1.MainWindow..ctor () [0x00000] in <filename unknown>:0
  at KPartTutorial1.KPartTutorial1.Main (System.String[] args) [0x00000] in <filename unknown>:0
pumphaus
Registered Member
Posts
3
Karma
0
OS

Re: KParts in Kimono

Sun Jan 16, 2011 12:47 pm
Yes, this is what the bindings do. I don't know if KateFactory is public or not, but often there are completely private implementations of a class returned from such a method, so we have to fall back to the return type.

I don't think this can be worked around currently :(
If you post your code or a small test case exhibiting this behaviour, I can fix it in time for 4.6. though.
Way Walker
Registered Member
Posts
17
Karma
0
OS

Re: KParts in Kimono

Sun Jan 16, 2011 9:53 pm
The code I had was essentially what's in http://techbase.kde.org/Development/Tutorials/Using_KParts translated to C#. There's not much fat to trim, but a slightly slimmer version would be:
Code: Select all
using System;
using System.Collections.Generic;

using Kimono;


class KPartsExample : KParts.MainWindow {


protected KParts.ReadWritePart part;


public KPartsExample() : base() {
   List<KService> service = KServiceTypeTrader.Self().Query(
      "KParts/ReadWritePart", "'katepart' == DesktopEntryName");
   if (service == null) { throw new Exception("Could not find katepart"); }

   part = service[0].CreateInstance<KParts.ReadWritePart>();
   if (part == null) { throw new Exception("Could not create katepart"); }

   SetCentralWidget(part.Widget());
   SetupGUI();
}


static int Main(String[] args) {
   KAboutData aboutData = new KAboutData(
      "kpartsexample", "",
      KDE.Ki18n("KParts Example"), "1.0",
      KDE.Ki18n(
         "Example where the Kimono bindings try to create an instance of " +
         "the abstract class KParts.Factory"),
      KAboutData.LicenseKey.License_BSD,
      KDE.Ki18n("copyright 2011"));
   KCmdLineArgs.Init(args, aboutData);

   new KApplication();

   KPartsExample mainWindow = new KPartsExample();
   mainWindow.Show();

   return KApplication.Exec();
}


}


which, at the line:
part = service[0].CreateInstance<KParts.ReadWritePart>();
produces the same error I posted before.

I've never worked on bindings before, so I'm curious what the best solution is in a case like this. Are changes like making KParts.Factory concrete typical?
Way Walker
Registered Member
Posts
17
Karma
0
OS

Re: KParts in Kimono

Thu Jan 27, 2011 12:57 am
I just tried running
Code: Select all
using System;
using Kimono;
class KPartsExample {
static int Main(String[] args) {
   KService service = KService.ServiceByDesktopPath("katepart.desktop");
   if (service != null) {
      KParts.ReadWritePart part =
         service.CreateInstance<KParts.ReadWritePart>();
   }
   return 0;
}
}

and it looks like the KService marshaller is working fine, but it still gives the error for trying to create an instance of KParts.Factory. Is there anything I can do to help it happen for 4.6.1?


Bookmarks



Who is online

Registered users: bartoloni, Bing [Bot], Evergrowing, Google [Bot], ourcraft